summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLutz Bichler <Lutz.Bichler@bmw.de>2020-02-12 13:04:15 +0100
committerLutz Bichler <Lutz.Bichler@bmw.de>2020-02-12 13:04:15 +0100
commit8371cdca9463a75220c4de92b47c8df9d3bbe346 (patch)
tree16b4bf73c284b026b0ac032171110dafd1752196
parentee44d19e0a3773adcda3bace073c66e334a3e6a7 (diff)
downloadvSomeIP-8371cdca9463a75220c4de92b47c8df9d3bbe346.tar.gz
vsomeip 3.1.7.13.1.7.1
-rw-r--r--Android.bp146
-rw-r--r--CHANGES134
-rw-r--r--CMakeLists.txt390
-rw-r--r--README.md43
-rw-r--r--config/vsomeip-tcp-client-security.json10
-rw-r--r--config/vsomeip-tcp-client.json10
-rw-r--r--config/vsomeip-udp-client-security.json10
-rw-r--r--config/vsomeip-udp-client.json10
-rw-r--r--daemon/CMakeLists.txt17
-rw-r--r--documentation/vsomeipUserGuide611
-rw-r--r--examples/CMakeLists.txt74
-rw-r--r--examples/hello_world/CMakeLists.txt6
-rw-r--r--examples/hello_world/hello_world_client.cpp2
-rw-r--r--examples/hello_world/hello_world_service.cpp2
-rw-r--r--examples/notify-sample.cpp37
-rw-r--r--examples/request-sample.cpp2
-rw-r--r--examples/response-sample.cpp4
-rw-r--r--examples/routingmanagerd/CMakeLists.txt24
-rw-r--r--examples/routingmanagerd/routingmanagerd.cpp (renamed from daemon/vsomeipd.cpp)54
-rw-r--r--examples/subscribe-sample.cpp6
-rw-r--r--exportmap.gcc98
-rw-r--r--implementation/compat/logging/include/logger.hpp28
-rw-r--r--implementation/compat/logging/include/logger_impl.hpp33
-rw-r--r--implementation/compat/logging/src/logger.cpp16
-rw-r--r--implementation/compat/logging/src/logger_impl.cpp30
-rw-r--r--implementation/compat/message/include/message_base_impl.hpp82
-rw-r--r--implementation/compat/message/include/message_impl.hpp37
-rw-r--r--implementation/compat/message/include/payload_impl.hpp45
-rw-r--r--implementation/compat/message/src/message_base_impl.cpp166
-rw-r--r--implementation/compat/message/src/message_impl.cpp56
-rw-r--r--implementation/compat/message/src/payload_impl.cpp95
-rw-r--r--implementation/compat/runtime/include/application_impl.hpp202
-rw-r--r--implementation/compat/runtime/include/runtime_impl.hpp58
-rw-r--r--implementation/compat/runtime/src/application_impl.cpp649
-rw-r--r--implementation/compat/runtime/src/runtime.cpp29
-rw-r--r--implementation/compat/runtime/src/runtime_impl.cpp125
-rw-r--r--implementation/configuration/include/client.hpp10
-rw-r--r--implementation/configuration/include/configuration.hpp109
-rw-r--r--implementation/configuration/include/configuration_element.hpp26
-rw-r--r--implementation/configuration/include/configuration_impl.hpp266
-rw-r--r--implementation/configuration/include/configuration_plugin.hpp26
-rw-r--r--implementation/configuration/include/configuration_plugin_impl.hpp42
-rw-r--r--implementation/configuration/include/debounce.hpp10
-rw-r--r--implementation/configuration/include/e2e.hpp40
-rw-r--r--implementation/configuration/include/event.hpp18
-rw-r--r--implementation/configuration/include/eventgroup.hpp10
-rw-r--r--implementation/configuration/include/internal.hpp.in101
-rw-r--r--implementation/configuration/include/internal_android.hpp206
-rw-r--r--implementation/configuration/include/service.hpp20
-rw-r--r--implementation/configuration/include/service_instance_range.hpp12
-rw-r--r--implementation/configuration/include/trace.hpp12
-rw-r--r--implementation/configuration/include/watchdog.hpp10
-rw-r--r--implementation/configuration/src/configuration_impl.cpp2156
-rw-r--r--implementation/configuration/src/configuration_plugin_impl.cpp52
-rw-r--r--implementation/e2e_protection/include/buffer/buffer.hpp10
-rw-r--r--implementation/e2e_protection/include/crc/crc.hpp10
-rw-r--r--implementation/e2e_protection/include/e2e/profile/e2e_provider.hpp36
-rw-r--r--implementation/e2e_protection/include/e2e/profile/e2e_provider_impl.hpp67
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp12
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp10
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp10
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp19
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp10
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp12
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp12
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp14
-rw-r--r--implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp10
-rw-r--r--implementation/e2e_protection/include/e2exf/config.hpp10
-rw-r--r--implementation/e2e_protection/src/buffer/buffer.cpp4
-rw-r--r--implementation/e2e_protection/src/crc/crc.cpp4
-rw-r--r--implementation/e2e_protection/src/e2e/profile/e2e_provider_impl.cpp122
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp8
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp6
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp6
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp8
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp6
-rw-r--r--implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp5
-rw-r--r--implementation/e2e_protection/src/e2exf/config.cpp4
-rw-r--r--implementation/endpoints/include/buffer.hpp52
-rw-r--r--implementation/endpoints/include/client_endpoint.hpp8
-rw-r--r--implementation/endpoints/include/client_endpoint_impl.hpp271
-rw-r--r--implementation/endpoints/include/credentials.hpp10
-rw-r--r--implementation/endpoints/include/endpoint.hpp135
-rw-r--r--implementation/endpoints/include/endpoint_definition.hpp10
-rw-r--r--implementation/endpoints/include/endpoint_host.hpp31
-rw-r--r--implementation/endpoints/include/endpoint_impl.hpp205
-rw-r--r--implementation/endpoints/include/endpoint_manager_base.hpp82
-rw-r--r--implementation/endpoints/include/endpoint_manager_impl.hpp133
-rw-r--r--implementation/endpoints/include/local_client_endpoint_impl.hpp34
-rw-r--r--implementation/endpoints/include/local_server_endpoint_impl.hpp102
-rw-r--r--implementation/endpoints/include/netlink_connector.hpp22
-rw-r--r--implementation/endpoints/include/server_endpoint_impl.hpp209
-rw-r--r--implementation/endpoints/include/tcp_client_endpoint_impl.hpp199
-rw-r--r--implementation/endpoints/include/tcp_server_endpoint_impl.hpp300
-rw-r--r--implementation/endpoints/include/tp.hpp60
-rw-r--r--implementation/endpoints/include/tp_message.hpp62
-rw-r--r--implementation/endpoints/include/tp_reassembler.hpp58
-rw-r--r--implementation/endpoints/include/udp_client_endpoint_impl.hpp140
-rw-r--r--implementation/endpoints/include/udp_server_endpoint_impl.hpp204
-rw-r--r--implementation/endpoints/include/virtual_server_endpoint_impl.hpp34
-rw-r--r--implementation/endpoints/src/client_endpoint_impl.cpp1181
-rw-r--r--implementation/endpoints/src/credentials.cpp12
-rw-r--r--implementation/endpoints/src/endpoint_definition.cpp4
-rw-r--r--implementation/endpoints/src/endpoint_impl.cpp295
-rw-r--r--implementation/endpoints/src/endpoint_manager_base.cpp233
-rw-r--r--implementation/endpoints/src/endpoint_manager_impl.cpp1034
-rw-r--r--implementation/endpoints/src/local_client_endpoint_impl.cpp739
-rw-r--r--implementation/endpoints/src/local_server_endpoint_impl.cpp836
-rw-r--r--implementation/endpoints/src/netlink_connector.cpp37
-rw-r--r--implementation/endpoints/src/server_endpoint_impl.cpp1102
-rw-r--r--implementation/endpoints/src/tcp_client_endpoint_impl.cpp1706
-rw-r--r--implementation/endpoints/src/tcp_server_endpoint_impl.cpp202
-rw-r--r--implementation/endpoints/src/tp.cpp77
-rw-r--r--implementation/endpoints/src/tp_message.cpp352
-rw-r--r--implementation/endpoints/src/tp_reassembler.cpp202
-rw-r--r--implementation/endpoints/src/udp_client_endpoint_impl.cpp807
-rw-r--r--implementation/endpoints/src/udp_server_endpoint_impl.cpp492
-rw-r--r--implementation/endpoints/src/virtual_server_endpoint_impl.cpp58
-rw-r--r--implementation/helper/1.55/boost/asio/basic_datagram_socket_ext.hpp (renamed from implementation/helper/boost/asio/basic_datagram_socket_ext.hpp)1908
-rw-r--r--implementation/helper/1.55/boost/asio/basic_socket_acceptor_ext.hpp1139
-rw-r--r--implementation/helper/1.55/boost/asio/basic_stream_socket_ext.hpp855
-rw-r--r--implementation/helper/1.55/boost/asio/datagram_socket_service_ext.hpp (renamed from implementation/helper/boost/asio/datagram_socket_service_ext.hpp)874
-rw-r--r--implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext.hpp (renamed from implementation/helper/boost/asio/detail/handler_type_requirements_ext.hpp)1040
-rw-r--r--implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext_local.hpp536
-rw-r--r--implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp (renamed from implementation/helper/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp)540
-rw-r--r--implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp270
-rw-r--r--implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext.ipp (renamed from implementation/helper/boost/asio/detail/impl/socket_ops_ext.ipp)420
-rw-r--r--implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext_local.ipp302
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactive_socket_recv_op_ext.hpp)252
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp126
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp)272
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp136
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp)256
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp128
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactive_socket_service_base_ext.hpp)910
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext_local.hpp454
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactive_socket_service_ext.hpp)924
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext_local.hpp462
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactor_op_ext.hpp (renamed from implementation/helper/boost/asio/detail/reactor_op_ext.hpp)84
-rw-r--r--implementation/helper/1.55/boost/asio/detail/reactor_op_ext_local.hpp43
-rw-r--r--implementation/helper/1.55/boost/asio/detail/socket_ops_ext.hpp (renamed from implementation/helper/boost/asio/detail/socket_ops_ext.hpp)124
-rw-r--r--implementation/helper/1.55/boost/asio/detail/socket_ops_ext_local.hpp72
-rw-r--r--implementation/helper/1.55/boost/asio/ip/udp_ext.hpp (renamed from implementation/helper/boost/asio/ip/udp_ext.hpp)230
-rw-r--r--implementation/helper/1.55/boost/asio/local/stream_protocol_ext.hpp93
-rw-r--r--implementation/helper/1.55/boost/asio/socket_acceptor_service_ext.hpp305
-rw-r--r--implementation/helper/1.55/boost/asio/stream_socket_service_ext.hpp379
-rw-r--r--implementation/helper/1.66/boost/asio/basic_datagram_socket_ext.hpp1043
-rw-r--r--implementation/helper/1.66/boost/asio/basic_socket_acceptor_ext.hpp1989
-rw-r--r--implementation/helper/1.66/boost/asio/basic_socket_ext.hpp1760
-rw-r--r--implementation/helper/1.66/boost/asio/basic_socket_ext_local.hpp1760
-rw-r--r--implementation/helper/1.66/boost/asio/basic_stream_socket_ext.hpp924
-rw-r--r--implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext.hpp565
-rw-r--r--implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext_local.hpp592
-rw-r--r--implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp302
-rw-r--r--implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp302
-rw-r--r--implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext.ipp210
-rw-r--r--implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext_local.ipp302
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext.hpp138
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp138
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp141
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp141
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp135
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp135
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext.hpp517
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext_local.hpp514
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext.hpp531
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext_local.hpp529
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactor_op_ext.hpp42
-rw-r--r--implementation/helper/1.66/boost/asio/detail/reactor_op_ext_local.hpp47
-rw-r--r--implementation/helper/1.66/boost/asio/detail/socket_ops_ext.hpp62
-rw-r--r--implementation/helper/1.66/boost/asio/detail/socket_ops_ext_local.hpp95
-rw-r--r--implementation/helper/1.66/boost/asio/ip/udp_ext.hpp115
-rw-r--r--implementation/helper/1.66/boost/asio/local/stream_protocol_ext.hpp93
-rw-r--r--implementation/helper/1.66/boost/asio/stream_socket_service_ext.hpp415
-rw-r--r--implementation/helper/1.70/boost/asio/basic_datagram_socket_ext.hpp1118
-rw-r--r--implementation/helper/1.70/boost/asio/basic_socket_acceptor_ext.hpp2381
-rw-r--r--implementation/helper/1.70/boost/asio/basic_socket_ext.hpp1859
-rw-r--r--implementation/helper/1.70/boost/asio/basic_socket_ext_local.hpp1859
-rw-r--r--implementation/helper/1.70/boost/asio/basic_stream_socket_ext.hpp996
-rw-r--r--implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext.hpp586
-rw-r--r--implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext_local.hpp588
-rw-r--r--implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp302
-rw-r--r--implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp302
-rw-r--r--implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext.ipp210
-rw-r--r--implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext_local.ipp303
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext.hpp140
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp140
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp145
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp145
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp138
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp138
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext.hpp521
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext_local.hpp521
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext.hpp508
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext_local.hpp508
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactor_op_ext.hpp42
-rw-r--r--implementation/helper/1.70/boost/asio/detail/reactor_op_ext_local.hpp43
-rw-r--r--implementation/helper/1.70/boost/asio/detail/socket_ops_ext.hpp62
-rw-r--r--implementation/helper/1.70/boost/asio/detail/socket_ops_ext_local.hpp95
-rw-r--r--implementation/helper/1.70/boost/asio/ip/udp_ext.hpp115
-rw-r--r--implementation/helper/1.70/boost/asio/local/stream_protocol_ext.hpp93
-rw-r--r--implementation/logging/include/android_sink_backend.hpp33
-rw-r--r--implementation/logging/include/defines.hpp3
-rw-r--r--implementation/logging/include/dlt_sink_backend.hpp11
-rw-r--r--implementation/logging/include/logger_impl.hpp147
-rw-r--r--implementation/logging/src/android_sink_backend.cpp66
-rw-r--r--implementation/logging/src/dlt_sink_backend.cpp4
-rw-r--r--implementation/logging/src/logger.cpp28
-rw-r--r--implementation/logging/src/logger_impl.cpp402
-rw-r--r--implementation/message/include/deserializer.hpp136
-rw-r--r--implementation/message/include/message_base_impl.hpp150
-rw-r--r--implementation/message/include/message_header_impl.hpp94
-rw-r--r--implementation/message/include/message_impl.hpp114
-rw-r--r--implementation/message/include/payload_impl.hpp92
-rw-r--r--implementation/message/include/serializer.hpp100
-rw-r--r--implementation/message/src/deserializer.cpp472
-rw-r--r--implementation/message/src/message_base_impl.cpp253
-rw-r--r--implementation/message/src/message_header_impl.cpp160
-rw-r--r--implementation/message/src/message_impl.cpp134
-rw-r--r--implementation/message/src/payload_impl.cpp158
-rw-r--r--implementation/message/src/serializer.cpp244
-rw-r--r--implementation/plugin/include/plugin_manager.hpp53
-rw-r--r--implementation/plugin/include/plugin_manager_impl.hpp58
-rw-r--r--implementation/plugin/src/plugin_manager.cpp204
-rw-r--r--implementation/plugin/src/plugin_manager_impl.cpp216
-rw-r--r--implementation/routing/include/event.hpp83
-rw-r--r--implementation/routing/include/eventgroupinfo.hpp123
-rw-r--r--implementation/routing/include/function_types.hpp19
-rw-r--r--implementation/routing/include/remote_subscription.hpp129
-rw-r--r--implementation/routing/include/routing_host.hpp44
-rw-r--r--implementation/routing/include/routing_manager.hpp61
-rw-r--r--implementation/routing/include/routing_manager_adapter.hpp10
-rw-r--r--implementation/routing/include/routing_manager_base.hpp191
-rw-r--r--implementation/routing/include/routing_manager_host.hpp22
-rw-r--r--implementation/routing/include/routing_manager_impl.hpp360
-rw-r--r--implementation/routing/include/routing_manager_proxy.hpp133
-rw-r--r--implementation/routing/include/routing_manager_stub.hpp54
-rw-r--r--implementation/routing/include/routing_manager_stub_host.hpp60
-rw-r--r--implementation/routing/include/serviceinfo.hpp21
-rw-r--r--implementation/routing/include/types.hpp94
-rw-r--r--implementation/routing/src/event.cpp151
-rw-r--r--implementation/routing/src/eventgroupinfo.cpp486
-rw-r--r--implementation/routing/src/remote_subscription.cpp315
-rw-r--r--implementation/routing/src/routing_manager_base.cpp472
-rw-r--r--implementation/routing/src/routing_manager_impl.cpp3714
-rw-r--r--implementation/routing/src/routing_manager_proxy.cpp756
-rw-r--r--implementation/routing/src/routing_manager_stub.cpp561
-rw-r--r--implementation/routing/src/serviceinfo.cpp24
-rw-r--r--implementation/runtime/include/application_impl.hpp128
-rw-r--r--implementation/runtime/include/runtime_impl.hpp12
-rw-r--r--implementation/runtime/src/application_impl.cpp591
-rw-r--r--implementation/runtime/src/error.cpp14
-rw-r--r--implementation/runtime/src/runtime.cpp4
-rw-r--r--implementation/runtime/src/runtime_impl.cpp8
-rw-r--r--implementation/security/include/policy.hpp (renamed from implementation/configuration/include/policy.hpp)15
-rw-r--r--implementation/security/include/policy_manager_impl.hpp43
-rw-r--r--implementation/security/include/security.hpp56
-rw-r--r--implementation/security/include/security_impl.hpp122
-rw-r--r--implementation/security/src/policy_manager.cpp17
-rw-r--r--implementation/security/src/policy_manager_impl.cpp111
-rw-r--r--implementation/security/src/security.cpp15
-rw-r--r--implementation/security/src/security_impl.cpp1631
-rw-r--r--implementation/service_discovery/include/configuration_option_impl.hpp93
-rw-r--r--implementation/service_discovery/include/constants.hpp12
-rw-r--r--implementation/service_discovery/include/defines.hpp9
-rwxr-xr-ximplementation/service_discovery/include/deserializer.hpp61
-rwxr-xr-ximplementation/service_discovery/include/entry_impl.hpp162
-rw-r--r--implementation/service_discovery/include/enumeration_types.hpp11
-rwxr-xr-ximplementation/service_discovery/include/eventgroupentry_impl.hpp141
-rw-r--r--implementation/service_discovery/include/ip_option_impl.hpp23
-rw-r--r--implementation/service_discovery/include/ipv4_option_impl.hpp78
-rw-r--r--implementation/service_discovery/include/ipv6_option_impl.hpp78
-rwxr-xr-ximplementation/service_discovery/include/load_balancing_option_impl.hpp78
-rwxr-xr-ximplementation/service_discovery/include/message_element_impl.hpp57
-rwxr-xr-ximplementation/service_discovery/include/message_impl.hpp254
-rw-r--r--implementation/service_discovery/include/option_impl.hpp94
-rw-r--r--implementation/service_discovery/include/primitive_types.hpp12
-rwxr-xr-ximplementation/service_discovery/include/protection_option_impl.hpp77
-rw-r--r--implementation/service_discovery/include/remote_subscription_ack.hpp64
-rw-r--r--implementation/service_discovery/include/request.hpp12
-rw-r--r--implementation/service_discovery/include/runtime.hpp74
-rw-r--r--implementation/service_discovery/include/runtime_impl.hpp14
-rw-r--r--implementation/service_discovery/include/selective_option_impl.hpp46
-rw-r--r--implementation/service_discovery/include/service_discovery.hpp37
-rw-r--r--implementation/service_discovery/include/service_discovery_host.hpp54
-rw-r--r--implementation/service_discovery/include/service_discovery_impl.hpp300
-rw-r--r--implementation/service_discovery/include/serviceentry_impl.hpp64
-rw-r--r--implementation/service_discovery/include/subscription.hpp60
-rwxr-xr-ximplementation/service_discovery/src/configuration_option_impl.cpp259
-rw-r--r--implementation/service_discovery/src/deserializer.cpp82
-rwxr-xr-ximplementation/service_discovery/src/entry_impl.cpp384
-rwxr-xr-ximplementation/service_discovery/src/eventgroupentry_impl.cpp474
-rw-r--r--implementation/service_discovery/src/ip_option_impl.cpp33
-rw-r--r--implementation/service_discovery/src/ipv4_option_impl.cpp164
-rwxr-xr-ximplementation/service_discovery/src/ipv6_option_impl.cpp166
-rwxr-xr-ximplementation/service_discovery/src/load_balancing_option_impl.cpp147
-rwxr-xr-ximplementation/service_discovery/src/message_element_impl.cpp48
-rwxr-xr-ximplementation/service_discovery/src/message_impl.cpp873
-rwxr-xr-ximplementation/service_discovery/src/option_impl.cpp141
-rwxr-xr-ximplementation/service_discovery/src/protection_option_impl.cpp147
-rw-r--r--implementation/service_discovery/src/remote_subscription_ack.cpp92
-rw-r--r--implementation/service_discovery/src/request.cpp4
-rw-r--r--implementation/service_discovery/src/runtime_impl.cpp29
-rwxr-xr-ximplementation/service_discovery/src/selective_option_impl.cpp86
-rw-r--r--implementation/service_discovery/src/service_discovery_impl.cpp3719
-rwxr-xr-ximplementation/service_discovery/src/serviceentry_impl.cpp120
-rw-r--r--implementation/service_discovery/src/subscription.cpp93
-rw-r--r--implementation/tracing/include/channel_impl.hpp12
-rw-r--r--implementation/tracing/include/connector_impl.hpp15
-rw-r--r--implementation/tracing/include/defines.hpp10
-rw-r--r--implementation/tracing/include/enumeration_types.hpp10
-rw-r--r--implementation/tracing/include/header.hpp10
-rw-r--r--implementation/tracing/src/channel_impl.cpp8
-rw-r--r--implementation/tracing/src/connector_impl.cpp10
-rw-r--r--implementation/tracing/src/header.cpp8
-rw-r--r--implementation/utility/include/byteorder.hpp116
-rw-r--r--implementation/utility/include/criticalsection.hpp10
-rw-r--r--implementation/utility/include/utility.hpp74
-rw-r--r--implementation/utility/src/criticalsection.cpp4
-rw-r--r--implementation/utility/src/utility.cpp1193
-rw-r--r--interface/compat/vsomeip/application.hpp1093
-rw-r--r--interface/compat/vsomeip/constants.hpp63
-rw-r--r--interface/compat/vsomeip/defines.hpp41
-rw-r--r--interface/compat/vsomeip/enumeration_types.hpp81
-rw-r--r--interface/compat/vsomeip/error.hpp26
-rw-r--r--interface/compat/vsomeip/export.hpp30
-rw-r--r--interface/compat/vsomeip/function_types.hpp22
-rw-r--r--interface/compat/vsomeip/handler.hpp72
-rw-r--r--interface/compat/vsomeip/internal/deserializable.hpp24
-rw-r--r--interface/compat/vsomeip/internal/serializable.hpp30
-rw-r--r--interface/compat/vsomeip/message.hpp52
-rw-r--r--interface/compat/vsomeip/message_base.hpp211
-rw-r--r--interface/compat/vsomeip/payload.hpp105
-rw-r--r--interface/compat/vsomeip/plugin.hpp89
-rw-r--r--interface/compat/vsomeip/plugins/application_plugin.hpp42
-rw-r--r--interface/compat/vsomeip/plugins/pre_configuration_plugin.hpp29
-rw-r--r--interface/compat/vsomeip/primitive_types.hpp66
-rw-r--r--interface/compat/vsomeip/runtime.hpp216
-rw-r--r--interface/compat/vsomeip/trace.hpp218
-rw-r--r--interface/compat/vsomeip/vsomeip.hpp21
-rw-r--r--interface/vsomeip/application.hpp479
-rw-r--r--interface/vsomeip/constants.hpp17
-rw-r--r--interface/vsomeip/defines.hpp6
-rw-r--r--interface/vsomeip/enumeration_types.hpp38
-rw-r--r--interface/vsomeip/error.hpp10
-rw-r--r--interface/vsomeip/export.hpp6
-rw-r--r--interface/vsomeip/function_types.hpp10
-rw-r--r--interface/vsomeip/handler.hpp32
-rw-r--r--interface/vsomeip/internal/deserializable.hpp48
-rw-r--r--interface/vsomeip/internal/logger.hpp (renamed from implementation/logging/include/logger.hpp)99
-rw-r--r--interface/vsomeip/internal/policy_manager.hpp38
-rw-r--r--interface/vsomeip/internal/serializable.hpp60
-rw-r--r--interface/vsomeip/message.hpp35
-rw-r--r--interface/vsomeip/message_base.hpp412
-rw-r--r--interface/vsomeip/payload.hpp212
-rw-r--r--interface/vsomeip/plugin.hpp14
-rw-r--r--interface/vsomeip/plugins/application_plugin.hpp10
-rw-r--r--interface/vsomeip/plugins/pre_configuration_plugin.hpp11
-rw-r--r--interface/vsomeip/primitive_types.hpp25
-rw-r--r--interface/vsomeip/runtime.hpp10
-rw-r--r--interface/vsomeip/trace.hpp51
-rw-r--r--interface/vsomeip/vsomeip.hpp2
-rw-r--r--test/CMakeLists.txt1015
-rw-r--r--test/application_tests/application_test.cpp35
-rw-r--r--test/application_tests/application_test_client.cpp8
-rw-r--r--test/application_tests/application_test_client_availability.cpp2
-rw-r--r--test/application_tests/application_test_daemon.cpp2
-rw-r--r--test/application_tests/application_test_service.cpp8
-rw-r--r--test/application_tests/application_test_single_process.cpp6
-rwxr-xr-xtest/application_tests/application_test_starter.sh6
-rw-r--r--test/application_tests/conf/application_test_daemon.json.in2
-rw-r--r--test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in2
-rw-r--r--test/big_payload_tests/big_payload_test_client.cpp32
-rw-r--r--test/big_payload_tests/big_payload_test_client.hpp3
-rwxr-xr-xtest/big_payload_tests/big_payload_test_external_starter.sh26
-rw-r--r--test/big_payload_tests/big_payload_test_globals.hpp3
-rw-r--r--test/big_payload_tests/big_payload_test_local.json6
-rw-r--r--test/big_payload_tests/big_payload_test_local_limited.json6
-rw-r--r--test/big_payload_tests/big_payload_test_local_queue_limited.json8
-rw-r--r--test/big_payload_tests/big_payload_test_local_random.json4
-rw-r--r--test/big_payload_tests/big_payload_test_service.cpp148
-rw-r--r--test/big_payload_tests/big_payload_test_service.hpp4
-rwxr-xr-xtest/big_payload_tests/big_payload_test_service_external_start.sh6
-rw-r--r--test/big_payload_tests/big_payload_test_udp_client.json44
-rw-r--r--test/big_payload_tests/big_payload_test_udp_service.json41
-rw-r--r--test/big_payload_tests/conf/big_payload_test_udp_client.json.in44
-rw-r--r--test/big_payload_tests/conf/big_payload_test_udp_service.json.in41
-rwxr-xr-xtest/client_id_tests/client_id_test_master_starter.sh9
-rw-r--r--test/client_id_tests/client_id_test_service.cpp4
-rw-r--r--test/client_id_tests/client_id_test_utility.cpp658
-rw-r--r--test/client_id_tests/client_id_test_utility.json2
-rw-r--r--test/client_id_tests/client_id_test_utility_discontinuous_masked_511.json2
-rw-r--r--test/client_id_tests/client_id_test_utility_masked_127.json2
-rw-r--r--test/client_id_tests/client_id_test_utility_masked_4095.json4
-rw-r--r--test/client_id_tests/client_id_test_utility_masked_511.json4
-rw-r--r--test/configuration_tests/configuration-test-deprecated.json30
-rw-r--r--test/configuration_tests/configuration-test.cpp211
-rw-r--r--test/configuration_tests/configuration-test.json42
-rw-r--r--test/cpu_load_tests/conf/cpu_load_test_client_master.json.in6
-rw-r--r--test/cpu_load_tests/conf/cpu_load_test_client_slave.json.in6
-rw-r--r--test/cpu_load_tests/conf/cpu_load_test_service_master.json.in7
-rw-r--r--test/cpu_load_tests/conf/cpu_load_test_service_slave.json.in7
-rw-r--r--test/cpu_load_tests/cpu_load_measurer.cpp3
-rw-r--r--test/cpu_load_tests/cpu_load_test_client.cpp10
-rwxr-xr-xtest/cpu_load_tests/cpu_load_test_master_starter.sh9
-rw-r--r--test/cpu_load_tests/cpu_load_test_service.cpp6
-rw-r--r--test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_client.cpp748
-rw-r--r--test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp39
-rwxr-xr-xtest/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_master_starter.sh70
-rw-r--r--test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_service.cpp184
-rwxr-xr-xtest/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_slave_starter.sh33
-rw-r--r--test/e2e_tests/e2e_test_client.cpp16
-rwxr-xr-xtest/e2e_tests/e2e_test_external_master_start.sh2
-rw-r--r--test/e2e_tests/e2e_test_service.cpp12
-rw-r--r--test/event_tests/conf/event_test_master.json.in2
-rw-r--r--test/event_tests/conf/event_test_slave_tcp.json.in2
-rw-r--r--test/event_tests/conf/event_test_slave_udp.json.in2
-rw-r--r--test/event_tests/event_test_client.cpp8
-rwxr-xr-xtest/event_tests/event_test_master_starter.sh4
-rw-r--r--test/event_tests/event_test_service.cpp13
-rwxr-xr-xtest/event_tests/event_test_slave_starter.sh2
-rw-r--r--test/header_factory_tests/header_factory_test_client.cpp3
-rw-r--r--test/header_factory_tests/header_factory_test_client.hpp2
-rw-r--r--test/header_factory_tests/header_factory_test_service.cpp2
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_tcp.json.in93
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_udp.json.in (renamed from test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_master.json.in)41
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_tcp.json.in93
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_udp.json.in67
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_tcp.json.in93
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_udp.json.in66
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_tcp.json.in93
-rw-r--r--test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_udp.json.in67
-rw-r--r--test/initial_event_tests/initial_event_test_availability_checker.cpp4
-rw-r--r--test/initial_event_tests/initial_event_test_client.cpp102
-rw-r--r--test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_master_udp.json66
-rw-r--r--test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_slave_udp.json67
-rw-r--r--test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_master_udp.json66
-rw-r--r--test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_slave_udp.json67
-rwxr-xr-xtest/initial_event_tests/initial_event_test_master_starter.sh49
-rw-r--r--test/initial_event_tests/initial_event_test_service.cpp11
-rwxr-xr-xtest/initial_event_tests/initial_event_test_slave_starter.sh35
-rw-r--r--test/initial_event_tests/initial_event_test_stop_service.cpp14
-rw-r--r--test/magic_cookies_tests/magic_cookies_test_client.cpp38
-rw-r--r--test/magic_cookies_tests/magic_cookies_test_service.cpp4
-rwxr-xr-xtest/magic_cookies_tests/magic_cookies_test_starter.sh4
-rw-r--r--test/malicious_data_tests/conf/malicious_data_test_master.json.in2
-rwxr-xr-xtest/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in13
-rw-r--r--test/malicious_data_tests/malicious_data_test_msg_sender.cpp19
-rw-r--r--test/malicious_data_tests/malicious_data_test_service.cpp7
-rw-r--r--test/npdu_tests/conf/npdu_test_client_no_npdu.json.in39
-rw-r--r--test/npdu_tests/conf/npdu_test_client_npdu.json.in167
-rw-r--r--test/npdu_tests/conf/npdu_test_service_no_npdu.json.in87
-rw-r--r--test/npdu_tests/conf/npdu_test_service_npdu.json.in168
-rw-r--r--test/npdu_tests/npdu_test_client.cpp599
-rw-r--r--test/npdu_tests/npdu_test_client.hpp103
-rw-r--r--test/npdu_tests/npdu_test_client_no_npdu.json39
-rwxr-xr-xtest/npdu_tests/npdu_test_client_no_npdu_start.sh82
-rw-r--r--test/npdu_tests/npdu_test_client_npdu.json167
-rwxr-xr-xtest/npdu_tests/npdu_test_client_npdu_start.sh75
-rw-r--r--test/npdu_tests/npdu_test_globals.hpp45
-rw-r--r--test/npdu_tests/npdu_test_rmd.cpp160
-rw-r--r--test/npdu_tests/npdu_test_rmd.hpp (renamed from test/security_config_plugin_tests/security_config_plugin_test_service.hpp)30
-rw-r--r--test/npdu_tests/npdu_test_service.cpp306
-rw-r--r--test/npdu_tests/npdu_test_service.hpp64
-rw-r--r--test/npdu_tests/npdu_test_service_no_npdu.json87
-rwxr-xr-xtest/npdu_tests/npdu_test_service_no_npdu_start.sh64
-rw-r--r--test/npdu_tests/npdu_test_service_npdu.json168
-rwxr-xr-xtest/npdu_tests/npdu_test_service_npdu_start.sh64
-rwxr-xr-xtest/npdu_tests/npdu_test_starter.sh96
-rw-r--r--test/offer_tests/conf/offer_test_big_sd_msg_master.json.in2
-rwxr-xr-xtest/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in13
-rw-r--r--test/offer_tests/conf/offer_test_big_sd_msg_slave.json.in2
-rw-r--r--test/offer_tests/conf/offer_test_external_master.json.in2
-rwxr-xr-xtest/offer_tests/conf/offer_test_external_master_starter.sh.in26
-rw-r--r--test/offer_tests/conf/offer_test_external_slave.json.in2
-rw-r--r--test/offer_tests/offer_test_big_sd_msg_client.cpp24
-rw-r--r--test/offer_tests/offer_test_big_sd_msg_service.cpp53
-rwxr-xr-xtest/offer_tests/offer_test_big_sd_msg_slave_starter.sh2
-rw-r--r--test/offer_tests/offer_test_client.cpp24
-rwxr-xr-xtest/offer_tests/offer_test_external_slave_starter.sh2
-rw-r--r--test/offer_tests/offer_test_local.json2
-rwxr-xr-xtest/offer_tests/offer_test_local_starter.sh8
-rw-r--r--test/offer_tests/offer_test_service.cpp12
-rw-r--r--test/offer_tests/offer_test_service_external.cpp8
-rw-r--r--test/offered_services_info_test/offered_services_info_test_client.cpp13
-rw-r--r--test/offered_services_info_test/offered_services_info_test_local.json22
-rwxr-xr-xtest/offered_services_info_test/offered_services_info_test_local_starter.sh4
-rw-r--r--test/offered_services_info_test/offered_services_info_test_service.cpp16
-rw-r--r--test/payload_tests/conf/external_local_payload_test_client_external.json.in7
-rw-r--r--test/payload_tests/conf/external_local_payload_test_client_local.json.in7
-rw-r--r--test/payload_tests/conf/external_local_payload_test_service.json.in7
-rwxr-xr-xtest/payload_tests/external_local_payload_test_client_external_starter.sh9
-rwxr-xr-xtest/payload_tests/external_local_payload_test_client_local_and_external_starter.sh9
-rw-r--r--test/payload_tests/payload_test_client.cpp10
-rw-r--r--test/payload_tests/payload_test_service.cpp9
-rw-r--r--test/payload_tests/payload_test_service.hpp4
-rw-r--r--test/pending_subscription_tests/conf/pending_subscription_test_master.json.in15
-rwxr-xr-xtest/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in13
-rw-r--r--test/pending_subscription_tests/pending_subscription_test_sd_msg_sender.cpp1305
-rw-r--r--test/pending_subscription_tests/pending_subscription_test_service.cpp34
-rw-r--r--test/readme.txt51
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.cpp15
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.hpp2
-rw-r--r--test/restart_routing_tests/restart_routing_test_client.json2
-rw-r--r--test/restart_routing_tests/restart_routing_test_service.cpp2
-rw-r--r--test/restart_routing_tests/restart_routing_test_service.json4
-rwxr-xr-xtest/restart_routing_tests/restart_routing_test_starter.sh24
-rwxr-xr-xtest/routing_tests/conf/local_routing_test_starter.sh.in2
-rw-r--r--test/routing_tests/external_local_routing_test_service.cpp2
-rwxr-xr-xtest/routing_tests/external_local_routing_test_starter.sh9
-rw-r--r--test/routing_tests/local_routing_test_client.cpp3
-rw-r--r--test/routing_tests/local_routing_test_client.hpp1
-rw-r--r--test/routing_tests/local_routing_test_client.json2
-rw-r--r--test/routing_tests/local_routing_test_service.cpp2
-rw-r--r--test/routing_tests/local_routing_test_service.json2
-rw-r--r--test/second_address_tests/conf/second_address_test_master_client.json.in (renamed from test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_slave.json.in)17
-rw-r--r--test/second_address_tests/conf/second_address_test_master_service_udp.json.in40
-rw-r--r--test/second_address_tests/conf/second_address_test_slave_client.json.in32
-rw-r--r--test/second_address_tests/conf/second_address_test_slave_service_udp.json.in40
-rwxr-xr-xtest/second_address_tests/conf/second_address_test_slave_starter.sh.in60
-rw-r--r--test/second_address_tests/second_address_test_client.cpp353
-rw-r--r--test/second_address_tests/second_address_test_globals.hpp29
-rwxr-xr-xtest/second_address_tests/second_address_test_master_starter.sh77
-rw-r--r--test/second_address_tests/second_address_test_service.cpp252
-rw-r--r--test/security_config_plugin_tests/conf/security_config_plugin_test_local.json.in128
-rwxr-xr-xtest/security_config_plugin_tests/security_config_plugin_test_client.cpp1045
-rwxr-xr-xtest/security_config_plugin_tests/security_config_plugin_test_globals.hpp37
-rwxr-xr-xtest/security_config_plugin_tests/security_config_plugin_test_local_starter.sh65
-rw-r--r--test/security_config_plugin_tests/security_config_plugin_test_service.cpp222
-rw-r--r--test/security_tests/conf/security_test_config_client_external_allow.json.in4
-rw-r--r--test/security_tests/conf/security_test_config_client_external_deny.json.in4
-rw-r--r--test/security_tests/conf/security_test_config_service_external_allow.json.in4
-rw-r--r--test/security_tests/conf/security_test_config_service_external_deny.json.in4
-rw-r--r--test/security_tests/conf/security_test_local_config.json.in4
-rw-r--r--test/security_tests/security_test_client.cpp16
-rwxr-xr-xtest/security_tests/security_test_external_master_start.sh6
-rwxr-xr-xtest/security_tests/security_test_external_slave_start.sh4
-rwxr-xr-xtest/security_tests/security_test_local_start.sh4
-rw-r--r--test/security_tests/security_test_service.cpp10
-rw-r--r--test/someip_test_globals.hpp3
-rw-r--r--test/someip_tp_tests/conf/someip_tp_test_master.json.in45
-rwxr-xr-xtest/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in65
-rw-r--r--test/someip_tp_tests/someip_tp_test_globals.hpp40
-rw-r--r--test/someip_tp_tests/someip_tp_test_master.json45
-rwxr-xr-xtest/someip_tp_tests/someip_tp_test_master_starter.sh65
-rw-r--r--test/someip_tp_tests/someip_tp_test_msg_sender.cpp1387
-rw-r--r--test/someip_tp_tests/someip_tp_test_service.cpp412
-rwxr-xr-xtest/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh54
-rw-r--r--test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp97
-rwxr-xr-xtest/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh34
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_tcp.json.in33
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json.in61
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json.in (renamed from test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in)21
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json.in (renamed from test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in)21
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_tcp.json.in33
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json.in61
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_tcp.json.in33
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json.in61
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_tcp.json.in33
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json.in61
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in2
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in2
-rw-r--r--test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in2
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json61
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json61
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json61
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json61
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json61
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json61
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_master_starter.sh54
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp27
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh11
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp27
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh2
-rw-r--r--test/subscribe_notify_tests/subscribe_notify_test_service.cpp83
-rwxr-xr-xtest/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh37
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/vsomeip_ctrl.cpp10
-rw-r--r--vsomeip.pc.in4
-rw-r--r--vsomeip3.pc.in11
-rw-r--r--vsomeip3Config.cmake.in19
-rw-r--r--vsomeip3ConfigVersion.cmake.in11
-rw-r--r--vsomeipConfig.cmake.in34
-rw-r--r--vsomeipConfigVersion.cmake.in22
584 files changed, 74565 insertions, 28316 deletions
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..a297c32
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,146 @@
+libvsomeip_srcs = [
+ "implementation/endpoints/**/*.cpp",
+ "implementation/logging/**/*.cpp",
+ "implementation/tracing/**/*.cpp",
+ "implementation/message/**/*.cpp",
+ "implementation/routing/**/*.cpp",
+ "implementation/runtime/**/*.cpp",
+ "implementation/utility/**/*.cpp",
+ "implementation/plugin/**/*.cpp",
+ "implementation/security/**/*.cpp",
+]
+
+libvsomeip_cfg_srcs = [
+ "implementation/configuration/src/*.cpp",
+]
+
+libvsomeip_e2e_srcs = [
+ "implementation/e2e_protection/src/*.cpp",
+]
+
+libvsomeip_sd_srcs = [
+ "implementation/service_discovery/src/*.cpp",
+]
+
+cc_defaults {
+ name: "vsomeip_defaults",
+ cppflags: [
+ "-std=c++11",
+ "-fexceptions",
+ "-Wno-non-virtual-dtor",
+ "-Wno-unused-const-variable",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-lambda-capture",
+ "-Wno-unused-variable",
+ "-Wno-sign-compare",
+ "-Wno-format",
+ "-Wno-header-guard",
+ "-Wno-overloaded-virtual"
+ ]
+}
+
+cc_library_shared {
+ name: "libvsomeip",
+ vendor: true,
+
+ srcs: libvsomeip_srcs,
+
+ defaults: [
+ "vsomeip_defaults"
+ ],
+
+ cflags: [
+ "-DWITHOUT_SYSTEMD"
+ ],
+
+ rtti: true,
+
+ local_include_dirs: [
+ "interface",
+ "implementation/helper/1.66"
+ ],
+
+ export_include_dirs: [
+ "interface"
+ ],
+
+ shared_libs: [
+ "libboost_log",
+ "libboost_system",
+ "libboost_thread",
+ "libboost_filesystem",
+ "liblog",
+ "libutils"
+ ]
+}
+
+cc_library_shared {
+ name: "libvsomeip_cfg",
+ vendor: true,
+
+ srcs: libvsomeip_cfg_srcs,
+
+ defaults: [
+ "vsomeip_defaults"
+ ],
+
+ rtti: true,
+
+ local_include_dirs: [
+ "interface",
+ "implementation/helper/1.66"
+ ],
+
+ shared_libs: [
+ "libvsomeip",
+ "libboost_log",
+ "libboost_filesystem"
+ ]
+}
+
+cc_library_shared {
+ name: "libvsomeip_e2e",
+ vendor: true,
+
+ srcs: libvsomeip_e2e_srcs,
+
+ defaults: [
+ "vsomeip_defaults"
+ ],
+
+ rtti: true,
+
+ local_include_dirs: [
+ "interface",
+ "implementation/helper/1.66"
+ ],
+
+ shared_libs: [
+ "libvsomeip",
+ "libboost_log"
+ ]
+}
+
+cc_library_shared {
+ name: "libvsomeip_sd",
+ vendor: true,
+
+ srcs: libvsomeip_sd_srcs,
+
+ defaults: [
+ "vsomeip_defaults"
+ ],
+
+ rtti: true,
+
+ local_include_dirs: [
+ "interface",
+ "implementation/helper/1.66"
+ ],
+
+ shared_libs: [
+ "libvsomeip",
+ "libboost_log"
+ ]
+}
diff --git a/CHANGES b/CHANGES
index e978854..896c0e2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,17 +1,113 @@
Changes
=======
+v3.1.7
+- Fix stop subscribes when a service is released
+- Improve handling of time stamps when processing subscriptions
+- Log queued data instead of socket fill levels
+- Ensure all shutdown steps are executed (even in case of exceptions)
+
+v3.1.6
+- Fix possible busy loop when expiring subscriptions
+- Use set of serializers to avoid deadlock situation
+- Improve client identifier handling
+ - Check whether corresponding socket is available
+ - Implement retry if a client identifier cannot be used
+- Log buffer fill levels if they exceed a configurable threshold (default=67%).
+
+v3.1.5
+- Ensure subscriptions to remote services are correctly reset when
+ services are no longer available.
+- Fix race condition when inserting new subscriptions.
+- Fix accessing of security module during library shutdown.
+
+v3.1.4
+- Ensure to only mark remote services offered via UDP and TCP as
+ available when both endpoints are marked as connected to prevent TCP
+ connection restarting by the service discovery.
+- Fix possible deadlock when expiring a remote subscription and
+ sending the corresponding event at the same time.
+- Fix nullptr access in service discovery when receiving a
+ subscription for an unknown eventgroup.
+- Add new cmake variables DEFAULT_CONFIGURATION_FOLDER and
+ DEFAULT_CONFIGURATION_FILE which can be used to change the default
+ configuration folder and file at compile time (see vsomeipUserGuide
+ for more information)
+- Fix race condition leading to not accepting service offers from
+ a local client when the same service was offered and stop offered in
+ a high frequency
+
+v3.1.3
+- Set client ID to 0x0 for SOME/IP SD messages
+
+v3.1.2
+- Fix bug in vSomeIP 2 compatibility layer which lead to offering
+ selective events as normal events in conjunction with
+ CommonAPI-SomeIP mainloop integration when a proxy was build to a
+ stub through the same CommonAPI connection ID in the same binary.
+
+v3.1.1
+- Ensure sending StopOffers for services specified with a different
+ protocol than someip in the configuration.
+- Add support for boost v1.70 and v1.71.
+
+v3.1.0
+- Integrate changes of 2.14.12 - 2.14.18
+- Add get_uid and get_gid methods to message class
+- Add reliability parameter to application::offer_event and
+ application::request_event methods
+- Add vSomeIP 2 compatibility layer.
+- Fix crash when expiring a reliable-only subscription
+- Fix Android compile errors
+- Fix bug in service discovery offer acceptance handling which led to
+ only checking the first service entry of an incoming SD message via
+ the registered handler.
+- Deactivate adherence to NPDU debounce time between SOME/IP-TP
+ segments of the same message.
+- Fix less than operator of remote_info_t which lead to
+ application::get_sd_acceptance_required() always returning a map
+ with only one erroneous element
+- Fix SD startup on Windows
+- Fix heap-use-after-free in server endpoints
+
+v3.0.0
+- Cleanup of application interface
+ - Removed (un)register_subscription_error_handler methods. The
+ functionality is now offered through the
+ (un)register_subscription_status_handler methods.
+ - All methods concerning events/fields now use a new event_type_e
+ enum to specify the event type.
+ - The subscription_type_e parameter was removed from the subscribe
+ method. The way the remote service is offered now determines the
+ subscription type.
+ - The offer_acceptance* methods were renamed to sd_acceptance*.
+ - The flush parameter was removed from the send method
+ - Removed notify and notify_one methods which used the flush
+ parameter.
+- Added SOME/IP-TP functionality. Please see the vsomeipUserGuide for
+ more information.
+- Added nPDU functionality. Please see the vsomeipUserGuide for more
+ information
+- E2E protection is now implemented as plugin
+- Added Android support
+- Internal improvements and bugfixes
+
+v2.14.18
+- Fix bug leading to not sending out FindService entries after a
+ resume from Suspend-to-RAM, if the service was already known at the
+ time of the request.
+
+v2.14.17
+- Performance improvements for request-service message handling
+
v2.14.16
- Ensure restarting of TCP connection if TCP reset is received
before 3 way handshake is finished
-- Reworked IPSec connection unblocking if reboot was detected
v2.14.15
- Ensure that all clients receive the security policy update
v2.14.14
-- Increased the max allowed number of open file descriptors
- from the soft limit to the hard limit for vsomeipd
- Improved handling for EMFILE error (per-process limit of open
filedescriptors reached)
- Fixed client ID assignment
@@ -64,6 +160,7 @@ v2.14.4
v2.14.3
- Prevent concurrent access to any client policies
+- Updated ACL plugin interface
v2.14.2
- Fix possible deadlock when receiving invalid responses from remote
@@ -77,6 +174,7 @@ v2.14.1
- Ensure to always resume sending if endpoints were restarted
- Prevent possible concurrent access to receive buffer in endpoints
- Allow or deny all remote clients via security config parameter
+- Adapt security config plugin to updated ACL interface
- Make receive buffer size configurable for UDP client and
server endpoints via "udp-receive-buffer-size" parameter
in json configuration file
@@ -87,6 +185,7 @@ v2.14.0
- Introduce security policy updates during runtime and extend
security configuration to filter on instance ID and method ID level
For more information see the vsomeipUserGuide.
+- Make IPsec plugin more robust against libdavici communication loss
v2.13.2
- Make I/O thread nice level configurable
@@ -99,6 +198,11 @@ v2.13.1
- Fix race when expiring remote services
v2.13.0
+- Update debug_diagnosis_plugin and add update_service_configuration
+ method to public application interface. This enables offering of
+ service instances on the network which are only offered locally by
+ default. The changes done through the new method are not persistent
+ over reboots.
- Fix handling of requests send to the service discovery port
- Log time since routing state was set to RS_RESUMED in cyclic version
logger
@@ -106,6 +210,10 @@ v2.13.0
RS_SUSPENDED
- Prevent possible exception during application shutdown
+v2.12.4
+- Improve handling of reboot detection in IPsec plugin if the
+ same ipsec connection is still used after reboot.
+
v2.12.3
- Improve handling of broken TCP streams
@@ -117,6 +225,7 @@ v2.12.1
- Fixed race condition in event registration
v2.12.0
+- Improve error handling and STR behaviour of IPsec plugin.
- Improve magic cookie handling.
- Fix possible deadlock on application shutdown
- Fix handling of local StopOffers when duplicate service instances
@@ -125,9 +234,19 @@ v2.12.0
- Fix bug in security configuration when black listing single
UIDs/GIDs
+v2.11.2
+- Ensure service availability if IPSec plugin is activated but IPsec
+ not configured correctly.
+
v2.11.1
+- Improve handling of slow remote ECUs in IPsec plugin
- Fix possible deadlock on application shutdown
+v2.11.0
+- Added IPsec plugin.
+ The compilation of the plugin has to be explicitly enabled when calling cmake.
+ Example: cmake -DPLUGIN_IPSEC_BUILD=1 ..
+
v2.10.22
- Handle EPERM error (Operation not permitted) in cei::send_cbk
- Restart TCP endpoint if a maximum number of aborted restarts
@@ -189,17 +308,24 @@ v2.10.17
- Fix bug leading to usage of client port outside of configured range
v2.10.16
+- Added changes for diagnosis mode plugin (as in v2.10.14)
- Only map shared memory for client IDs once per process
v2.10.15
+- Reverted diagnosis mode plugin (as in v2.10.11)
- Fix remote event caching
v2.10.14
+- Added changes for diagnosis mode plugin.
- Bugfix for pending subscriptions when same port is used
for TCP and UDP endpoint option.
+v2.10.13
+- Reverted diagnosis mode plugin
+
v2.10.12
- Fix exception handling for boost logger
+- Update diagnosis mode plugin
v2.10.11
- Fix client ID handling for remote selective subscriptions
@@ -286,6 +412,8 @@ v2.10.5
v2.10.4
+- Extended diagnosis plugin to handle requests for
+ "disableRxAndEnableTx" and "disableRxAndTx".
- Catch unhandled user code exceptions thrown from called handlers.
- Don't send SubscribeEventGroupNACK for pending subscriptions on next
offer to reduce the amount of StopSubscribe/Subscribe messages.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1d6f6d6..3a6023f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,10 +6,13 @@
cmake_minimum_required (VERSION 2.8.12)
project (vsomeip)
-set (VSOMEIP_MAJOR_VERSION 2)
-set (VSOMEIP_MINOR_VERSION 14)
-set (VSOMEIP_PATCH_VERSION 16)
-set (VSOMEIP_HOTFIX_VERSION 0)
+set (VSOMEIP_NAME vsomeip3)
+set (VSOMEIP_COMPAT_NAME vsomeip)
+
+set (VSOMEIP_MAJOR_VERSION 3)
+set (VSOMEIP_MINOR_VERSION 1)
+set (VSOMEIP_PATCH_VERSION 7)
+set (VSOMEIP_HOTFIX_VERSION 1)
set (VSOMEIP_VERSION ${VSOMEIP_MAJOR_VERSION}.${VSOMEIP_MINOR_VERSION}.${VSOMEIP_PATCH_VERSION})
set (PACKAGE_VERSION ${VSOMEIP_VERSION}) # Used in documentatin/doxygen.in
@@ -35,7 +38,7 @@ set (INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header f
if (WIN32 AND NOT CYGWIN)
set (DEF_INSTALL_CMAKE_DIR CMake)
else ()
- set (DEF_INSTALL_CMAKE_DIR lib/cmake/vsomeip)
+ set (DEF_INSTALL_CMAKE_DIR lib/cmake/${VSOMEIP_NAME})
endif ()
set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
@@ -77,14 +80,49 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(OS_CXX_FLAGS "-pthread")
endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
+################################################################################
+# Options
+################################################################################
+
+# DLT
+if (DISABLE_DLT)
+set (VSOMEIP_ENABLE_DLT 0)
+else ()
+set (VSOMEIP_ENABLE_DLT 1)
+endif ()
+
# Signal handling
if (ENABLE_SIGNAL_HANDLING)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVSOMEIP_ENABLE_SIGNAL_HANDLING")
endif ()
-include_directories(
- "interface"
-)
+# Thread sanitizer
+if (ENABLE_THREAD_SANITIZER)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
+endif ()
+
+# Configuration overlays
+if (ENABLE_CONFIGURATION_OVERLAYS)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVSOMEIP_ENABLE_CONFIGURATION_OVERLAYS")
+endif ()
+
+# Compatibility
+if (ENABLE_COMPAT)
+set (VSOMEIP_ENABLE_COMPAT 1)
+else ()
+set (VSOMEIP_ENABLE_COMPAT 0)
+endif ()
+
+# Multiple routing managers
+if (ENABLE_MULTIPLE_ROUTING_MANAGERS)
+set (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS 1)
+else ()
+set (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS 0)
+endif ()
+
+################################################################################
+# Dependencies
+################################################################################
# Threads
find_package(Threads REQUIRED)
@@ -106,12 +144,33 @@ else()
MESSAGE( STATUS "Boost was not found!")
endif()
-# DLT
+# cmake 3.15 introduced a new variable and a new format for the old one
+if (DEFINED Boost_VERSION_MACRO)
+ set(VSOMEIP_BOOST_VERSION ${Boost_VERSION_MACRO})
+else()
+ set(VSOMEIP_BOOST_VERSION ${Boost_VERSION})
+endif()
+
+message( STATUS "Using boost version: ${VSOMEIP_BOOST_VERSION}" )
+if (${VSOMEIP_BOOST_VERSION} GREATER 107200)
+message( ERROR "boost version ${VSOMEIP_BOOST_VERSION} is not (yet) supported. Latest supported version is 1.72.0" )
+elseif(${VSOMEIP_BOOST_VERSION} GREATER 106999)
+set(VSOMEIP_BOOST_HELPER implementation/helper/1.70)
+elseif(${VSOMEIP_BOOST_VERSION} GREATER 106599)
+set(VSOMEIP_BOOST_HELPER implementation/helper/1.66)
+else()
+set(VSOMEIP_BOOST_HELPER implementation/helper/1.55)
+endif()
+
find_package(PkgConfig)
+
+# DLT
+if(VSOMEIP_ENABLE_DLT EQUAL 1)
pkg_check_modules(DLT "automotive-dlt >= 2.11")
-IF(DLT_FOUND)
+if(DLT_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_DLT")
-ENDIF(DLT_FOUND)
+endif(DLT_FOUND)
+endif()
# SystemD
pkg_check_modules(SystemD "libsystemd")
@@ -121,9 +180,18 @@ MESSAGE( STATUS "Systemd was not found, watchdog disabled!")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITHOUT_SYSTEMD")
endif(NOT SystemD_FOUND)
+# Multiple routing managers
+if (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS EQUAL 1)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS")
+endif ()
+
+################################################################################
+# Directories
+################################################################################
+
include_directories(
- include
- implementation/helper
+ interface
+ ${VSOMEIP_BOOST_HELPER}
${DLT_INCLUDE_DIRS}
)
@@ -131,25 +199,6 @@ link_directories(
${DLT_LIBDIR}
)
-# Base library
-file(GLOB vsomeip_SRC
- "implementation/endpoints/src/*.cpp"
- "implementation/logging/src/*.cpp"
- "implementation/tracing/src/*.cpp"
- "implementation/message/src/*.cpp"
- "implementation/routing/src/*.cpp"
- "implementation/runtime/src/*.cpp"
- "implementation/utility/src/*.cpp"
- "implementation/plugin/src/*.cpp"
-)
-
-file(GLOB_RECURSE vsomeip_e2e_SRC
- "implementation/e2e_protection/src/*.cpp"
-)
-
-list(SORT vsomeip_SRC)
-list(SORT vsomeip_e2e_SRC)
-
if (${VSOMEIP_HOTFIX_VERSION} EQUAL 0)
add_definitions(-DVSOMEIP_VERSION="${VSOMEIP_VERSION}")
else()
@@ -171,43 +220,127 @@ else()
set(USE_RT "rt")
endif()
-add_library(vsomeip SHARED ${vsomeip_SRC} ${vsomeip_e2e_SRC})
-set_target_properties (vsomeip PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
+################################################################################
+# Configuration library
+################################################################################
+file(GLOB ${VSOMEIP_NAME}-cfg_SRC
+ "implementation/configuration/src/*.cpp"
+)
+list(SORT ${VSOMEIP_NAME}-cfg_SRC)
+if (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS EQUAL 0)
+ add_library(${VSOMEIP_NAME}-cfg SHARED ${${VSOMEIP_NAME}-cfg_SRC})
+ set_target_properties (${VSOMEIP_NAME}-cfg PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
+ if (MSVC)
+ set_target_properties(${VSOMEIP_NAME}-cfg PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
+ endif()
+
+ target_link_libraries(${VSOMEIP_NAME}-cfg ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+endif ()
+
+################################################################################
+# Base library
+################################################################################
+file(GLOB ${VSOMEIP_NAME}_SRC
+ "implementation/endpoints/src/*.cpp"
+ "implementation/logging/src/*.cpp"
+ "implementation/tracing/src/*.cpp"
+ "implementation/message/src/*.cpp"
+ "implementation/plugin/src/*.cpp"
+ "implementation/routing/src/*.cpp"
+ "implementation/runtime/src/*.cpp"
+ "implementation/security/src/*.cpp"
+ "implementation/utility/src/*.cpp"
+)
+if (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS EQUAL 1)
+list(APPEND ${VSOMEIP_NAME}_SRC ${${VSOMEIP_NAME}-cfg_SRC})
+endif()
+list(SORT ${VSOMEIP_NAME}_SRC)
+
+add_library(${VSOMEIP_NAME} SHARED ${${VSOMEIP_NAME}_SRC})
+set_target_properties (${VSOMEIP_NAME} PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
+if (MSVC)
+ set_target_properties(${VSOMEIP_NAME} PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
+endif ()
+target_include_directories(${VSOMEIP_NAME} INTERFACE
+ $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/interface>
+ $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
+ $<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>)
# PRIVATE means the listed libraries won't be included in the "link interface",
-# meaning the exported vsomeipTargets.cmake targets won't try to link against
+# meaning the exported vsomeip3Targets.cmake targets won't try to link against
# them (which shouldn't be required). ${Boost_LIBRARIES} includes absolute
# build host paths as of writing, which also makes this important as it breaks
# the build.
-target_link_libraries(vsomeip PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${DLT_LIBRARIES} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(${VSOMEIP_NAME} PRIVATE ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${DLT_LIBRARIES} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
-# Configuration library
-file(GLOB vsomeip-cfg_SRC
- "implementation/configuration/src/*.cpp"
+################################################################################
+# Service Discovery library
+################################################################################
+file(GLOB ${VSOMEIP_NAME}-sd_SRC
+ "implementation/service_discovery/src/*.cpp"
)
-list(SORT vsomeip-cfg_SRC)
+list(SORT ${VSOMEIP_NAME}-sd_SRC)
-add_library(vsomeip-cfg SHARED ${vsomeip-cfg_SRC})
-set_target_properties (vsomeip-cfg PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
-target_link_libraries(vsomeip-cfg vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+add_library(${VSOMEIP_NAME}-sd SHARED ${${VSOMEIP_NAME}-sd_SRC})
+set_target_properties (${VSOMEIP_NAME}-sd PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
+if (MSVC)
+ set_target_properties(${VSOMEIP_NAME}-sd PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
+endif ()
-# Service-Discovery library
-file(GLOB vsomeip-sd_SRC
- "implementation/service_discovery/src/*.cpp"
+target_link_libraries(${VSOMEIP_NAME}-sd ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+
+
+################################################################################
+# E2E library
+################################################################################
+file(GLOB_RECURSE ${VSOMEIP_NAME}-e2e_SRC
+ "implementation/e2e_protection/src/*.cpp"
)
-list(SORT vsomeip-sd_SRC)
+list(SORT ${VSOMEIP_NAME}-e2e_SRC)
+
+add_library(${VSOMEIP_NAME}-e2e SHARED ${${VSOMEIP_NAME}-e2e_SRC})
+set_target_properties (${VSOMEIP_NAME}-e2e PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
+if (MSVC)
+ set_target_properties(${VSOMEIP_NAME}-e2e PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
+endif ()
-add_library(vsomeip-sd SHARED ${vsomeip-sd_SRC})
-set_target_properties (vsomeip-sd PROPERTIES VERSION ${VSOMEIP_VERSION} SOVERSION ${VSOMEIP_MAJOR_VERSION})
-target_link_libraries(vsomeip-sd vsomeip ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+target_link_libraries(${VSOMEIP_NAME}-e2e ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+################################################################################
+# Compatibility library
+################################################################################
+if (VSOMEIP_ENABLE_COMPAT EQUAL 1)
+set (VSOMEIP_COMPAT_MAJOR_VERSION 2)
+set (VSOMEIP_COMPAT_VERSION ${VSOMEIP_COMPAT_MAJOR_VERSION}.99.99)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVSOMEIP_ENABLE_COMPAT")
+
+file(GLOB_RECURSE ${VSOMEIP_COMPAT_NAME}_SRC
+ "implementation/compat/logging/src/*.cpp"
+ "implementation/compat/message/src/*.cpp"
+ "implementation/compat/runtime/src/*.cpp"
+)
+list(SORT ${VSOMEIP_COMPAT_NAME}_SRC)
+
+add_library(${VSOMEIP_COMPAT_NAME} SHARED ${${VSOMEIP_COMPAT_NAME}_SRC})
+set_target_properties (${VSOMEIP_COMPAT_NAME} PROPERTIES VERSION ${VSOMEIP_COMPAT_VERSION} SOVERSION ${VSOMEIP_COMPAT_MAJOR_VERSION})
if (MSVC)
- set_target_properties(vsomeip-cfg PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
- set_target_properties(vsomeip-sd PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
- set_target_properties(vsomeip PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION")
-endif()
+ set_target_properties(${VSOMEIP_COMPAT_NAME} PROPERTIES COMPILE_DEFINITIONS "VSOMEIP_DLL_COMPILATION_PLUGIN")
+endif ()
-# Configuration files
+target_include_directories(
+ ${VSOMEIP_COMPAT_NAME}
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> # for headers when building
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # for generated files in build mode
+ $<INSTALL_INTERFACE:include/compat> # for clients in install mode
+)
+target_link_libraries(${VSOMEIP_COMPAT_NAME} PRIVATE ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${USE_RT} ${DL_LIBRARY} ${SystemD_LIBRARIES})
+
+endif ()
+################################################################################
+# Configuration files
+################################################################################
set(EXAMPLE_CONFIG_FILES
"config/vsomeip.json"
"config/vsomeip-local.json"
@@ -217,8 +350,14 @@ set(EXAMPLE_CONFIG_FILES
"config/vsomeip-udp-service.json"
)
-###################################################################################################
-set (VSOMEIP_DIAGNOSIS_ADDRESS "0x00")
+################################################################################
+# Configuration parameters
+################################################################################
+set (VSOMEIP_BASE_PATH "/tmp")
+if (BASE_PATH)
+set (VSOMEIP_BASE_PATH ${BASE_PATH})
+endif ()
+set (VSOMEIP_DIAGNOSIS_ADDRESS "0x01")
if (DIAGNOSIS_ADDRESS)
set (VSOMEIP_DIAGNOSIS_ADDRESS ${DIAGNOSIS_ADDRESS})
endif ()
@@ -226,20 +365,24 @@ set (VSOMEIP_UNICAST_ADDRESS "127.0.0.1")
if (UNICAST_ADDRESS)
set (VSOMEIP_UNICAST_ADDRESS ${UNICAST_ADDRESS})
endif ()
-set (VSOMEIP_ROUTING "vsomeipd")
-if (ROUTING)
-set (VSOMEIP_ROUTING ${ROUTING})
-endif ()
set (VSOMEIP_ROUTING_READY_MESSAGE "SOME/IP routing ready.")
if (ROUTING_READY_MESSAGE)
set (VSOMEIP_ROUTING_READY_MESSAGE ${ROUTING_READY_MESSAGE})
endif ()
+
+set(DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip" CACHE PATH "Default configuration folder")
+message(STATUS "Default configuration folder: ${DEFAULT_CONFIGURATION_FOLDER}")
+
+set(DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json" CACHE FILEPATH "Default configuration file")
+message(STATUS "Default configuration file: ${DEFAULT_CONFIGURATION_FILE}")
+
+message("Predefined base path: ${VSOMEIP_BASE_PATH}")
message("Predefined unicast address: ${VSOMEIP_UNICAST_ADDRESS}")
message("Predefined diagnosis address: ${VSOMEIP_DIAGNOSIS_ADDRESS}")
-message("Predefined routing application: ${VSOMEIP_ROUTING}")
-
-###################################################################################################
+################################################################################
+# Installation
+################################################################################
set(INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/interface/vsomeip")
file (GLOB_RECURSE vsomeip_INCLUDE RELATIVE ${INCLUDE_PATH} "interface/*.hpp" )
@@ -251,9 +394,9 @@ foreach ( file ${vsomeip_INCLUDE} )
endforeach()
install (
- TARGETS vsomeip
+ TARGETS ${VSOMEIP_NAME}
# IMPORTANT: Add the vsomeip library to the "export-set"
- EXPORT vsomeipTargets
+ EXPORT vsomeip3Targets
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
@@ -261,60 +404,93 @@ install (
)
install (
- TARGETS vsomeip-cfg
+ TARGETS ${VSOMEIP_NAME}-e2e
+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+)
+
+if (VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS EQUAL 0)
+install (
+ TARGETS ${VSOMEIP_NAME}-cfg
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
)
+endif ()
install (
- TARGETS vsomeip-sd
+ TARGETS ${VSOMEIP_NAME}-sd
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
)
+if (VSOMEIP_ENABLE_COMPAT EQUAL 1)
+install (
+ TARGETS ${VSOMEIP_COMPAT_NAME}
+ EXPORT vsomeipTargets
+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+)
+
+export (TARGETS ${VSOMEIP_COMPAT_NAME} FILE "${PROJECT_BINARY_DIR}/vsomeipTargets.cmake")
+export (PACKAGE ${VSOMEIP_COMPAT_NAME})
+
+configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfig.cmake" @ONLY)
+configure_file (vsomeipConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" @ONLY)
+
+set (COMPAT_INSTALL_CMAKE_DIR "lib/cmake/${VSOMEIP_COMPAT_NAME}")
+
+install (
+ EXPORT vsomeipTargets
+ DESTINATION "${COMPAT_INSTALL_CMAKE_DIR}"
+ COMPONENT dev
+)
+
+install (
+ FILES
+ "${PROJECT_BINARY_DIR}/vsomeipConfig.cmake"
+ "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake"
+ DESTINATION "${COMPAT_INSTALL_CMAKE_DIR}"
+ COMPONENT dev
+)
+
+configure_file(vsomeip.pc.in ${PROJECT_BINARY_DIR}/vsomeip.pc @ONLY)
+install(FILES ${PROJECT_BINARY_DIR}/vsomeip.pc DESTINATION lib/pkgconfig)
+
+endif ()
+
install (
FILES ${EXAMPLE_CONFIG_FILES} DESTINATION etc/vsomeip COMPONENT config
)
# Add all targets to the build-tree export set
-export (TARGETS vsomeip FILE "${PROJECT_BINARY_DIR}/vsomeipTargets.cmake")
+export (TARGETS ${VSOMEIP_NAME} FILE "${PROJECT_BINARY_DIR}/vsomeip3Targets.cmake")
# Export the package for use from the build-tree
# (this registers the build-tree with a global CMake-registry)
-export (PACKAGE vsomeip)
-
-# Create the vsomeipConfig.cmake and vsomeipConfigVersion files
-file (RELATIVE_PATH REL_INCLUDE_DIR "${ABSOLUTE_INSTALL_CMAKE_DIR}" "${ABSOLUTE_INSTALL_INCLUDE_DIR}")
+export (PACKAGE ${VSOMEIP_NAME})
-# ... for the build tree
-set (CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/interface" "${PROJECT_BINARY_DIR}")
-configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfig.cmake" @ONLY)
+# Create the vsomeip3Config.cmake and vsomeip3ConfigVersion files
+configure_file (vsomeip3Config.cmake.in "${PROJECT_BINARY_DIR}/vsomeip3Config.cmake" @ONLY)
+configure_file (vsomeip3ConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/vsomeip3ConfigVersion.cmake" @ONLY)
-# ... for the install tree
-set (CONF_INCLUDE_DIRS "\${VSOMEIP_CMAKE_DIR}/${REL_INCLUDE_DIR}")
-configure_file (vsomeipConfig.cmake.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake" @ONLY)
-
-# ... for both
-configure_file (vsomeipConfigVersion.cmake.in "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake" @ONLY)
-
-# confugure internal.hpp for correct version number
+# configure internal.hpp for correct version number
configure_file (
"${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp.in"
"${PROJECT_SOURCE_DIR}/implementation/configuration/include/internal.hpp"
)
-# Install the vsomeipConfig.cmake and vsomeipConfigVersion.cmake
+# Install the vsomeip3Config.cmake and vsomeip3ConfigVersion.cmake
install (
FILES
- "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/vsomeipConfig.cmake"
- "${PROJECT_BINARY_DIR}/vsomeipConfigVersion.cmake"
+ "${PROJECT_BINARY_DIR}/vsomeip3Config.cmake"
+ "${PROJECT_BINARY_DIR}/vsomeip3ConfigVersion.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}"
COMPONENT dev
)
# Install the export set for use with the install-tree
install (
- EXPORT vsomeipTargets
+ EXPORT vsomeip3Targets
DESTINATION "${INSTALL_CMAKE_DIR}"
COMPONENT dev
)
@@ -383,15 +559,14 @@ endif()
##############################################################################
# create pkg-config file
if(NOT WIN32)
- configure_file(vsomeip.pc.in ${PROJECT_BINARY_DIR}/vsomeip.pc @ONLY)
- install(FILES ${PROJECT_BINARY_DIR}/vsomeip.pc DESTINATION lib/pkgconfig)
+ configure_file(vsomeip3.pc.in ${PROJECT_BINARY_DIR}/vsomeip3.pc @ONLY)
+ install(FILES ${PROJECT_BINARY_DIR}/vsomeip3.pc DESTINATION lib/pkgconfig)
endif()
##############################################################################
-# build daemon (Non-Windows only)
+# build routing manager daemon (Non-Windows only)
if (NOT MSVC)
-add_custom_target( daemon )
-add_subdirectory( daemon )
+add_subdirectory( examples/routingmanagerd )
endif()
# build tools
@@ -402,17 +577,6 @@ add_subdirectory( tools )
add_custom_target( examples )
add_subdirectory( examples EXCLUDE_FROM_ALL )
-# build plugins located directly in the build tree
-# (Non-Windows only)
-if (NOT MSVC)
- if(EXISTS "${PROJECT_SOURCE_DIR}/plugins/CMakeLists.txt")
- # build plugins if available
- message("Plugins CMakeList.txt found: Build plugins")
- add_subdirectory( plugins )
- endif()
-endif()
-
-
##############################################################################
# Test section
##############################################################################
@@ -469,6 +633,20 @@ if((${TEST_IP_MASTER} STREQUAL ${TEST_IP_DEFAULT_VALUE}) OR
"-DTEST_IP_MASTER=10.0.3.1 -DTEST_IP_SLAVE=10.0.3.125")
endif()
+SET(TEST_IP_SLAVE_SECOND "${TEST_IP_DEFAULT_VALUE}" CACHE STRING
+ "The second IP address of the interface which will act as test slave")
+set(TEST_SECOND_ADDRESS "OFF" CACHE BOOL
+ "Controls whether second address tests should run or not")
+
+if(${TEST_IP_SLAVE_SECOND} STREQUAL ${TEST_IP_DEFAULT_VALUE})
+ message(WARNING "TEST_IP_SLAVE_SECOND isn't set. "
+ "Test with more than one IP address on same interface is not enabled."
+ "Please specify them via for example "
+ "-TEST_IP_SLAVE_SECOND=10.0.3.126")
+else()
+ set(TEST_SECOND_ADDRESS "ON")
+endif()
+
SET(TEST_UID_DEFAULT_VALUE "123456789")
SET(TEST_UID "${TEST_UID_DEFAULT_VALUE}" CACHE STRING
"The User ID of the user running the test: Needed for security")
@@ -489,8 +667,8 @@ if((${TEST_UID} STREQUAL ${TEST_UID_DEFAULT_VALUE}) OR
endif()
add_custom_target(build_tests)
-add_dependencies(build_tests vsomeip)
-add_dependencies(build_tests vsomeip-sd)
+add_dependencies(build_tests vsomeip3)
+add_dependencies(build_tests vsomeip3-sd)
set(CMAKE_CTEST_COMMAND ctest -V)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
diff --git a/README.md b/README.md
index efcfe94..8036a11 100644
--- a/README.md
+++ b/README.md
@@ -14,11 +14,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
The vsomeip stack implements the http://some-ip.com/ (Scalable service-Oriented
MiddlewarE over IP (SOME/IP)) protocol. The stack consists out of:
-* a shared library for SOME/IP (`libvsomeip.so`)
-* a second shared library for SOME/IP's service discovery (`libvsomeip-sd.so`)
+* a shared library for SOME/IP (`libvsomeip3.so`)
+* a second shared library for SOME/IP's service discovery (`libvsomeip3-sd.so`)
which is loaded during runtime if the service discovery is enabled.
-##### Build Instructions
+##### Build Instructions for Linux
###### Dependencies
@@ -72,6 +72,20 @@ cmake -DDIAGNOSIS_ADDRESS=<YOUR DIAGNOSIS ADDRESS> ..
```
The diagnosis address is a single byte value.
+###### Compilation with custom default configuration folder
+To change the default configuration folder, call cmake like:
+```bash
+cmake -DDEFAULT_CONFIGURATION_FOLDER=<DEFAULT CONFIGURATION FOLDER> ..
+```
+The default configuration folder is /etc/vsomeip.
+
+###### Compilation with custom default configuration file
+To change the default configuration file, call cmake like:
+```bash
+cmake -DDEFAULT_CONFIGURATION_FILE=<DEFAULT CONFIGURATION FILE> ..
+```
+The default configuration file is /etc/vsomeip.json.
+
###### Compilation with signal handling
To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled, call cmake like:
@@ -79,3 +93,26 @@ To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled, call cmake lik
cmake -DENABLE_SIGNAL_HANDLING=1 ..
```
In the default setting, the application has to take care of shutting down vsomeip in case these signals are received.
+
+
+##### Build Instructions for Android
+
+###### Dependencies
+
+- vsomeip uses Boost >= 1.55. The boost libraries (system, thread and log) must be included in the Android source tree and integrated into the build process with an appropriate Android.bp file.
+
+###### Compilation
+
+In general for building the Android source tree the instructions found on the pages from the Android Open Source Project (AOSP) apply (https://source.android.com/setup/build/requirements).
+
+To integrate the vsomeip library into the build process, the source code together with the Android.bp file has to be inserted into the Android source tree (by simply copying or by fetching with a custom platform manifest).
+When building the Android source tree, the Android.bp file is automatically found and considered by the build system.
+
+In order that the vsomeip library is also included in the Android image, the library has to be added to the PRODUCT_PACKAGES variable in one of a device/target specific makefile:
+
+```
+PRODUCT_PACKAGES += \
+ libvsomeip \
+ libvsomeip_cfg \
+ libvsomeip_sd
+``` \ No newline at end of file
diff --git a/config/vsomeip-tcp-client-security.json b/config/vsomeip-tcp-client-security.json
index 319e6b1..4a3f65b 100644
--- a/config/vsomeip-tcp-client-security.json
+++ b/config/vsomeip-tcp-client-security.json
@@ -29,11 +29,11 @@
],
"clients" :
[
- {
- "service" : "0x1234",
- "instance" : "0x5678",
- "reliable" : [ "41234" ]
- }
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "reliable" : [ "41234" ]
+ }
],
"security" :
{
diff --git a/config/vsomeip-tcp-client.json b/config/vsomeip-tcp-client.json
index b3d58cf..65b8189 100644
--- a/config/vsomeip-tcp-client.json
+++ b/config/vsomeip-tcp-client.json
@@ -29,11 +29,11 @@
],
"clients" :
[
- {
- "service" : "0x1234",
- "instance" : "0x5678",
- "reliable" : [ "41234" ]
- }
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "reliable" : [ "41234" ]
+ }
],
"routing" : "client-sample",
"service-discovery" :
diff --git a/config/vsomeip-udp-client-security.json b/config/vsomeip-udp-client-security.json
index 661e092..eec9613 100644
--- a/config/vsomeip-udp-client-security.json
+++ b/config/vsomeip-udp-client-security.json
@@ -29,11 +29,11 @@
],
"clients" :
[
- {
- "service" : "0x1234",
- "instance" : "0x5678",
- "unreliable" : [ 40000, 40002 ]
- }
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "unreliable" : [ 40000, 40002 ]
+ }
],
"security" :
{
diff --git a/config/vsomeip-udp-client.json b/config/vsomeip-udp-client.json
index 909eab5..47ffb26 100644
--- a/config/vsomeip-udp-client.json
+++ b/config/vsomeip-udp-client.json
@@ -29,11 +29,11 @@
],
"clients" :
[
- {
- "service" : "0x1234",
- "instance" : "0x5678",
- "unreliable" : [ 40000, 40002 ]
- }
+ {
+ "service" : "0x1234",
+ "instance" : "0x5678",
+ "unreliable" : [ 40000, 40002 ]
+ }
],
"routing" : "client-sample",
"service-discovery" :
diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt
deleted file mode 100644
index 2c04ab3..0000000
--- a/daemon/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-cmake_minimum_required (VERSION 2.8)
-
-# Daemon
-add_executable(vsomeipd vsomeipd.cpp)
-target_link_libraries(vsomeipd vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY} ${DLT_LIBRARIES})
-
-install (
- TARGETS vsomeipd
- RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
-)
-
-###################################################################################################
diff --git a/documentation/vsomeipUserGuide b/documentation/vsomeipUserGuide
index f4f5770..f3ac6be 100644
--- a/documentation/vsomeipUserGuide
+++ b/documentation/vsomeipUserGuide
@@ -14,8 +14,8 @@ vsomeip
:data-uri:
Copyright
-+++++++++
-Copyright (C) 2015-2017, Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
++++++++
+Copyright (C) 2015-2019, Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
License
+++++++
@@ -81,6 +81,16 @@ make
make install
----
+Compilation with predefined base path
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To predefine the base path, the path that is used to create the local sockets,
+call cmake like:
+[source,bash]
+----
+cmake -DBASE_PATH=<YOUR BASE PATH> ..
+----
+The default base path is /tmp.
+
Compilation with predefined unicast and/or diagnosis address
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To predefine the unicast address, call cmake like:
@@ -96,6 +106,24 @@ cmake -DDIAGNOSIS_ADDRESS=<YOUR DIAGNOSIS ADDRESS> ..
----
The diagnosis address is a single byte value.
+Compilation with custom default configuration folder
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To change the default configuration folder, call cmake like:
+[source,bash]
+----
+cmake -DDEFAULT_CONFIGURATION_FOLDER=<DEFAULT CONFIGURATION FOLDER> ..
+----
+The default configuration folder is /etc/vsomeip.
+
+Compilation with custom default configuration file
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To change the default configuration file, call cmake like:
+[source,bash]
+----
+cmake -DDEFAULT_CONFIGURATION_FILE=<DEFAULT CONFIGURATION FILE> ..
+----
+The default configuration file is /etc/vsomeip.json.
+
Compilation with signal handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To compile vsomeip with signal handling (SIGINT/SIGTERM) enabled,
@@ -116,6 +144,24 @@ to be ready to send/receive messages, call cmake like:
cmake -DROUTING_READY_MESSAGE=<YOUR MESSAGE> ..
----
+Compilation with configuration overlays
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To compile vsomeip with configuration overlays enabled, call cmake
+like:
+[source,bash]
+----
+cmake -DENABLE_CONFIGURATION_OVERLAYS=1 ..
+----
+
+Compilation with vSomeIP 2 compatibility layer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+To compile vsomeip with enabled vSomeIP 2 compatibility layer, call
+cmake like:
+[source,bash]
+----
+cmake -DENABLE_COMPAT=1 ..
+----
+
Compilation of examples
^^^^^^^^^^^^^^^^^^^^^^^
For compilation of the examples call:
@@ -289,6 +335,10 @@ The IP address of the host system.
+
The netmask to specify the subnet of the host system.
+
+* 'device' (optional)
++
+If specified, IP endpoints will be bound to this device.
++
* 'diagnosis'
+
The diagnosis address (byte) that will be used to build client identifiers. The
@@ -457,15 +507,15 @@ case the low byte must be different from zero. Thus, if the diagnosis address is
values range from 0x6301 until 0x63FF. It is also possible to use id values with a high byte
different from the diagnosis address.
+
-** 'max_dispatchers'
+** 'max_dispatchers' (optional)
+
-The maximum number of threads that shall be used to execute the application callbacks.
+The maximum number of threads that shall be used to execute the application callbacks. Default is 10.
+
-** 'max_dispatch_time'
+** 'max_dispatch_time' (optional)
+
-The maximum time that an application callback may consume before the callback is
+The maximum time in ms that an application callback may consume before the callback is
considered to be blocked (and an additional thread is used to execute pending
-callbacks if max_dispatchers is configured greater than 0).
+callbacks if max_dispatchers is configured greater than 0). The default value if not specified is 100ms.
+
** 'threads' (optional)
+
@@ -485,6 +535,30 @@ the load of sent messages to the routing manager and furthermore the replies fro
routing manager (which contains the routing info for the requested service if available)
can be heavily reduced. The default value if not specified is 10ms.
+
+** 'plugins' (optional array)
++
+Contains the plug-ins that should be loaded to extend the functionality of vsomeip.
++
+*** 'name'
++
+The name of the plug-in.
++
+*** 'type'
++
+The plug-in type (valid values: _application_plugin_).
++
+An application plug-in extends the functionality on application level. It gets informed
+by vsomeip over the basic application states (INIT/START/STOP) and can, based on these
+notifications, access the standard "application"-API via the runtime.
++
+** 'overlay' (optional)
++
+Contains the path to a configuration that overwrites specific configuration elements
+(unicast, netmask, device, network, diagnosis address & mask, service discovery) for the
+application. This allows to manage different network addresses from a single process.
++
+NOTE: This feature is only available if vsomeip was compiled with ENABLE_CONFIGURATION_OVERLAYS.
++
* `services` (array)
+
Contains the services of the service provider.
@@ -590,6 +664,33 @@ number of subscribers is lower than the threshold and by multicast if the number
of subscribers is greater or equal. This means, a threshold of 1 will lead to all events
being sent by multicast. The default value is _0_.
+** `debounce-times` (object)
++
+Used to configure the nPDU feature. This is described in detail in
+<<npdu,vSomeIP nPDU feature>>.
+
+** `someip-tp` (object)
++
+Used to configure the SOME/IP-TP feature. There's an example available at
+<<someiptp, SOME/IP-TP>>.
+
+*** `service-to-client` (array)
++
+Contains the IDs for responses, fields and events which are sent from the node
+to a remote client which can be segmented via SOME/IP-TP if they exceed the
+maximum message size for UDP communication. If an ID isn't listed here the
+message will otherwise be dropped if the maximum message size is exceeded.
+
+*** `client-to-service` (array)
++
+Contains the IDs for requests, which are sent from the node
+to a remote service which can be segmented via SOME/IP-TP if they exceed the
+maximum message size for UDP communication. If an ID isn't listed here the
+message will otherwise be dropped if the maximum message size is exceeded.
+Please note that the unicast key has to be set to the remote IP address of the
+offering node for this setting to take effect.
+
+
* `clients` (array)
+
The client-side ports that shall be used to connect to a specific service.
@@ -696,6 +797,14 @@ The maximum allowed payload size for TCP communication in
bytes. By default the payload size for TCP communication is
unlimited. It can be limited via this setting.
+* `max-payload-size-unreliable`
++
+The maximum allowed payload size for UDP communication via SOME/IP-TP in
+bytes. By default the payload size for UDP via SOME/IP-TP communication is
+unlimited. It can be limited via this setting. This setting only applies for
+SOME/IP-TP enabled methods/events/fields (otherwise the UDP default of 1400
+bytes applies). See <<someiptp, SOME/IP-TP>> for an example configuration.
+
* `endpoint-queue-limits` (array)
+
Array to limit the maximum allowed size in bytes of cached outgoing messages per
@@ -893,6 +1002,12 @@ Configures the time in milliseconds local clients wait for acknowledgement of
their deregistration from the routing manager during shutdown. Defaults to
5000ms.
+* `warn_fill_level`
++
+The routing manager regulary checks the fill level of the send buffers to its
+clients. This variable defines the minimum fill level in percent that leads to
+a warning being logged. Defaults to 67.
+
* `service-discovery`
+
Contains settings related to the Service Discovery of the host application.
@@ -1023,7 +1138,7 @@ Specifies the amount of allowed missing pongs.
(valid values: _1 - 2^32_), (default is _3_ pongs).
+
//CAPI-Selective Broadcasts support
-* anchor:config-supports_selective_broadcasts[]`supports_selective_broadcasts` (optional)
+* anchor:config-supports_selective_broadcasts[]`supports_selective_broadcasts` (optional array)
+
This nodes allow to add a list of IP addresses on which CAPI-Selective-Broadcasts feature is supported.
If not specified the feature can't be used and the subscription behavior of the stack is same as with
@@ -1038,17 +1153,17 @@ Security
--------
vsomeip has a security implementation based on UNIX credentials.
If activated every local connection is authenticated during connect using the standard UNIX credential passing mechanism.
-During authentification a client transfers its client identifier together with its credentials (UID / GID) to the server which is then matched against the configuration.
+During authentication a client transfers its client identifier together with its credentials (UID / GID) to the server which is then matched against the configuration.
If received credentials don't match the policy the socket will be immediately closed by the server and an message is logged.
If accepted the client identifier is bound to the receiving socket and can therefore be used to do further security checks on incoming messages (vsomeip messages as well as internal commands).
In general clients can be configured to be allowed/denied to request (means communicate with) and offer different service instances.
-Every incoming vsomeip message (request/response/notifcation) as well as offer service requests or local subscriptions are then checked against the policy.
+Every incoming vsomeip message (request/response/notification) as well as offer service requests or local subscriptions are then checked against the policy.
If an incoming vsomeip message or another operation (e.g. offer/subscribe) violates the configured policies it is skipped and a message is logged.
Furthermore if an application receives informations about other clients/services in the system, it must be received from the authenticated routing manager.
This is to avoid malicious applications faking the routing manager and therefore being able to wrongly inform other clients about services running on the system.
-Therefore, whenever the "security" tag is specified, the routing manager (e.g. vsomeipd) must be a configured application with a fixed client identifier.
+Therefore, whenever the "security" tag is specified, the routing manager (e.g. routingmanagerd/vsomeipd) must be a configured application with a fixed client identifier.
See chapter "Configuration File Structure" on how to configure an application to use a specific client identifier.
Credential passing is only possible via Unix-Domain-Sockets and therefore only available for local communication.
@@ -1080,39 +1195,19 @@ If not specified, all remote requests / subscriptions are allowed to be received
+
Specifies the security policies. Each policy at least needs to specify _allow_ or _deny_.
-*** `client` (optional)
-+
-Specifies a client for which a security policy will be applied (valid value: A valid client identifier in hex: e.g. _0x1234_).
-It is also possible to specify a client identifier range to easily apply a policy to a set of clients.
-A usecase is e.g. to allow a set of remote clients communicate with local services offered remote.
-+
-No client specification equals to any client (_0xFFFF_). Such policies are applied if a client has no specific policy.
-
-**** `first`
-+
-Specifies the first client of a range (first is included).
-(valid value: A valid client identifier in hex: e.g. _0x1234_)
-
-**** `last`
+*** `credentials`
+
-Specifies the last client id of a range (last is included).
-(valid value: A valid client identifier in hex: e.g. _0x1234_)
-
-*** `credential` (optional)
-+
-Specifies the credentials of the above client(s).
-If _check_credentials_ is set to _true_ the credentials for the above client(s) (if they running locally) needs to be specified correctly to ensure local socket authentification can succeed.
-This entry is optional due to the fact that remote clients needs to be configured as well to allow to communicate with local services as already mentioned above.
-For remote clients this entry should be skipped.
+Specifies the credentials for which a security policy will be applied.
+If _check_credentials_ is set to _true_ the credentials of a local application needs to be specified correctly to ensure local socket authentication can succeed.
**** `uid`
+
-Specifies the LINUX user id of the above client(s) as decimal number.
+Specifies the LINUX user id of the client application as decimal number.
As a wildcard "any" can be used.
**** `gid`
+
-Specifies the LINUX group id of the above client(s) as decimal number.
+Specifies the LINUX group id of the client application as decimal number.
As a wildcard "any" can be used.
**** `allow` / `deny` (optional)
@@ -1137,7 +1232,7 @@ With _deny_ a blacklisting of what is allowed can be done which means an empty _
**** `requests` (array)
+
-Specifies a set of service instance pairs which the above client(s) is allowed/denied to communicate with.
+Specifies a set of service instance pairs which the above client application using the credentials above is allowed/denied to communicate with.
. `service`
+
@@ -1179,7 +1274,7 @@ As a wildcard "any" can be used which means a range from method ID 0x01 to 0xFFF
**** `offers` (array)
+
-Specifies a set of service instance pairs which are allowed/denied to be offered by the above client(s).
+Specifies a set of service instance pairs which are allowed/denied to be offered by the client application using the credentials above.
. `service`
+
@@ -1192,7 +1287,7 @@ As a wildcard "any" can be used which means a range from instance ID 0x01 to 0xF
. `instances` (array)
+
-Specifies a set of instance ID ranges which are allowed/denied to be offered by the above client(s)
+Specifies a set of instance ID ranges which are allowed/denied to be offered by the client application using the credentials above.
It is also possible to specify a single instance ID as array element without giving an upper / lower range bound.
As a wildcard "any" can be used which means a range from instance ID 0x01 to 0xFFFF.
@@ -1345,25 +1440,23 @@ Every client running locally needs to have at least its own credentials configur
Practically that means if a client requests its identifier over the autoconfiguration for which no credentials are configured (at least it isn't known which client identifier is used beforehand) it is impossible for that client to establish a connection to a server endpoint.
However if the credentials for all clients are same it's possible to configure them for the overall (or DIAGNOSIS_ADDRESS) client identifier range to mix autoconfiguration together with activated security.
-vsomeipd
---------
-The vsomeipd is a minimal vsomeip application intended to offer routing manager
-functionality on a node where one system wide configuration file is present.
-
-The vsomeipd uses the application name `vsomeipd` by default. This name can be
-overridden by specifying `-DROUTING=$DESIRED_NAME` during the cmake call.
+routingmanagerd
+---------------
+The routingmanagerd is a minimal vsomeip application intended to offer routing
+manager functionality on a node where one system wide configuration file is
+present. It can be found in the examples folder.
Example: Starting the daemon on a system where the system wide configuration is
stored under `/etc/vsomeip.json`:
[source, bash]
----
-VSOMEIP_CONFIGURATION=/etc/vsomeip.json ./vsomeipd
+VSOMEIP_CONFIGURATION=/etc/vsomeip.json ./routingmanagerd
----
When using the daemon it should be ensured that:
-* In the system wide configuration file the vsomeipd is defined as
- routing manager, meaning it contains the line `"routing" : "vsomeipd"`.
+* In the system wide configuration file the routingmanagerd is defined as
+ routing manager, meaning it contains the line `"routing" : "routingmanagerd"`.
If the default name is overridden the entry has to be adapted accordingly.
The system wide configuration file should contain the information about all
other offered services on the system as well.
@@ -1750,6 +1843,422 @@ Example:
its_channel->remove_filter(its_filter_id);
----
+anchor:npdu[]
+
+vsomeip nPDU feature
+------------------
+
+This is the add-on documentation for the nPDU feature, aka. _Zugverfahren_.
+
+The nPDU feature can be used to reduce network load as it enables the vsomeip
+stack to combine multiple vsomeip messages in one single ethernet frame.
+
+Some general _important_ things regarding the nPDU feature first:
+
+* Due to its nature the nPDU feature trades lower network load for speed.
+* As the nPDU feature requires some settings which are not transmitted
+through the service discovery, it's *not* sufficient anymore to have an json
+file without a "services" section on the client side.
+* As the client- and server-endpoints of a node are managed by the routing
+ manager (which is the application entered at "routing" in the json file)
+ the nPDU feature settings *always* have to be defined in the json file used by
+ the application acting as routing manager.
+* The nPDU feature timings are defined in milliseconds.
+* Node internal communication over UNIX domain sockets is not affected by the
+ nPDU feature.
+* If the debounce times configuration for a method in the json file is missing
+ or incomplete the default values are used: 2ms debounce time and 5ms max
+ retention time. The global default values can be overwritten via the
+ `npdu-default-timings` json object.
+
+Configuration
+~~~~~~~~~~~~~
+There are two parameters specific for the nPDU feature:
+
+* *debounce time*: minimal time between sending a message to the same method of
+ a remote service over the same connection (src/dst address + src/dst port).
+* *max retention time*: the maximum time which a message to the same method of a
+ remote service over the same connection (src/dst address + src/dst port) is
+ allowed to be buffered on sender side.
+
+For more information please see the corresponding requirement documents.
+
+
+The nPDU feature specific settings are configured in the json file in the
+"services" section on service level in a special _debounce-times_ section:
+
+[source, bash]
+----
+[...]
+"services":
+[
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "debounce-times":
+ {
+ // nPDU feature configuration for this
+ // service here
+ }
+ }
+],
+[...]
+----
+
+Additionally nPDU default timings can be configured globally.
+
+The global default timings can be overwritten via the `npdu-default-timings`
+json object. For example the following configuration snippet shows how to set
+all default timings to zero:
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.9",
+ [...]
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
+
+Example 1: One service with one method offered over UDP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* The service is hosted on IP: 192.168.1.9.
+* The service is offered on port 30509 via UDP.
+* The service has the ID 0x1000
+* The method has the ID 0x0001
+* The client accesses the service from IP: 192.168.1.77
+
+Service side
+++++++++++++
+
+* Debounce time for responses should have a:
+** debounce time of 10 milliseconds
+** maximum retention time of 100 milliseconds
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.9",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "debounce-times":
+ {
+ "responses": {
+ "0x1001" : {
+ "debounce-time":"10",
+ "maximum-retention-time":"100"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+Client side
+++++++++++++
+
+* Debounce time for requests to the service on 192.168.1.9 should have a:
+** debounce time of 20 milliseconds
+** maximum retention time of 200 milliseconds
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.77",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unicast":"192.168.1.9", // required to mark service as external
+ "unreliable":"30509",
+ "debounce-times":
+ {
+ "requests": {
+ "0x1001" : {
+ "debounce-time":"20",
+ "maximum-retention-time":"200"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
+Example 2: One service with two methods offered over UDP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* The service is hosted on IP: 192.168.1.9.
+* The service is offered on port 30509 via UDP.
+* The service has the ID 0x1000
+* The method has the ID 0x0001
+* The second method has the ID 0x0002
+* The client accesses the service from IP: 192.168.1.77
+
+Service side
+++++++++++++
+
+* Debounce time for responses should have a:
+** debounce time of 10 milliseconds for method 0x1001 and 20 for 0x1002
+** maximum retention time of 100 milliseconds for method 0x1001 and 200 for 0x1002
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.9",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "debounce-times":
+ {
+ "responses": {
+ "0x1001" : {
+ "debounce-time":"10",
+ "maximum-retention-time":"100"
+ },
+ "0x1002" : {
+ "debounce-time":"20",
+ "maximum-retention-time":"200"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+Client side
+++++++++++++
+
+* Debounce time for requests to the service on 192.168.1.9 should have a:
+** debounce time of 20 milliseconds for method 0x1001 and 40 for 0x1002
+** maximum retention time of 200 milliseconds for method 0x1001 and 400 for 0x1002
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.77",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unicast":"192.168.1.9", // required to mark service as external
+ "unreliable":"30509",
+ "debounce-times":
+ {
+ "requests": {
+ "0x1001" : {
+ "debounce-time":"20",
+ "maximum-retention-time":"200"
+ },
+ "0x1002" : {
+ "debounce-time":"40",
+ "maximum-retention-time":"400"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
+Example 3: One service with one method offered over UDP and TCP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* The service is hosted on IP: 192.168.1.9.
+* The service is offered on port 30509 via UDP.
+* The service is offered on port 30510 via TCP.
+* The service has the ID 0x1000
+* The method has the ID 0x0001
+* The client accesses the service from IP: 192.168.1.77
+
+Service side
+++++++++++++
+
+* Debounce time for responses should have a:
+** debounce time of 10 milliseconds
+** maximum retention time of 100 milliseconds
+** TCP should use the same settings as UDP
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.9",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "responses": {
+ "0x1001" : {
+ "debounce-time":"10",
+ "maximum-retention-time":"100",
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+Client side
+++++++++++++
+
+* Debounce time for requests to the service on 192.168.1.9 should have a:
+** debounce time of 20 milliseconds
+** maximum retention time of 200 milliseconds
+** TCP should use the same settings as UDP
+
+[source, bash]
+----
+{
+ "unicast":"192.168.1.77",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unicast":"192.168.1.9", // required to mark service as external
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "requests": {
+ "0x1001" : {
+ "debounce-time":"20",
+ "maximum-retention-time":"200",
+ }
+ }
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
+
+anchor:someiptp[]
+
+SOME/IP TP
+----------
+With SOME/IP Transport Protocol (TP) it is possible to transport messages which
+exceed the UDP payload size limit of 1400 byte. If enabled the message is
+segmented and send in multiple UDP datagrams.
+
+Example configuration:
+
+* Service 0x1111/0x1 is hosted on 192.168.0.1 on UDP port 40000
+* Client is running on 192.168.0.100
+* The service has two methods with ID: 0x1 and 0x2 which require large requests
+ and large responses. Additionally the service offers a field with ID 0x8001
+ which requires a large payloads as well.
+* The maximum payload size on service side should be limited to 5000 bytes.
+
+Configuration service side:
+[source, bash]
+----
+{
+ "unicast":"192.168.0.1",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x1",
+ "unreliable":"40000",
+ "someip-tp": {
+ "service-to-client": [
+ "0x1", "0x2", "0x8001"
+ ]
+ }
+ }
+ ],
+ "max-payload-size-unreliable" : "5000",
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
+Configuration client side:
+
+[source, bash]
+----
+{
+ "unicast":"192.168.0.100",
+ "logging": { [...] },
+ "applications": [ [...] ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x1",
+ "unicast":"192.168.0.1", // required to mark service as external
+ "unreliable":"40000", // required to mark service as external
+ "someip-tp": {
+ "client-to-service": [
+ "0x1", "0x2"
+ ]
+ }
+ }
+ ],
+ "routing":"[...]",
+ "service-discovery": { [...] }
+}
+----
+
Tools
-----
@@ -1766,11 +2275,11 @@ be printed.
* The complete message has to be passed in hexadecimal notation.
* See the `--help` parameter for available options.
* If `vsomeip_ctrl` is used to send messages to a remote service and no
- `vsomeipd` is running on the local machine, make sure to pass a json
+ `routingmanagerd` is running on the local machine, make sure to pass a json
configuration file where `vsomeip_ctrl` is set as routing manager via
environment variable.
* If `vsomeip_ctrl` is used to send messages to a local service and no
- `vsomeipd` is running on the local machine, make sure to use the same json
+ `routingmanagerd` is running on the local machine, make sure to use the same json
configuration file as the local service.
Example: Calling method with method id 0x80e8 on service with service id 0x1234,
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 017c56d..f6324e0 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,37 +1,37 @@
-# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-cmake_minimum_required (VERSION 2.8)
-
-set(EXAMPLE_CONFIG_FILES
- "../config/vsomeip.json"
- "../config/vsomeip-local.json"
- "../config/vsomeip-tcp-client.json"
- "../config/vsomeip-tcp-service.json"
- "../config/vsomeip-udp-client.json"
- "../config/vsomeip-udp-service.json"
-)
-
-# Examples
-add_executable(request-sample request-sample.cpp ${EXAMPLE_CONFIG_FILES})
-target_link_libraries(request-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY})
-
-add_executable(response-sample response-sample.cpp ${EXAMPLE_CONFIG_FILES})
-target_link_libraries(response-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY})
-
-add_executable(subscribe-sample subscribe-sample.cpp ${EXAMPLE_CONFIG_FILES})
-target_link_libraries(subscribe-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY})
-
-add_executable(notify-sample notify-sample.cpp ${EXAMPLE_CONFIG_FILES})
-target_link_libraries(notify-sample vsomeip ${Boost_LIBRARIES} ${DL_LIBRARY})
-
-add_dependencies(examples request-sample response-sample subscribe-sample notify-sample)
-
-install (
- TARGETS request-sample response-sample subscribe-sample notify-sample
- RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
-)
-
-###################################################################################################
+# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+cmake_minimum_required (VERSION 2.8)
+
+set(EXAMPLE_CONFIG_FILES
+ "../config/vsomeip.json"
+ "../config/vsomeip-local.json"
+ "../config/vsomeip-tcp-client.json"
+ "../config/vsomeip-tcp-service.json"
+ "../config/vsomeip-udp-client.json"
+ "../config/vsomeip-udp-service.json"
+)
+
+# Examples
+add_executable(request-sample request-sample.cpp ${EXAMPLE_CONFIG_FILES})
+target_link_libraries(request-sample ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${DL_LIBRARY})
+
+add_executable(response-sample response-sample.cpp ${EXAMPLE_CONFIG_FILES})
+target_link_libraries(response-sample ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${DL_LIBRARY})
+
+add_executable(subscribe-sample subscribe-sample.cpp ${EXAMPLE_CONFIG_FILES})
+target_link_libraries(subscribe-sample ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${DL_LIBRARY})
+
+add_executable(notify-sample notify-sample.cpp ${EXAMPLE_CONFIG_FILES})
+target_link_libraries(notify-sample ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${DL_LIBRARY})
+
+add_dependencies(examples request-sample response-sample subscribe-sample notify-sample)
+
+install (
+ TARGETS request-sample response-sample subscribe-sample notify-sample
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+)
+
+###################################################################################################
diff --git a/examples/hello_world/CMakeLists.txt b/examples/hello_world/CMakeLists.txt
index b7f7c78..2aabd02 100644
--- a/examples/hello_world/CMakeLists.txt
+++ b/examples/hello_world/CMakeLists.txt
@@ -9,9 +9,9 @@ project (vSomeIPHelloWorld)
# This will get us acces to
# VSOMEIP_INCLUDE_DIRS - include directories for vSomeIP
# VSOMEIP_LIBRARIES - libraries to link against
-find_package(vsomeip)
-if (NOT vsomeip_FOUND)
- message("vsomeip was not found. Please specify vsomeip_DIR")
+find_package(${VSOMEIP_NAME})
+if (NOT ${VSOMEIP_NAME}_FOUND)
+ message("${VSOMEIP_NAME} was not found. Please specify vsomeip_DIR")
endif()
find_package(Threads REQUIRED)
diff --git a/examples/hello_world/hello_world_client.cpp b/examples/hello_world/hello_world_client.cpp
index cecdf67..37bd0d9 100644
--- a/examples/hello_world/hello_world_client.cpp
+++ b/examples/hello_world/hello_world_client.cpp
@@ -93,7 +93,7 @@ public:
// Send the request to the service. Response will be delivered to the
// registered message handler
std::cout << "Sending: " << str << std::endl;
- app_->send(rq, true);
+ app_->send(rq);
}
}
diff --git a/examples/hello_world/hello_world_service.cpp b/examples/hello_world/hello_world_service.cpp
index 7af031c..ce07721 100644
--- a/examples/hello_world/hello_world_service.cpp
+++ b/examples/hello_world/hello_world_service.cpp
@@ -115,7 +115,7 @@ public:
resp->set_payload(resp_pl);
// Send the response back
- app_->send(resp, true);
+ app_->send(resp);
// we have finished
terminate();
}
diff --git a/examples/notify-sample.cpp b/examples/notify-sample.cpp
index 1bcd219..0b9ed52 100644
--- a/examples/notify-sample.cpp
+++ b/examples/notify-sample.cpp
@@ -11,6 +11,7 @@
#include <iostream>
#include <sstream>
#include <thread>
+#include <mutex>
#include <vsomeip/vsomeip.hpp>
@@ -62,8 +63,12 @@ public:
SAMPLE_INSTANCE_ID,
SAMPLE_EVENT_ID,
its_groups,
- true);
- payload_ = vsomeip::runtime::get()->create_payload();
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
+ {
+ std::lock_guard<std::mutex> its_lock(payload_mutex_);
+ payload_ = vsomeip::runtime::get()->create_payload();
+ }
blocked_ = true;
condition_.notify_one();
@@ -120,17 +125,23 @@ public:
void on_get(const std::shared_ptr<vsomeip::message> &_message) {
std::shared_ptr<vsomeip::message> its_response
= vsomeip::runtime::get()->create_response(_message);
- its_response->set_payload(payload_);
- app_->send(its_response, true);
+ {
+ std::lock_guard<std::mutex> its_lock(payload_mutex_);
+ its_response->set_payload(payload_);
+ }
+ app_->send(its_response);
}
void on_set(const std::shared_ptr<vsomeip::message> &_message) {
- payload_ = _message->get_payload();
-
std::shared_ptr<vsomeip::message> its_response
= vsomeip::runtime::get()->create_response(_message);
- its_response->set_payload(payload_);
- app_->send(its_response, true);
+ {
+ std::lock_guard<std::mutex> its_lock(payload_mutex_);
+ payload_ = _message->get_payload();
+ its_response->set_payload(payload_);
+ }
+
+ app_->send(its_response);
app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID,
SAMPLE_EVENT_ID, payload_);
}
@@ -176,10 +187,13 @@ public:
for (uint32_t i = 0; i < its_size; ++i)
its_data[i] = static_cast<uint8_t>(i);
- payload_->set_data(its_data, its_size);
+ {
+ std::lock_guard<std::mutex> its_lock(payload_mutex_);
+ payload_->set_data(its_data, its_size);
- std::cout << "Setting event (Length=" << std::dec << its_size << ")." << std::endl;
- app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_);
+ std::cout << "Setting event (Length=" << std::dec << its_size << ")." << std::endl;
+ app_->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, payload_);
+ }
its_size++;
@@ -203,6 +217,7 @@ private:
std::condition_variable notify_condition_;
bool is_offered_;
+ std::mutex payload_mutex_;
std::shared_ptr<vsomeip::payload> payload_;
// blocked_ / is_offered_ must be initialized before starting the threads!
diff --git a/examples/request-sample.cpp b/examples/request-sample.cpp
index 7732cb0..b6105c4 100644
--- a/examples/request-sample.cpp
+++ b/examples/request-sample.cpp
@@ -151,7 +151,7 @@ public:
std::unique_lock<std::mutex> its_lock(mutex_);
while (!blocked_) condition_.wait(its_lock);
if (is_available_) {
- app_->send(request_, true);
+ app_->send(request_);
std::cout << "Client/Session ["
<< std::setw(4) << std::setfill('0') << std::hex << request_->get_client()
<< "/"
diff --git a/examples/response-sample.cpp b/examples/response-sample.cpp
index b4b6250..064388e 100644
--- a/examples/response-sample.cpp
+++ b/examples/response-sample.cpp
@@ -19,7 +19,7 @@
class service_sample {
public:
service_sample(bool _use_static_routing) :
- app_(vsomeip::runtime::get()->create_application()),
+ app_(vsomeip::runtime::get()->create_application("response-sample")),
is_registered_(false),
use_static_routing_(_use_static_routing),
blocked_(false),
@@ -111,7 +111,7 @@ public:
its_payload->set_data(its_payload_data);
its_response->set_payload(its_payload);
- app_->send(its_response, true);
+ app_->send(its_response);
}
void run() {
diff --git a/examples/routingmanagerd/CMakeLists.txt b/examples/routingmanagerd/CMakeLists.txt
new file mode 100644
index 0000000..d15949a
--- /dev/null
+++ b/examples/routingmanagerd/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+cmake_minimum_required (VERSION 2.8)
+
+# Daemon
+add_executable(routingmanagerd routingmanagerd.cpp)
+target_link_libraries(routingmanagerd ${VSOMEIP_NAME} ${Boost_LIBRARIES} ${DL_LIBRARY} ${DLT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+add_dependencies(routingmanagerd ${VSOMEIP_NAME})
+
+option(VSOMEIP_INSTALL_ROUTINGMANAGERD "Whether or not to install the routing manager daemon.")
+
+if (VSOMEIP_INSTALL_ROUTINGMANAGERD)
+ install (
+ TARGETS routingmanagerd
+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
+ )
+endif()
+
+
+
+###################################################################################################
diff --git a/daemon/vsomeipd.cpp b/examples/routingmanagerd/routingmanagerd.cpp
index 8314b9a..53b4fc1 100644
--- a/daemon/vsomeipd.cpp
+++ b/examples/routingmanagerd/routingmanagerd.cpp
@@ -10,48 +10,34 @@
#include <thread>
#include <condition_variable>
#include <mutex>
-#include <cstring>
#include <iostream>
#include <vsomeip/vsomeip.hpp>
-#include "../implementation/configuration/include/internal.hpp"
-#include "../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#ifdef USE_DLT
#include <dlt/dlt.h>
-#include "../implementation/logging/include/defines.hpp"
+#include "../../implementation/logging/include/defines.hpp"
#endif
static std::shared_ptr<vsomeip::application> its_application;
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
-static vsomeip::routing_state_e routing_state = vsomeip::routing_state_e::RS_RUNNING;
static bool stop_application = false;
static bool stop_sighandler = false;
static std::condition_variable_any sighandler_condition;
static std::recursive_mutex sighandler_mutex;
#endif
-#ifndef _WIN32
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
/*
* Handle signal to stop the daemon
*/
-void vsomeipd_stop(int _signal) {
+void routingmanagerd_stop(int _signal) {
// Do not log messages in signal handler as this can cause deadlock in boost logger
if (_signal == SIGINT || _signal == SIGTERM) {
stop_application = true;
}
- if (_signal == SIGUSR1) {
- routing_state = vsomeip::routing_state_e::RS_SUSPENDED;
- }
- if (_signal == SIGUSR2) {
- routing_state = vsomeip::routing_state_e::RS_RESUMED;
- }
std::unique_lock<std::recursive_mutex> its_lock(sighandler_mutex);
sighandler_condition.notify_one();
}
@@ -60,7 +46,7 @@ void vsomeipd_stop(int _signal) {
/*
* Create a vsomeip application object and start it.
*/
-int vsomeipd_process(bool _is_quiet) {
+int routingmanagerd_process(bool _is_quiet) {
#ifdef USE_DLT
if (!_is_quiet)
DLT_REGISTER_APP(VSOMEIP_LOG_DEFAULT_APPLICATION_ID, VSOMEIP_LOG_DEFAULT_APPLICATION_NAME);
@@ -76,14 +62,12 @@ int vsomeipd_process(bool _is_quiet) {
}
// Create the application object
- its_application = its_runtime->create_application(VSOMEIP_ROUTING);
+ its_application = its_runtime->create_application("routingmanagerd");
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
std::thread sighandler_thread([]() {
// Unblock signals for this thread only
sigset_t handler_mask;
sigemptyset(&handler_mask);
- sigaddset(&handler_mask, SIGUSR2);
- sigaddset(&handler_mask, SIGUSR1);
sigaddset(&handler_mask, SIGTERM);
sigaddset(&handler_mask, SIGINT);
sigaddset(&handler_mask, SIGSEGV);
@@ -91,48 +75,28 @@ int vsomeipd_process(bool _is_quiet) {
pthread_sigmask(SIG_UNBLOCK, &handler_mask, NULL);
// Handle the following signals
- signal(SIGINT, vsomeipd_stop);
- signal(SIGTERM, vsomeipd_stop);
- signal(SIGUSR1, vsomeipd_stop);
- signal(SIGUSR2, vsomeipd_stop);
+ signal(SIGINT, routingmanagerd_stop);
+ signal(SIGTERM, routingmanagerd_stop);
while (!stop_sighandler) {
std::unique_lock<std::recursive_mutex> its_lock(sighandler_mutex);
sighandler_condition.wait(its_lock);
-
if (stop_application) {
its_application->stop();
return;
- } else if (routing_state == vsomeip::routing_state_e::RS_RESUMED ||
- routing_state == vsomeip::routing_state_e::RS_SUSPENDED){
- VSOMEIP_INFO << "Received signal for setting routing_state to: 0x"
- << std::hex << static_cast<int>(routing_state );
- its_application->set_routing_state(routing_state);
}
}
});
#endif
if (its_application->init()) {
if (its_application->is_routing()) {
-#ifndef _WIN32
- // raise the max number of open file descriptors to the hard limit
- struct rlimit its_current_fd_limit;
- if (-1 == getrlimit(RLIMIT_NOFILE, &its_current_fd_limit)) {
- VSOMEIP_ERROR << "Couldn't read out RLIMIT_NOFILE: " << std::strerror(errno);
- } else {
- its_current_fd_limit.rlim_cur = its_current_fd_limit.rlim_max;
- if (-1 == setrlimit(RLIMIT_NOFILE, &its_current_fd_limit)) {
- VSOMEIP_ERROR << "Couldn't set RLIMIT_NOFILE: " << std::strerror(errno);
- }
- }
-#endif
its_application->start();
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
sighandler_thread.join();
#endif
return 0;
}
- VSOMEIP_ERROR << "vsomeipd has not been configured as routing - abort";
+ VSOMEIP_ERROR << "routingmanagerd has not been configured as routing - abort";
}
#ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
std::unique_lock<std::recursive_mutex> its_lock(sighandler_mutex);
@@ -198,5 +162,5 @@ int main(int argc, char **argv) {
}
}
- return vsomeipd_process(is_quiet);
+ return routingmanagerd_process(is_quiet);
}
diff --git a/examples/subscribe-sample.cpp b/examples/subscribe-sample.cpp
index 5350263..7374dae 100644
--- a/examples/subscribe-sample.cpp
+++ b/examples/subscribe-sample.cpp
@@ -54,7 +54,7 @@ public:
SAMPLE_INSTANCE_ID,
SAMPLE_EVENT_ID,
its_groups,
- true);
+ vsomeip::event_type_e::ET_FIELD);
app_->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID);
return true;
@@ -121,7 +121,7 @@ public:
its_get->set_instance(SAMPLE_INSTANCE_ID);
its_get->set_method(SAMPLE_GET_METHOD_ID);
its_get->set_reliable(use_tcp_);
- app_->send(its_get, true);
+ app_->send(its_get);
}
if ((its_payload->get_length() % 8) == 0) {
@@ -139,7 +139,7 @@ public:
= vsomeip::runtime::get()->create_payload();
its_set_payload->set_data(its_data, sizeof(its_data));
its_set->set_payload(its_set_payload);
- app_->send(its_set, true);
+ app_->send(its_set);
}
}
}
diff --git a/exportmap.gcc b/exportmap.gcc
index aec5019..efeaadb 100644
--- a/exportmap.gcc
+++ b/exportmap.gcc
@@ -1,48 +1,64 @@
{
global:
extern "C++" {
- *vsomeip::configuration;
- vsomeip::configuration::*;
- *vsomeip::cfg::configuration_impl;
- vsomeip::cfg::configuration_impl::*;
- *vsomeip::serializer;
- vsomeip::serializer::*;
- *vsomeip::deserializer;
- vsomeip::deserializer::*;
- *vsomeip::endpoint_definition;
- vsomeip::endpoint_definition*;
- *vsomeip::tcp*;
- vsomeip::tcp*;
- *vsomeip::udp*;
- vsomeip::udp*;
- *vsomeip::logger;
- vsomeip::logger::get*;
- *vsomeip::logger_impl;
- vsomeip::logger_impl::init*;
- *vsomeip::message_base_impl;
- *vsomeip::message_base_impl::*;
- *vsomeip::message_header_impl;
- *vsomeip::message_header_impl::*;
- *vsomeip::payload_impl;
- *vsomeip::payload_impl::*;
+ *vsomeip_v3::configuration;
+ vsomeip_v3::configuration::*;
+ *vsomeip_v3::cfg::configuration_impl;
+ vsomeip_v3::cfg::configuration_impl::*;
+ *vsomeip_v3::serializer;
+ vsomeip_v3::serializer::*;
+ *vsomeip_v3::deserializer;
+ vsomeip_v3::deserializer::*;
+ *vsomeip_v3::e2e::e2e_provider_impl;
+ vsomeip_v3::e2e::e2e_provider_impl::*;
+ *vsomeip_v3::endpoint_definition;
+ vsomeip_v3::endpoint_definition*;
+ *vsomeip_v3::tcp*;
+ vsomeip_v3::tcp*;
+ *vsomeip_v3::udp*;
+ vsomeip_v3::udp*;
+ *vsomeip_v3::logger;
+ vsomeip_v3::logger::get*;
+ *vsomeip_v3::logger_impl;
+ vsomeip_v3::logger_impl::init*;
+ *vsomeip_v3::message_base_impl;
+ *vsomeip_v3::message_base_impl::*;
+ *vsomeip_v3::message_header_impl;
+ *vsomeip_v3::message_header_impl::*;
+ *vsomeip_v3::payload_impl;
+ *vsomeip_v3::payload_impl::*;
+ *vsomeip_v3::policy_manager;
+ vsomeip_v3::policy_manager::*;
+ *vsomeip_v3::runtime;
+ vsomeip_v3::runtime::get*;
+ vsomeip_v3::runtime::set_property*;
+ *vsomeip_v3::application_impl;
+ vsomeip_v3::application_impl*;
+ *vsomeip_v3::eventgroupinfo;
+ vsomeip_v3::eventgroupinfo::*;
+ *vsomeip_v3::remote_subscription;
+ vsomeip_v3::remote_subscription::*;
+ *vsomeip_v3::security;
+ vsomeip_v3::security::*;
+ *vsomeip_v3::security_impl;
+ vsomeip_v3::security_impl::*;
+ *vsomeip_v3::servicegroup;
+ vsomeip_v3::servicegroup::*;
+ *vsomeip_v3::serviceinfo;
+ vsomeip_v3::serviceinfo::*;
+ *vsomeip_v3::sd::runtime;
+ vsomeip_v3::sd::runtime::*;
+ *vsomeip_v3::utility;
+ vsomeip_v3::utility::is*;
+ vsomeip_v3::utility::parse*;
+ *vsomeip_v3::plugin_manager;
+ vsomeip_v3::plugin_manager::*;
+ vsomeip_v3::tp::tp_reassembler::*;
+
+ vsomeip::runtime::*;
*vsomeip::runtime;
- vsomeip::runtime::get*;
- vsomeip::runtime::set_property*;
- *vsomeip::application_impl;
- vsomeip::application_impl*;
- *vsomeip::eventgroupinfo;
- vsomeip::eventgroupinfo::*;
- *vsomeip::servicegroup;
- vsomeip::servicegroup::*;
- *vsomeip::serviceinfo;
- vsomeip::serviceinfo::*;
- *vsomeip::sd::runtime;
- vsomeip::sd::runtime::*;
- *vsomeip::utility;
- vsomeip::utility::is*;
- vsomeip::utility::parse*;
- *vsomeip::plugin_manager;
- vsomeip::plugin_manager::*;
+ vsomeip::logger::*;
+ *vsomeip::logger;
};
vsomeip_plugin_init;
local:
diff --git a/implementation/compat/logging/include/logger.hpp b/implementation/compat/logging/include/logger.hpp
new file mode 100644
index 0000000..0f59502
--- /dev/null
+++ b/implementation/compat/logging/include/logger.hpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_LOGGER_HPP_
+#define VSOMEIP_COMPAT_LOGGER_HPP_
+
+#include <memory>
+
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/trivial.hpp>
+
+namespace vsomeip {
+
+class logger {
+public:
+ static std::shared_ptr<logger> get();
+
+ virtual ~logger() {}
+
+ virtual boost::log::sources::severity_logger_mt<
+ boost::log::trivial::severity_level> & get_internal() = 0;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_LOGGER_HPP_
diff --git a/implementation/compat/logging/include/logger_impl.hpp b/implementation/compat/logging/include/logger_impl.hpp
new file mode 100644
index 0000000..8aed18e
--- /dev/null
+++ b/implementation/compat/logging/include/logger_impl.hpp
@@ -0,0 +1,33 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_LOGGER_IMPL_HPP_
+#define VSOMEIP_COMPAT_LOGGER_IMPL_HPP_
+
+#include "logger.hpp"
+
+namespace vsomeip_v3 {
+class logger;
+} // namespace vsomeip_v3
+
+namespace vsomeip {
+
+class logger_impl
+ : public logger {
+public:
+ static std::shared_ptr<logger> get();
+
+ logger_impl();
+
+ boost::log::sources::severity_logger_mt<
+ boost::log::trivial::severity_level> & get_internal();
+
+private:
+ std::shared_ptr<vsomeip_v3::logger> impl_;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_LOGGER_IMPL_HPP_
diff --git a/implementation/compat/logging/src/logger.cpp b/implementation/compat/logging/src/logger.cpp
new file mode 100644
index 0000000..eb11707
--- /dev/null
+++ b/implementation/compat/logging/src/logger.cpp
@@ -0,0 +1,16 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/logger_impl.hpp"
+
+namespace vsomeip {
+
+std::shared_ptr<logger>
+logger::get() {
+
+ return (logger_impl::get());
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/logging/src/logger_impl.cpp b/implementation/compat/logging/src/logger_impl.cpp
new file mode 100644
index 0000000..4ceaaa7
--- /dev/null
+++ b/implementation/compat/logging/src/logger_impl.cpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/logger_impl.hpp"
+#include <vsomeip/internal/logger.hpp>
+
+namespace vsomeip {
+
+std::shared_ptr<logger>
+logger_impl::get() {
+
+ static std::shared_ptr<logger_impl> the_logger(
+ std::make_shared<logger_impl>()
+ );
+ return the_logger;
+}
+
+logger_impl::logger_impl()
+ : impl_(vsomeip_v3::logger::get()) {
+}
+
+boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> &
+logger_impl::get_internal() {
+
+ return impl_->get_internal();
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/message/include/message_base_impl.hpp b/implementation/compat/message/include/message_base_impl.hpp
new file mode 100644
index 0000000..6333965
--- /dev/null
+++ b/implementation/compat/message/include/message_base_impl.hpp
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_MESSAGE_BASE_IMPL_HPP_
+#define VSOMEIP_COMPAT_MESSAGE_BASE_IMPL_HPP_
+
+#include <compat/vsomeip/export.hpp>
+#include <compat/vsomeip/message.hpp>
+#include <vsomeip/message.hpp>
+
+namespace vsomeip_v3 {
+class message_impl;
+} // namespace vsomeip_v3
+
+namespace vsomeip {
+
+class message;
+
+class message_base_impl
+ : virtual public message_base {
+
+public:
+ VSOMEIP_EXPORT message_base_impl(const std::shared_ptr<vsomeip_v3::message> &_impl);
+ VSOMEIP_EXPORT virtual ~message_base_impl();
+
+ VSOMEIP_EXPORT message_t get_message() const;
+ VSOMEIP_EXPORT void set_message(message_t _message);
+
+ VSOMEIP_EXPORT service_t get_service() const;
+ VSOMEIP_EXPORT void set_service(service_t _service);
+
+ VSOMEIP_EXPORT instance_t get_instance() const;
+ VSOMEIP_EXPORT void set_instance(instance_t _instance);
+
+ VSOMEIP_EXPORT method_t get_method() const;
+ VSOMEIP_EXPORT void set_method(method_t _method);
+
+ VSOMEIP_EXPORT length_t get_length() const;
+
+ VSOMEIP_EXPORT request_t get_request() const;
+
+ VSOMEIP_EXPORT client_t get_client() const;
+ VSOMEIP_EXPORT void set_client(client_t _client);
+
+ VSOMEIP_EXPORT session_t get_session() const;
+ VSOMEIP_EXPORT void set_session(session_t _session);
+
+ VSOMEIP_EXPORT protocol_version_t get_protocol_version() const;
+
+ VSOMEIP_EXPORT interface_version_t get_interface_version() const;
+ VSOMEIP_EXPORT void set_interface_version(interface_version_t _interface_version);
+
+ VSOMEIP_EXPORT message_type_e get_message_type() const;
+ VSOMEIP_EXPORT void set_message_type(message_type_e _type);
+
+ VSOMEIP_EXPORT return_code_e get_return_code() const;
+ VSOMEIP_EXPORT void set_return_code(return_code_e _code);
+
+ VSOMEIP_EXPORT bool is_reliable() const;
+ VSOMEIP_EXPORT void set_reliable(bool _is_reliable);
+
+ VSOMEIP_EXPORT virtual bool is_initial() const;
+ VSOMEIP_EXPORT virtual void set_initial(bool _is_initial);
+
+ //VSOMEIP_EXPORT message * get_owner() const;
+ //VSOMEIP_EXPORT void set_owner(message *_owner);
+
+ VSOMEIP_EXPORT bool is_valid_crc() const;
+ VSOMEIP_EXPORT void set_is_valid_crc(bool _is_valid_crc);
+
+ inline std::shared_ptr<vsomeip_v3::message> get_impl() const { return impl_; }
+
+protected:
+ //message *owner_;
+ std::shared_ptr<vsomeip_v3::message> impl_;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_MESSAGE_BASE_IMPL_HPP_
diff --git a/implementation/compat/message/include/message_impl.hpp b/implementation/compat/message/include/message_impl.hpp
new file mode 100644
index 0000000..d773b97
--- /dev/null
+++ b/implementation/compat/message/include/message_impl.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_MESSAGE_IMPL_HPP_
+#define VSOMEIP_COMPAT_MESSAGE_IMPL_HPP_
+
+#if _MSC_VER >= 1300
+# pragma warning( disable : 4250 )
+#endif
+
+#include <compat/vsomeip/message.hpp>
+#include "message_base_impl.hpp"
+
+namespace vsomeip {
+
+class payload;
+
+class message_impl
+ : virtual public message_base_impl,
+ virtual public message {
+
+public:
+ VSOMEIP_EXPORT message_impl(const std::shared_ptr<vsomeip_v3::message> &_impl);
+ VSOMEIP_EXPORT virtual ~message_impl();
+
+ VSOMEIP_EXPORT std::shared_ptr< payload > get_payload() const;
+ VSOMEIP_EXPORT void set_payload(std::shared_ptr< payload > _payload);
+
+ VSOMEIP_EXPORT bool serialize(serializer *_to) const;
+ VSOMEIP_EXPORT bool deserialize(deserializer *_from);
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_MESSAGE_IMPL_HPP_
diff --git a/implementation/compat/message/include/payload_impl.hpp b/implementation/compat/message/include/payload_impl.hpp
new file mode 100644
index 0000000..1e8b493
--- /dev/null
+++ b/implementation/compat/message/include/payload_impl.hpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_PAYLOAD_IMPL_HPP_
+#define VSOMEIP_COMPAT_PAYLOAD_IMPL_HPP_
+
+#include <compat/vsomeip/payload.hpp>
+#include <vsomeip/payload.hpp>
+
+namespace vsomeip {
+
+class payload_impl
+ : public payload {
+
+public:
+ payload_impl(const std::shared_ptr<vsomeip_v3::payload> &_impl);
+ ~payload_impl();
+
+ bool operator ==(const payload &_other);
+
+ byte_t * get_data();
+ const byte_t * get_data() const;
+
+ void set_data(const byte_t *_data, length_t _length);
+ void set_data(const std::vector<byte_t> &_data);
+ void set_data(std::vector<byte_t> &&_data);
+
+ length_t get_length() const;
+ void set_capacity(length_t _length);
+
+ bool deserialize(deserializer *_from);
+ bool serialize(serializer *_to) const;
+
+ // Wraps
+ inline std::shared_ptr<vsomeip_v3::payload> get_impl() const { return impl_; }
+
+private:
+ std::shared_ptr<vsomeip_v3::payload> impl_;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_PAYLOAD_IMPL_HPP_
diff --git a/implementation/compat/message/src/message_base_impl.cpp b/implementation/compat/message/src/message_base_impl.cpp
new file mode 100644
index 0000000..3d646ce
--- /dev/null
+++ b/implementation/compat/message/src/message_base_impl.cpp
@@ -0,0 +1,166 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/runtime.hpp>
+
+#include "../include/message_base_impl.hpp"
+#include "../../../message/include/message_impl.hpp"
+
+namespace vsomeip {
+
+message_base_impl::message_base_impl(
+ const std::shared_ptr<vsomeip_v3::message> &_impl)
+ : impl_(_impl) {
+}
+
+message_base_impl::~message_base_impl() {
+}
+
+message_t
+message_base_impl::get_message() const {
+ return impl_->get_message();
+}
+
+void
+message_base_impl::set_message(message_t _message) {
+ impl_->set_message(_message);
+}
+
+service_t
+message_base_impl::get_service() const {
+ return impl_->get_service();
+}
+
+void
+message_base_impl::set_service(service_t _service) {
+ impl_->set_service(_service);
+}
+
+instance_t
+message_base_impl::get_instance() const {
+ return impl_->get_instance();
+}
+
+void
+message_base_impl::set_instance(instance_t _instance) {
+ impl_->set_instance(_instance);
+}
+
+method_t
+message_base_impl::get_method() const {
+ return impl_->get_method();
+}
+
+void
+message_base_impl::set_method(method_t _method) {
+ impl_->set_method(_method);
+}
+
+length_t
+message_base_impl::get_length() const {
+ return impl_->get_length();
+}
+
+request_t
+message_base_impl::get_request() const {
+ return impl_->get_request();
+}
+
+client_t
+message_base_impl::get_client() const {
+ return impl_->get_client();
+}
+
+void
+message_base_impl::set_client(client_t _client) {
+ impl_->set_client(_client);
+}
+
+session_t
+message_base_impl::get_session() const {
+ return impl_->get_session();
+}
+
+void
+message_base_impl::set_session(session_t _session) {
+ impl_->set_session(_session);
+}
+
+protocol_version_t
+message_base_impl::get_protocol_version() const {
+ return impl_->get_protocol_version();
+}
+
+interface_version_t
+message_base_impl::get_interface_version() const {
+ return impl_->get_interface_version();
+}
+
+void
+message_base_impl::set_interface_version(interface_version_t _interface_version) {
+ impl_->set_interface_version(_interface_version);
+}
+
+message_type_e
+message_base_impl::get_message_type() const {
+ return static_cast<message_type_e>(impl_->get_message_type());
+}
+
+void
+message_base_impl::set_message_type(message_type_e _type) {
+ impl_->set_message_type(static_cast<vsomeip_v3::message_type_e>(_type));
+}
+
+return_code_e
+message_base_impl::get_return_code() const {
+ return static_cast<return_code_e>(impl_->get_return_code());
+}
+
+void
+message_base_impl::set_return_code(return_code_e _code) {
+ impl_->set_return_code(static_cast<vsomeip_v3::return_code_e>(_code));
+}
+
+bool
+message_base_impl::is_reliable() const {
+ return impl_->is_reliable();
+}
+
+void
+message_base_impl::set_reliable(bool _is_reliable) {
+ impl_->set_reliable(_is_reliable);
+}
+
+bool
+message_base_impl::is_initial() const {
+ return impl_->is_initial();
+}
+
+void
+message_base_impl::set_initial(bool _is_initial) {
+ impl_->set_initial(_is_initial);
+}
+/*
+message *
+message_base_impl::get_owner() const {
+ return owner_;
+}
+
+void
+message_base_impl::set_owner(message *_owner) {
+ owner_ = _owner;
+}
+*/
+bool
+message_base_impl::is_valid_crc() const {
+ return impl_->is_valid_crc();
+}
+
+void
+message_base_impl::set_is_valid_crc(bool _is_valid_crc) {
+ impl_->set_check_result(_is_valid_crc == true ? 1 : 0);
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/message/src/message_impl.cpp b/implementation/compat/message/src/message_impl.cpp
new file mode 100644
index 0000000..e7e7af1
--- /dev/null
+++ b/implementation/compat/message/src/message_impl.cpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/message_impl.hpp"
+#include "../include/payload_impl.hpp"
+#include "../../../message/include/message_impl.hpp"
+
+namespace vsomeip {
+
+message_impl::message_impl(const std::shared_ptr<vsomeip_v3::message> &_impl)
+ : message_base_impl(_impl) {
+}
+
+message_impl::~message_impl() {
+}
+
+std::shared_ptr< payload >
+message_impl::get_payload() const {
+
+ return std::make_shared<payload_impl>(impl_->get_payload());
+}
+
+void
+message_impl::set_payload(std::shared_ptr< payload > _payload) {
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->set_payload(its_payload->get_impl());
+ } else {
+ impl_->set_payload(nullptr);
+ }
+}
+
+bool
+message_impl::serialize(serializer *_to) const {
+
+ (void)_to;
+ VSOMEIP_ERROR << "message_impl::" << __func__
+ << ": Must not be called from compatibility layer.";
+ return false;
+}
+
+bool
+message_impl::deserialize(deserializer *_from) {
+
+ (void)_from;
+ VSOMEIP_ERROR << "message_impl::" << __func__
+ << ": Must not be called from compatibility layer.";
+ return false;
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/message/src/payload_impl.cpp b/implementation/compat/message/src/payload_impl.cpp
new file mode 100644
index 0000000..5d78304
--- /dev/null
+++ b/implementation/compat/message/src/payload_impl.cpp
@@ -0,0 +1,95 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/payload.hpp>
+#include <vsomeip/runtime.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/payload_impl.hpp"
+
+namespace vsomeip {
+
+payload_impl::payload_impl(const std::shared_ptr<vsomeip_v3::payload> &_impl)
+ : impl_(_impl) {
+}
+
+payload_impl::~payload_impl() {
+}
+
+bool
+payload_impl::operator==(const payload &_other) {
+
+ bool is_equal(true);
+ try {
+ const payload_impl &other = dynamic_cast< const payload_impl & >(_other);
+ is_equal = (*(impl_.get()) == *(other.impl_.get()));
+ }
+ catch (...) {
+ is_equal = false;
+ }
+ return is_equal;
+}
+
+byte_t *
+payload_impl::get_data() {
+
+ return impl_->get_data();
+}
+
+const byte_t *
+payload_impl::get_data() const {
+
+ return impl_->get_data();
+}
+
+length_t
+payload_impl::get_length() const {
+
+ return impl_->get_length();
+}
+
+void
+payload_impl::set_capacity(length_t _capacity) {
+
+ impl_->set_capacity(_capacity);
+}
+
+void
+payload_impl::set_data(const byte_t *_data, const length_t _length) {
+
+ impl_->set_data(_data, _length);
+}
+
+void
+payload_impl::set_data(const std::vector< byte_t > &_data) {
+
+ impl_->set_data(_data);
+}
+
+void
+payload_impl::set_data(std::vector< byte_t > &&_data) {
+
+ impl_->set_data(_data);
+}
+
+bool
+payload_impl::serialize(serializer *_to) const {
+
+ (void)_to;
+ VSOMEIP_ERROR << "payload_impl::" << __func__
+ << ": Must not be called from compatibility layer.";
+ return false;
+}
+
+bool
+payload_impl::deserialize(deserializer *_from) {
+
+ (void)_from;
+ VSOMEIP_ERROR << "payload_impl::" << __func__
+ << ": Must not be called from compatibility layer.";
+ return false;
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/runtime/include/application_impl.hpp b/implementation/compat/runtime/include/application_impl.hpp
new file mode 100644
index 0000000..8c3b4e0
--- /dev/null
+++ b/implementation/compat/runtime/include/application_impl.hpp
@@ -0,0 +1,202 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_APPLICATION_IMPL_HPP_
+#define VSOMEIP_COMPAT_APPLICATION_IMPL_HPP_
+
+#include <map>
+#include <mutex>
+
+#include <compat/vsomeip/application.hpp>
+
+namespace vsomeip_v3 {
+class application;
+} // namespace vsomeip_v3
+
+namespace vsomeip {
+
+class application_impl
+ : public application {
+public:
+ application_impl(const std::string &_name);
+ ~application_impl();
+
+ const std::string & get_name() const;
+ client_t get_client() const;
+
+ void set_configuration(
+ const std::shared_ptr<configuration> _configuration);
+
+ bool init();
+ void start();
+ void stop();
+
+ void offer_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
+ void stop_offer_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
+
+ void offer_event(service_t _service, instance_t _instance, event_t _event,
+ const std::set<eventgroup_t> &_eventgroups, bool _is_field);
+ void stop_offer_event(service_t _service, instance_t _instance,
+ event_t _event);
+
+ void request_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _use_exclusive_proxy);
+ void release_service(service_t _service, instance_t _instance);
+
+ void request_event(service_t _service, instance_t _instance,
+ event_t _event, const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field);
+ void release_event(service_t _service, instance_t _instance,
+ event_t _event);
+
+ void subscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ subscription_type_e _subscription_type,
+ event_t _event);
+ void unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup);
+
+ bool is_available(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) const;
+
+ void send(std::shared_ptr<message> _message, bool _flush);
+ void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload) const;
+ void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client) const;
+
+ void register_state_handler(state_handler_t _handler);
+ void unregister_state_handler();
+
+ void register_message_handler(service_t _service,
+ instance_t _instance, method_t _method,
+ message_handler_t _handler);
+ void unregister_message_handler(service_t _service,
+ instance_t _instance, method_t _method);
+
+ void register_availability_handler(service_t _service,
+ instance_t _instance, availability_handler_t _handler,
+ major_version_t _major, minor_version_t _minor);
+ void unregister_availability_handler(service_t _service,
+ instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
+
+ void register_subscription_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ subscription_handler_t _handler);
+ void unregister_subscription_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup);
+
+ void register_subscription_error_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ error_handler_t _handler);
+ void unregister_subscription_error_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup);
+
+ void clear_all_handler();
+
+ bool is_routing() const;
+
+ void offer_event(service_t _service,
+ instance_t _instance, event_t _event,
+ const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field,
+ std::chrono::milliseconds _cycle,
+ bool _change_resets_cycle,
+ const epsilon_change_func_t &_epsilon_change_func);
+
+ void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force) const;
+
+ void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force) const;
+
+ bool are_available(available_t &_available,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) const;
+
+ void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) const;
+
+ void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force, bool _flush) const;
+
+ void set_routing_state(routing_state_e _routing_state);
+
+ void unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
+
+ void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler);
+
+ void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler, bool _is_selective);
+
+ void get_offered_services_async(
+ offer_type_e _offer_type, offered_services_handler_t _handler);
+
+ void set_watchdog_handler(
+ watchdog_handler_t _handler, std::chrono::seconds _interval);
+
+ virtual void register_async_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ async_subscription_handler_t _handler);
+
+ virtual void set_offer_acceptance_required(
+ ip_address_t _address, const std::string _path, bool _enable);
+
+ virtual offer_acceptance_map_type_t get_offer_acceptance_required();
+
+ virtual void register_offer_acceptance_handler(
+ offer_acceptance_handler_t _handler);
+
+ virtual void register_reboot_notification_handler(
+ reboot_notification_handler_t _handler);
+
+ virtual void register_routing_ready_handler(
+ routing_ready_handler_t _handler);
+
+ virtual void register_routing_state_handler(
+ routing_state_handler_t _handler);
+
+ virtual bool update_service_configuration(
+ service_t _service, instance_t _instance,
+ std::uint16_t _port, bool _reliable,
+ bool _magic_cookies_enabled, bool _offer);
+
+ virtual void update_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid,
+ std::shared_ptr<policy> _policy, std::shared_ptr<payload> _payload,
+ security_update_handler_t _handler);
+
+ virtual void remove_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid, security_update_handler_t _handler);
+
+private:
+ bool is_selective_event(
+ vsomeip::service_t _service, vsomeip::instance_t _instance,
+ const std::set<vsomeip::eventgroup_t> &_eventgroups);
+
+private:
+ std::shared_ptr<vsomeip_v3::application> impl_;
+
+ std::map<service_t,
+ std::map<instance_t, std::set<eventgroup_t> > > eventgroups_;
+ std::mutex eventgroups_mutex_;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_APPLICATION_IMPL_HPP_
diff --git a/implementation/compat/runtime/include/runtime_impl.hpp b/implementation/compat/runtime/include/runtime_impl.hpp
new file mode 100644
index 0000000..caadbfa
--- /dev/null
+++ b/implementation/compat/runtime/include/runtime_impl.hpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_COMPAT_RUNTIME_IMPL_HPP_
+#define VSOMEIP_COMPAT_RUNTIME_IMPL_HPP_
+
+#include <map>
+#include <mutex>
+
+#include <compat/vsomeip/runtime.hpp>
+
+namespace vsomeip {
+
+class runtime_impl
+ : public runtime {
+public:
+ static std::string get_property(const std::string &_name);
+ static void set_property(const std::string &_name, const std::string &_value);
+
+ static std::shared_ptr<runtime> get();
+
+ ~runtime_impl();
+
+ std::shared_ptr<application> create_application(
+ const std::string &_name = "");
+
+ std::shared_ptr<message> create_message(bool _reliable = false) const;
+
+ std::shared_ptr<message> create_request(bool _reliable = false) const;
+
+ std::shared_ptr<message> create_response(
+ const std::shared_ptr<message> &_request) const;
+
+ std::shared_ptr<message> create_notification(
+ bool _reliable = false) const;
+
+ std::shared_ptr<payload> create_payload() const;
+ std::shared_ptr<payload> create_payload(
+ const byte_t *_data, uint32_t _size) const;
+ virtual std::shared_ptr<payload> create_payload(
+ const std::vector<byte_t> &_data) const;
+
+ std::shared_ptr<application> get_application(
+ const std::string &_name) const;
+ void remove_application( const std::string &_name);
+
+private:
+ static std::shared_ptr<runtime> the_runtime_;
+
+ std::map<std::string, std::weak_ptr<application> > applications_;
+ mutable std::mutex applications_mutex_;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_COMPAT_RUNTIME_IMPL_HPP_
diff --git a/implementation/compat/runtime/src/application_impl.cpp b/implementation/compat/runtime/src/application_impl.cpp
new file mode 100644
index 0000000..559eae3
--- /dev/null
+++ b/implementation/compat/runtime/src/application_impl.cpp
@@ -0,0 +1,649 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/application.hpp>
+#include <vsomeip/runtime.hpp>
+#include <compat/vsomeip/runtime.hpp>
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/application_impl.hpp"
+#include "../../message/include/message_impl.hpp"
+#include "../../message/include/payload_impl.hpp"
+
+namespace vsomeip {
+
+application_impl::application_impl(const std::string &_name) {
+
+ impl_ = vsomeip_v3::runtime::get()->create_application(_name);
+}
+
+application_impl::~application_impl() {
+
+ vsomeip::runtime::get()->remove_application(impl_->get_name());
+}
+
+const std::string &
+application_impl::get_name() const {
+
+ return impl_->get_name();
+}
+
+client_t
+application_impl::get_client() const {
+
+ return impl_->get_client();
+}
+
+void
+application_impl::set_configuration(const std::shared_ptr<configuration> _configuration) {
+
+ (void)_configuration;
+ // Not implemented
+}
+
+bool
+application_impl::init() {
+
+ return impl_->init();
+}
+
+void
+application_impl::start() {
+
+ impl_->start();
+}
+
+void
+application_impl::stop() {
+
+ impl_->stop();
+}
+
+void
+application_impl::offer_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ impl_->offer_service(_service, _instance, _major, _minor);
+}
+
+void
+application_impl::stop_offer_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ impl_->stop_offer_service(_service, _instance, _major, _minor);
+}
+
+void
+application_impl::offer_event(service_t _service, instance_t _instance,
+ event_t _event, const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field) {
+
+ // Set event type
+ vsomeip_v3::event_type_e its_type(vsomeip_v3::event_type_e::ET_EVENT);
+ if (_is_field)
+ its_type = vsomeip_v3::event_type_e::ET_FIELD;
+ else {
+ // Find out whether the event is selective. Requires a preceding
+ // call to "register_subscription_handler".
+ // Note: The check can be done on the eventgroup(s) as selective
+ // events own an exclusive eventgroup.
+ const bool is_selective
+ = is_selective_event(_service, _instance, _eventgroups);
+
+ if (is_selective)
+ its_type = vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT;
+ }
+
+ impl_->offer_event(_service, _instance, _event, _eventgroups, its_type);
+}
+
+void
+application_impl::stop_offer_event(service_t _service, instance_t _instance,
+ event_t _event) {
+
+ impl_->stop_offer_event(_service, _instance, _event);
+}
+
+void
+application_impl::request_service(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _use_exclusive_proxy) {
+
+ (void)_use_exclusive_proxy;
+ impl_->request_service(_service, _instance, _major, _minor);
+}
+
+void
+application_impl::release_service(service_t _service, instance_t _instance) {
+
+ impl_->release_service(_service, _instance);
+}
+
+void
+application_impl::request_event(service_t _service, instance_t _instance,
+ event_t _event, const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field) {
+
+ const vsomeip_v3::event_type_e its_type = (_is_field) ?
+ vsomeip_v3::event_type_e::ET_FIELD :
+ vsomeip_v3::event_type_e::ET_EVENT;
+ impl_->request_event(_service, _instance, _event, _eventgroups, its_type);
+}
+
+void
+application_impl::release_event(service_t _service, instance_t _instance,
+ event_t _event) {
+
+ impl_->release_event(_service, _instance, _event);
+}
+
+void
+application_impl::subscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ subscription_type_e _subscription_type, event_t _event) {
+
+ (void)_subscription_type; // unused in v3
+ impl_->subscribe(_service, _instance, _eventgroup, _major, _event);
+}
+
+void
+application_impl::unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup) {
+
+ impl_->unsubscribe(_service, _instance, _eventgroup);
+}
+
+bool
+application_impl::is_available(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) const {
+
+ return impl_->is_available(_service, _instance, _major, _minor);
+}
+
+void
+application_impl::send(std::shared_ptr<message> _message, bool _flush = true) {
+
+ (void)_flush; // unused in v3
+ if (_message) {
+ auto its_message = std::dynamic_pointer_cast<message_impl>(_message);
+ impl_->send(its_message->get_impl());
+ }
+}
+
+void
+application_impl::notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload) const {
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify(_service, _instance, _event, its_payload->get_impl());
+ } else {
+ impl_->notify(_service, _instance, _event, nullptr);
+ }
+}
+
+void
+application_impl::notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client) const {
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify_one(_service, _instance, _event, its_payload->get_impl(), _client);
+ } else {
+ impl_->notify_one(_service, _instance, _event, nullptr, _client);
+ }
+}
+
+void
+application_impl::register_state_handler(state_handler_t _handler) {
+
+ impl_->register_state_handler(
+ [_handler](vsomeip_v3::state_type_e _state) {
+ _handler(static_cast<vsomeip::state_type_e>(_state));
+ }
+ );
+}
+
+void
+application_impl::unregister_state_handler() {
+
+ impl_->unregister_state_handler();
+}
+
+void
+application_impl::register_message_handler(
+ service_t _service, instance_t _instance, method_t _method,
+ message_handler_t _handler) {
+
+ impl_->register_message_handler(_service, _instance, _method,
+ [_handler](const std::shared_ptr<vsomeip_v3::message> &_message) {
+ auto its_message = std::make_shared<message_impl>(_message);
+ _handler(its_message);
+ }
+ );
+}
+
+void
+application_impl::unregister_message_handler(
+ service_t _service, instance_t _instance, method_t _method) {
+
+ impl_->unregister_message_handler(_service, _instance, _method);
+}
+
+void
+application_impl::register_availability_handler(
+ service_t _service, instance_t _instance,
+ availability_handler_t _handler,
+ major_version_t _major, minor_version_t _minor) {
+
+ impl_->register_availability_handler(_service, _instance, _handler,
+ _major, _minor);
+}
+
+void
+application_impl::unregister_availability_handler(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ impl_->unregister_availability_handler(_service, _instance, _major, _minor);
+}
+
+void
+application_impl::register_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ subscription_handler_t _handler) {
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ eventgroups_[_service][_instance].insert(_eventgroup);
+ }
+
+ impl_->register_subscription_handler(_service, _instance, _eventgroup,
+ [_handler](client_t _client, vsomeip::uid_t _uid,
+ vsomeip::gid_t _gid, bool _accepted){
+ (void)_uid;
+ (void)_gid;
+ return _handler(_client, _accepted);
+ }
+ );
+}
+
+void
+application_impl::unregister_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+
+ impl_->unregister_subscription_handler(_service, _instance, _eventgroup);
+}
+
+
+// subscription_error_handlers were exclusively used for selective events.
+// As selective events use an exclusive eventgroup, the event identifier
+// itself is not needed and we can use a dummy.
+#define ERROR_HANDLER_DUMMY_EVENT 0xFFFE
+
+void
+application_impl::register_subscription_error_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ error_handler_t _handler) {
+
+ impl_->register_subscription_status_handler(
+ _service, _instance, _eventgroup, ERROR_HANDLER_DUMMY_EVENT,
+ [_handler](service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event,
+ uint16_t _error) {
+ (void)_service;
+ (void)_instance;
+ (void)_eventgroup;
+ (void)_event;
+
+ _handler(_error);
+ },
+ true
+ );
+}
+
+void
+application_impl::unregister_subscription_error_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+
+ impl_->unregister_subscription_status_handler(_service, _instance,
+ _eventgroup, ERROR_HANDLER_DUMMY_EVENT);
+}
+
+void
+application_impl::clear_all_handler() {
+
+ impl_->clear_all_handler();
+}
+
+bool
+application_impl::is_routing() const {
+
+ return impl_->is_routing();
+}
+
+void
+application_impl::offer_event(
+ service_t _service, instance_t _instance, event_t _event,
+ const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field,
+ std::chrono::milliseconds _cycle,
+ bool _change_resets_cycle,
+ const epsilon_change_func_t &_epsilon_change_func) {
+
+ // Set event type
+ vsomeip_v3::event_type_e its_type(vsomeip_v3::event_type_e::ET_EVENT);
+ if (_is_field)
+ its_type = vsomeip_v3::event_type_e::ET_FIELD;
+ else {
+ // Find out whether the event is selective. Requires a preceding
+ // call to "register_subscription_handler".
+ // Note: The check can be done on the eventgroup(s) as selective
+ // events own an exclusive eventgroup.
+ const bool is_selective
+ = is_selective_event(_service, _instance, _eventgroups);
+
+ if (is_selective)
+ its_type = vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT;
+ }
+
+ impl_->offer_event(_service, _instance, _event, _eventgroups,
+ its_type, _cycle, _change_resets_cycle, true,
+ [_epsilon_change_func](
+ const std::shared_ptr<vsomeip_v3::payload> &_lhs,
+ const std::shared_ptr<vsomeip_v3::payload> &_rhs) {
+ auto its_lhs = std::make_shared<payload_impl>(_lhs);
+ auto its_rhs = std::make_shared<payload_impl>(_rhs);
+ return _epsilon_change_func(its_lhs, its_rhs);
+ }
+ );
+}
+
+void
+application_impl::notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload, bool _force) const {
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify(_service, _instance, _event, its_payload->get_impl(),
+ _force);
+ } else {
+ impl_->notify(_service, _instance, _event, nullptr, _force);
+ }
+}
+
+void
+application_impl::notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force) const {
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify_one(_service, _instance, _event, its_payload->get_impl(),
+ _client, _force);
+ } else {
+ impl_->notify_one(_service, _instance, _event, nullptr, _client,
+ _force);
+ }
+}
+
+bool
+application_impl::are_available(available_t &_available,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) const {
+
+ return impl_->are_available(_available, _service, _instance, _major,
+ _minor);
+}
+
+void
+application_impl::notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) const {
+
+ (void)_flush; // unused in v3
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify(_service, _instance, _event, its_payload->get_impl(),
+ _force);
+ } else {
+ impl_->notify(_service, _instance, _event, nullptr, _force);
+ }
+}
+
+void
+application_impl::notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force, bool _flush) const {
+
+ (void)_flush; // unused in v3
+
+ if (_payload) {
+ auto its_payload = std::dynamic_pointer_cast<payload_impl>(_payload);
+ impl_->notify_one(_service, _instance, _event, its_payload->get_impl(),
+ _client, _force);
+ } else {
+ impl_->notify_one(_service, _instance, _event, nullptr, _client,
+ _force);
+ }
+}
+
+void
+application_impl::set_routing_state(routing_state_e _routing_state) {
+
+ impl_->set_routing_state(
+ static_cast<vsomeip_v3::routing_state_e>(_routing_state));
+}
+
+void
+application_impl::unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) {
+
+ impl_->unsubscribe(_service, _instance, _eventgroup, _event);
+}
+
+void
+application_impl::register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler) {
+
+ register_subscription_status_handler(_service, _instance,
+ _eventgroup, _event, _handler, false);
+}
+
+void
+application_impl::register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler, bool _is_selective) {
+ if (_is_selective) {
+ std::set<vsomeip::eventgroup_t> its_eventgroups;
+ its_eventgroups.insert(_eventgroup);
+ // An application may call "register_event" before
+ // "register_subscription_status_handler". While the call to
+ // "register_subscription_status_handler" contains the information
+ // whether an event is selective, the call to "register_event" does
+ // not. Therefore, we re-register the event with correct event type
+ // here.
+ impl_->request_event(_service, _instance, _event, its_eventgroups,
+ vsomeip_v3::event_type_e::ET_SELECTIVE_EVENT);
+ }
+
+ impl_->register_subscription_status_handler(_service, _instance,
+ _eventgroup, _event,
+ [_handler](const vsomeip_v3::service_t _service,
+ const vsomeip_v3::instance_t _instance,
+ const vsomeip_v3::eventgroup_t _eventgroup,
+ const vsomeip_v3::event_t _event,
+ const uint16_t _error) {
+
+ if (_handler)
+ _handler(_service, _instance, _eventgroup, _event, _error);
+ },
+ _is_selective);
+}
+
+void
+application_impl::get_offered_services_async(
+ offer_type_e _offer_type, offered_services_handler_t _handler) {
+
+ impl_->get_offered_services_async(
+ static_cast<vsomeip_v3::offer_type_e>(_offer_type), _handler);
+}
+
+void
+application_impl::set_watchdog_handler(
+ watchdog_handler_t _handler, std::chrono::seconds _interval) {
+
+ impl_->set_watchdog_handler(_handler, _interval);
+}
+
+void
+application_impl::register_async_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ async_subscription_handler_t _handler) {
+
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ eventgroups_[_service][_instance].insert(_eventgroup);
+ }
+ impl_->register_async_subscription_handler(_service, _instance,
+ _eventgroup, [_handler](client_t _client,
+ vsomeip::uid_t _uid, vsomeip::gid_t _gid, bool _accepted,
+ std::function<void(const bool)> _handler2) {
+ (void)_uid;
+ (void)_gid;
+ _handler(_client, _accepted, _handler2);
+ });
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// The following methods are not implemented as they should only be used by
+// plugin implementations that are not intended to run in compatibility mode
+////////////////////////////////////////////////////////////////////////////////
+void
+application_impl::set_offer_acceptance_required(
+ ip_address_t _address, const std::string _path, bool _enable) {
+
+ (void)_address;
+ (void)_path;
+ (void)_enable;
+
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+vsomeip::application::offer_acceptance_map_type_t
+application_impl::get_offer_acceptance_required() {
+
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+ return vsomeip::application::offer_acceptance_map_type_t();
+}
+
+void
+application_impl::register_offer_acceptance_handler(
+ offer_acceptance_handler_t _handler) {
+
+ (void)_handler;
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+void
+application_impl::register_reboot_notification_handler(
+ reboot_notification_handler_t _handler) {
+
+ (void)_handler;
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+void
+application_impl::register_routing_ready_handler(
+ routing_ready_handler_t _handler) {
+
+ (void)_handler;
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+void
+application_impl::register_routing_state_handler(
+ routing_state_handler_t _handler) {
+
+ (void)_handler;
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+bool
+application_impl::update_service_configuration(
+ service_t _service, instance_t _instance,
+ std::uint16_t _port, bool _reliable,
+ bool _magic_cookies_enabled, bool _offer) {
+
+ (void)_service;
+ (void)_instance;
+ (void)_port;
+ (void)_reliable;
+ (void)_magic_cookies_enabled;
+ (void)_offer;
+
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+ return false;
+}
+
+void
+application_impl::update_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid,
+ std::shared_ptr<policy> _policy, std::shared_ptr<payload> _payload,
+ security_update_handler_t _handler) {
+
+ (void)_uid;
+ (void)_gid;
+ (void)_policy;
+ (void)_payload;
+ (void)_handler;
+
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+void
+application_impl::remove_security_policy_configuration(
+ uint32_t _uid, uint32_t _gid, security_update_handler_t _handler) {
+
+ (void)_uid;
+ (void)_gid;
+ (void)_handler;
+
+ VSOMEIP_ERROR << __func__ << ": Must not be called from compatibility layer.";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private helper
+////////////////////////////////////////////////////////////////////////////////
+
+bool
+application_impl::is_selective_event(
+ vsomeip::service_t _service, vsomeip::instance_t _instance,
+ const std::set<vsomeip::eventgroup_t> &_eventgroups) {
+
+ bool is_selective(false);
+
+ std::lock_guard<std::mutex> its_events_lock(eventgroups_mutex_);
+ const auto its_service = eventgroups_.find(_service);
+ if (its_service != eventgroups_.end()) {
+ const auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ for (const auto eg : _eventgroups) {
+ const auto its_egrp = its_instance->second.find(eg);
+ if (its_egrp != its_instance->second.end()) {
+ is_selective = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return is_selective;
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/runtime/src/runtime.cpp b/implementation/compat/runtime/src/runtime.cpp
new file mode 100644
index 0000000..40075a8
--- /dev/null
+++ b/implementation/compat/runtime/src/runtime.cpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <compat/vsomeip/runtime.hpp>
+#include "../include/runtime_impl.hpp"
+
+namespace vsomeip {
+
+std::string
+runtime::get_property(const std::string &_name) {
+
+ return runtime_impl::get_property(_name);
+}
+
+void
+runtime::set_property(const std::string &_name, const std::string &_value) {
+
+ runtime_impl::set_property(_name, _value);
+}
+
+std::shared_ptr<runtime>
+runtime::get() {
+
+ return runtime_impl::get();
+}
+
+} // namespace vsomeip
diff --git a/implementation/compat/runtime/src/runtime_impl.cpp b/implementation/compat/runtime/src/runtime_impl.cpp
new file mode 100644
index 0000000..b434e5a
--- /dev/null
+++ b/implementation/compat/runtime/src/runtime_impl.cpp
@@ -0,0 +1,125 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <compat/vsomeip/defines.hpp>
+#include <vsomeip/runtime.hpp>
+
+#include "../include/application_impl.hpp"
+#include "../include/runtime_impl.hpp"
+#include "../../message/include/message_impl.hpp"
+#include "../../message/include/payload_impl.hpp"
+
+namespace vsomeip {
+
+std::shared_ptr<runtime> runtime_impl::the_runtime_
+ = std::make_shared<runtime_impl>();
+
+std::string
+runtime_impl::get_property(const std::string &_name) {
+
+ return vsomeip_v3::runtime::get_property(_name);
+}
+
+void
+runtime_impl::set_property(const std::string &_name, const std::string &_value) {
+
+ vsomeip_v3::runtime::set_property(_name, _value);
+}
+
+std::shared_ptr<runtime>
+runtime_impl::get() {
+
+ return the_runtime_;
+}
+
+runtime_impl::~runtime_impl() {
+}
+
+std::shared_ptr<application>
+runtime_impl::create_application(const std::string &_name) {
+
+ auto its_application = std::make_shared<application_impl>(_name);
+
+ {
+ std::lock_guard<std::mutex> its_lock(applications_mutex_);
+ applications_[its_application->get_name()] = its_application;
+ }
+
+ return (its_application);
+}
+
+std::shared_ptr<message>
+runtime_impl::create_message(bool _reliable) const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_message(_reliable);
+ return (std::make_shared<message_impl>(its_impl));
+}
+
+std::shared_ptr<message>
+runtime_impl::create_request(bool _reliable) const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_request(_reliable);
+ return (std::make_shared<message_impl>(its_impl));
+}
+
+std::shared_ptr<message>
+runtime_impl::create_response(const std::shared_ptr<message> &_request) const {
+
+ auto its_request = std::dynamic_pointer_cast<message_impl>(_request);
+ auto its_impl = vsomeip_v3::runtime::get()->create_response(
+ its_request->get_impl());
+ return (std::make_shared<message_impl>(its_impl));
+}
+
+std::shared_ptr<message>
+runtime_impl::create_notification(bool _reliable) const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_notification(_reliable);
+ return (std::make_shared<message_impl>(its_impl));
+}
+
+std::shared_ptr<payload>
+runtime_impl::create_payload() const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_payload();
+ return (std::make_shared<payload_impl>(its_impl));
+}
+
+std::shared_ptr<payload>
+runtime_impl::create_payload(const byte_t *_data, uint32_t _size) const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_payload(_data, _size);
+ return (std::make_shared<payload_impl>(its_impl));
+}
+
+std::shared_ptr<payload>
+runtime_impl::create_payload(const std::vector<byte_t> &_data) const {
+
+ auto its_impl = vsomeip_v3::runtime::get()->create_payload(_data);
+ return (std::make_shared<payload_impl>(its_impl));
+}
+
+std::shared_ptr<application>
+runtime_impl::get_application(const std::string &_name) const {
+
+ std::lock_guard<std::mutex> its_lock(applications_mutex_);
+ auto found_application = applications_.find(_name);
+ if (found_application != applications_.end())
+ return found_application->second.lock();
+
+ return (nullptr);
+}
+
+void
+runtime_impl::remove_application(const std::string &_name) {
+
+ std::lock_guard<std::mutex> its_lock(applications_mutex_);
+ auto found_application = applications_.find(_name);
+ if(found_application != applications_.end()) {
+ applications_.erase(_name);
+ }
+}
+
+} // namespace vsomeip
diff --git a/implementation/configuration/include/client.hpp b/implementation/configuration/include/client.hpp
index 81ed890..7758eca 100644
--- a/implementation/configuration/include/client.hpp
+++ b/implementation/configuration/include/client.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_CLIENT_HPP
-#define VSOMEIP_CFG_CLIENT_HPP
+#ifndef VSOMEIP_V3_CFG_CLIENT_HPP
+#define VSOMEIP_V3_CFG_CLIENT_HPP
#include <map>
#include <memory>
@@ -12,7 +12,7 @@
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct client {
@@ -29,6 +29,6 @@ struct client {
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_CLIENT_HPP
+#endif // VSOMEIP_V3_CFG_CLIENT_HPP
diff --git a/implementation/configuration/include/configuration.hpp b/implementation/configuration/include/configuration.hpp
index 9740a79..aac5422 100644
--- a/implementation/configuration/include/configuration.hpp
+++ b/implementation/configuration/include/configuration.hpp
@@ -3,13 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CONFIGURATION_HPP
-#define VSOMEIP_CONFIGURATION_HPP
+#ifndef VSOMEIP_V3_CONFIGURATION_HPP
+#define VSOMEIP_V3_CONFIGURATION_HPP
#include <map>
#include <memory>
#include <set>
#include <string>
+#include <chrono>
#include <boost/asio/ip/address.hpp>
#include <boost/log/trivial.hpp>
@@ -19,24 +20,35 @@
#include <vsomeip/plugin.hpp>
#include <vsomeip/primitive_types.hpp>
-#include "internal.hpp"
#include "trace.hpp"
#include "../../e2e_protection/include/e2exf/config.hpp"
#include "e2e.hpp"
-#include "policy.hpp"
#include "debounce.hpp"
+#ifdef ANDROID
+#include "internal_android.hpp"
+#else
+#include "internal.hpp"
+#endif // ANDROID
+
+#include "../../security/include/policy.hpp"
+
#define VSOMEIP_CONFIG_PLUGIN_VERSION 1
-namespace vsomeip {
+namespace vsomeip_v3 {
class event;
class configuration {
public:
- virtual ~configuration() {}
+ virtual ~configuration()
+#ifndef ANDROID
+ {}
+#else
+ ;
+#endif
virtual bool load(const std::string &_name) = 0;
virtual bool remote_offer_info_add(service_t _service,
@@ -55,8 +67,9 @@ public:
virtual const boost::asio::ip::address & get_unicast_address() const = 0;
virtual const boost::asio::ip::address& get_netmask() const = 0;
- virtual unsigned short get_diagnosis_address() const = 0;
- virtual std::uint16_t get_diagnosis_mask() const = 0;
+ virtual const std::string &get_device() const = 0;
+ virtual diagnosis_t get_diagnosis_address() const = 0;
+ virtual diagnosis_t get_diagnosis_mask() const = 0;
virtual bool is_v4() const = 0;
virtual bool is_v6() const = 0;
@@ -77,6 +90,17 @@ public:
virtual uint16_t get_unreliable_port(service_t _service,
instance_t _instance) const = 0;
+ virtual void get_configured_timing_requests(
+ service_t _service, std::string _ip_target,
+ std::uint16_t _port_target, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const = 0;
+ virtual void get_configured_timing_responses(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const = 0;
+
virtual bool is_someip(service_t _service, instance_t _instance) const = 0;
virtual bool get_client_port(service_t _service, instance_t _instance,
@@ -103,6 +127,7 @@ public:
virtual std::uint32_t get_max_message_size_local() const = 0;
virtual std::uint32_t get_max_message_size_reliable(const std::string& _address,
std::uint16_t _port) const = 0;
+ virtual std::uint32_t get_max_message_size_unreliable() const = 0;
virtual std::uint32_t get_buffer_shrink_threshold() const = 0;
virtual bool supports_selective_broadcasts(boost::asio::ip::address _address) const = 0;
@@ -111,7 +136,10 @@ public:
virtual bool is_local_service(service_t _service, instance_t _instance) const = 0;
- virtual bool is_event_reliable(service_t _service, instance_t _instance, event_t _event) const = 0;
+ virtual reliability_type_e get_event_reliability(
+ service_t _service, instance_t _instance, event_t _event) const = 0;
+ virtual reliability_type_e get_service_reliability(
+ service_t _service, instance_t _instance) const = 0;
// Service Discovery configuration
virtual bool is_sd_enabled() const = 0;
@@ -120,8 +148,8 @@ public:
virtual uint16_t get_sd_port() const = 0;
virtual const std::string & get_sd_protocol() const = 0;
- virtual int32_t get_sd_initial_delay_min() const = 0;
- virtual int32_t get_sd_initial_delay_max() const = 0;
+ virtual uint32_t get_sd_initial_delay_min() const = 0;
+ virtual uint32_t get_sd_initial_delay_max() const = 0;
virtual int32_t get_sd_repetitions_base_delay() const = 0;
virtual uint8_t get_sd_repetitions_max() const = 0;
virtual ttl_t get_sd_ttl() const = 0;
@@ -144,23 +172,6 @@ public:
virtual bool log_version() const = 0;
virtual uint32_t get_log_version_interval() const = 0;
- // Security
- virtual bool is_security_enabled() const = 0;
- virtual bool is_client_allowed(client_t _client, service_t _service,
- instance_t _instance, method_t _method, bool _is_request_service = false) const = 0;
- virtual bool is_offer_allowed(client_t _client, service_t _service,
- instance_t _instance) const = 0;
- virtual bool check_credentials(client_t _client,
- uint32_t _uid, uint32_t _gid) = 0;
- virtual bool store_client_to_uid_gid_mapping(client_t _client, uint32_t _uid, uint32_t _gid) = 0;
- virtual void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid, client_t _client) = 0;
-
- virtual bool get_client_to_uid_gid_mapping(client_t _client,
- std::pair<uint32_t, uint32_t> &_uid_gid) = 0;
- virtual bool remove_client_to_uid_gid_mapping(client_t _client) = 0;
- virtual bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
- std::set<client_t> &_clients) = 0;
-
// Plugins
virtual std::map<plugin_type_e, std::set<std::string>> get_plugins(
const std::string &_name) const = 0;
@@ -196,37 +207,31 @@ public:
virtual std::uint32_t get_max_tcp_restart_aborts() const = 0;
virtual std::uint32_t get_max_tcp_connect_time() const = 0;
- // Offer acceptance
- virtual bool offer_acceptance_required(
- const boost::asio::ip::address& _address) const = 0;
- virtual void set_offer_acceptance_required(
- const boost::asio::ip::address& _address, const std::string& _path,
- bool _enable) = 0;
- virtual std::map<boost::asio::ip::address, std::string> get_offer_acceptance_required() = 0;
-
- // Security policy
- virtual void update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy) = 0;
- virtual bool remove_security_policy(uint32_t _uid, uint32_t _gid) = 0;
-
- virtual void add_security_credentials(uint32_t _uid, uint32_t _gid,
- ::std::shared_ptr<policy> _credentials_policy, client_t _client) = 0;
-
- virtual bool is_remote_client_allowed() const = 0;
-
- virtual bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const = 0;
-
- virtual bool is_policy_removal_allowed(uint32_t _uid) const = 0;
+ // SD acceptance
+ virtual bool sd_acceptance_required(const boost::asio::ip::address& _address,
+ std::uint16_t _port) const = 0;
+ virtual void set_sd_acceptance_required(
+ const boost::asio::ip::address& _address, std::uint16_t _port,
+ const std::string& _path, bool _enable) = 0;
+ typedef std::map<std::pair<boost::asio::ip::address, std::uint16_t>, std::string> sd_acceptance_required_map_t;
+ virtual sd_acceptance_required_map_t get_sd_acceptance_required() = 0;
virtual std::uint32_t get_udp_receive_buffer_size() const = 0;
- virtual bool is_audit_mode_enabled() const = 0;
-
virtual bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const = 0;
+ // SOME/IP-TP
+ virtual bool tp_segment_messages_client_to_service(
+ service_t _service, std::string _ip_target,
+ std::uint16_t _port_target, method_t _method) const = 0;
+ virtual bool tp_segment_messages_service_to_client(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method) const = 0;
+
// routing shutdown timeout
virtual std::uint32_t get_shutdown_timeout() const = 0;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CONFIGURATION_HPP
+#endif // VSOMEIP_V3_CONFIGURATION_HPP
diff --git a/implementation/configuration/include/configuration_element.hpp b/implementation/configuration/include/configuration_element.hpp
new file mode 100644
index 0000000..7daf9d7
--- /dev/null
+++ b/implementation/configuration/include/configuration_element.hpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_CONFIGURATION_CONFIGURATION_ELEMENT_HPP_
+#define VSOMEIP_V3_CONFIGURATION_CONFIGURATION_ELEMENT_HPP_
+
+#include <string>
+
+#include <boost/property_tree/ptree.hpp>
+
+namespace vsomeip_v3 {
+
+struct configuration_element {
+ std::string name_;
+ boost::property_tree::ptree tree_;
+
+ bool operator<(const configuration_element &_other) const {
+ return (name_ < _other.name_);
+ }
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_CONFIGURATION_CONFIGURATION_ELEMENT_HPP_
diff --git a/implementation/configuration/include/configuration_impl.hpp b/implementation/configuration/include/configuration_impl.hpp
index 9bf1188..f43a97a 100644
--- a/implementation/configuration/include/configuration_impl.hpp
+++ b/implementation/configuration/include/configuration_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_CONFIGURATION_IMPL_HPP
-#define VSOMEIP_CFG_CONFIGURATION_IMPL_HPP
+#ifndef VSOMEIP_V3_CFG_CONFIGURATION_IMPL_HPP
+#define VSOMEIP_V3_CFG_CONFIGURATION_IMPL_HPP
#include <map>
#include <memory>
@@ -17,14 +17,15 @@
#include "trace.hpp"
#include "configuration.hpp"
+#include "configuration_element.hpp"
#include "watchdog.hpp"
#include "service_instance_range.hpp"
-#include "policy.hpp"
#include "../../e2e_protection/include/e2exf/config.hpp"
#include "e2e.hpp"
#include "debounce.hpp"
+#include "../../security/include/policy.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct client;
@@ -34,18 +35,8 @@ struct event;
struct eventgroup;
struct watchdog;
-struct element {
- std::string name_;
- boost::property_tree::ptree tree_;
-
- bool operator<(const element &_other) const {
- return (name_ < _other.name_);
- }
-};
-
class configuration_impl:
public configuration,
- public plugin_impl<configuration_impl>,
public std::enable_shared_from_this<configuration_impl> {
public:
VSOMEIP_EXPORT configuration_impl();
@@ -71,6 +62,7 @@ public:
VSOMEIP_EXPORT const boost::asio::ip::address & get_unicast_address() const;
VSOMEIP_EXPORT const boost::asio::ip::address& get_netmask() const;
+ VSOMEIP_EXPORT const std::string &get_device() const;
VSOMEIP_EXPORT unsigned short get_diagnosis_address() const;
VSOMEIP_EXPORT std::uint16_t get_diagnosis_mask() const;
VSOMEIP_EXPORT bool is_v4() const;
@@ -89,6 +81,17 @@ public:
VSOMEIP_EXPORT uint16_t get_unreliable_port(service_t _service,
instance_t _instance) const;
+ VSOMEIP_EXPORT void get_configured_timing_requests(
+ service_t _service, std::string _ip_target,
+ std::uint16_t _port_target, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const;
+ VSOMEIP_EXPORT void get_configured_timing_responses(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const;
+
VSOMEIP_EXPORT bool is_someip(service_t _service, instance_t _instance) const;
VSOMEIP_EXPORT bool get_client_port(service_t _service, instance_t _instance,
@@ -117,6 +120,7 @@ public:
VSOMEIP_EXPORT std::uint32_t get_max_message_size_local() const;
VSOMEIP_EXPORT std::uint32_t get_max_message_size_reliable(const std::string& _address,
std::uint16_t _port) const;
+ VSOMEIP_EXPORT std::uint32_t get_max_message_size_unreliable() const;
VSOMEIP_EXPORT std::uint32_t get_buffer_shrink_threshold() const;
VSOMEIP_EXPORT bool supports_selective_broadcasts(boost::asio::ip::address _address) const;
@@ -128,7 +132,11 @@ public:
VSOMEIP_EXPORT bool is_local_service(service_t _service, instance_t _instance) const;
- VSOMEIP_EXPORT bool is_event_reliable(service_t _service, instance_t _instance, event_t _event) const;
+ VSOMEIP_EXPORT reliability_type_e get_event_reliability(
+ service_t _service, instance_t _instance, event_t _event) const;
+
+ VSOMEIP_EXPORT reliability_type_e get_service_reliability(
+ service_t _service, instance_t _instance) const;
// Service Discovery configuration
VSOMEIP_EXPORT bool is_sd_enabled() const;
@@ -137,8 +145,8 @@ public:
VSOMEIP_EXPORT uint16_t get_sd_port() const;
VSOMEIP_EXPORT const std::string & get_sd_protocol() const;
- VSOMEIP_EXPORT int32_t get_sd_initial_delay_min() const;
- VSOMEIP_EXPORT int32_t get_sd_initial_delay_max() const;
+ VSOMEIP_EXPORT uint32_t get_sd_initial_delay_min() const;
+ VSOMEIP_EXPORT uint32_t get_sd_initial_delay_max() const;
VSOMEIP_EXPORT int32_t get_sd_repetitions_base_delay() const;
VSOMEIP_EXPORT uint8_t get_sd_repetitions_max() const;
VSOMEIP_EXPORT ttl_t get_sd_ttl() const;
@@ -156,22 +164,7 @@ public:
VSOMEIP_EXPORT std::uint32_t get_permissions_uds() const;
VSOMEIP_EXPORT std::uint32_t get_permissions_shm() const;
- // Policy
- VSOMEIP_EXPORT bool is_security_enabled() const;
- VSOMEIP_EXPORT bool is_client_allowed(client_t _client, service_t _service,
- instance_t _instance, method_t _method, bool _is_request_service = false) const;
- VSOMEIP_EXPORT bool is_offer_allowed(client_t _client, service_t _service,
- instance_t _instance) const;
- VSOMEIP_EXPORT bool check_credentials(client_t _client,
- uint32_t _uid, uint32_t _gid);
-
- VSOMEIP_EXPORT bool store_client_to_uid_gid_mapping(client_t _client, uint32_t _uid, uint32_t _gid);
- VSOMEIP_EXPORT void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid, client_t _client);
- VSOMEIP_EXPORT bool get_client_to_uid_gid_mapping(client_t _client,
- std::pair<uint32_t, uint32_t> &_uid_gid);
- VSOMEIP_EXPORT bool remove_client_to_uid_gid_mapping(client_t _client);
- VSOMEIP_EXPORT bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
- std::set<client_t> &_clients);
+ VSOMEIP_EXPORT bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const;
VSOMEIP_EXPORT std::map<plugin_type_e, std::set<std::string>> get_plugins(
const std::string &_name) const;
@@ -198,52 +191,59 @@ public:
VSOMEIP_EXPORT std::uint32_t get_max_tcp_restart_aborts() const;
VSOMEIP_EXPORT std::uint32_t get_max_tcp_connect_time() const;
- VSOMEIP_EXPORT bool offer_acceptance_required(
- const boost::asio::ip::address& _address) const;
-
- VSOMEIP_EXPORT void set_offer_acceptance_required(
- const boost::asio::ip::address& _address, const std::string& _path,
- bool _enable);
- VSOMEIP_EXPORT std::map<boost::asio::ip::address, std::string> get_offer_acceptance_required();
-
- VSOMEIP_EXPORT void update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy);
- VSOMEIP_EXPORT bool remove_security_policy(uint32_t _uid, uint32_t _gid);
-
- VSOMEIP_EXPORT void add_security_credentials(uint32_t _uid, uint32_t _gid,
- ::std::shared_ptr<policy> _credentials_policy, client_t _client);
+ VSOMEIP_EXPORT bool sd_acceptance_required(const boost::asio::ip::address& _address,
+ std::uint16_t _port) const;
- VSOMEIP_EXPORT bool is_remote_client_allowed() const;
-
- VSOMEIP_EXPORT bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const;
-
- VSOMEIP_EXPORT bool is_policy_removal_allowed(uint32_t _uid) const;
+ VSOMEIP_EXPORT void set_sd_acceptance_required(
+ const boost::asio::ip::address& _address, std::uint16_t _port,
+ const std::string& _path, bool _enable);
+ VSOMEIP_EXPORT sd_acceptance_required_map_t get_sd_acceptance_required();
VSOMEIP_EXPORT std::uint32_t get_udp_receive_buffer_size() const;
- VSOMEIP_EXPORT bool is_audit_mode_enabled() const;
+ VSOMEIP_EXPORT bool has_overlay(const std::string &_name) const;
+ VSOMEIP_EXPORT void load_overlay(const std::string &_name);
- VSOMEIP_EXPORT bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const;
+ VSOMEIP_EXPORT bool tp_segment_messages_client_to_service(
+ service_t _service, std::string _ip_target,
+ std::uint16_t _port_target, method_t _method) const;
+ VSOMEIP_EXPORT bool tp_segment_messages_service_to_client(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method) const;
VSOMEIP_EXPORT std::uint32_t get_shutdown_timeout() const;
private:
void read_data(const std::set<std::string> &_input,
- std::vector<element> &_elements,
+ std::vector<configuration_element> &_elements,
std::set<std::string> &_failed,
bool _mandatory_only);
- bool load_data(const std::vector<element> &_elements,
+ bool load_data(const std::vector<configuration_element> &_elements,
bool _load_mandatory, bool _load_optional);
- bool load_logging(const element &_element,
+ bool load_logging(const configuration_element &_element,
std::set<std::string> &_warnings);
- bool load_routing(const element &_element);
- bool load_routing_credentials(const element &_element);
+ bool load_routing(const configuration_element &_element);
+ bool load_routing_credentials(const configuration_element &_element);
- bool load_applications(const element &_element);
+ bool load_applications(const configuration_element &_element);
void load_application_data(const boost::property_tree::ptree &_tree,
const std::string &_file_name);
- void load_tracing(const element &_element);
+ std::map<plugin_type_e, std::set<std::string>> load_plugins(
+ const boost::property_tree::ptree &_tree,
+ const std::string& _application_name);
+
+ struct plugin_config_data_t {
+ std::string name_;
+ std::string type_;
+ };
+
+ void add_plugin(std::map<plugin_type_e, std::set<std::string>> &_plugins,
+ const plugin_config_data_t &_plugin_data,
+ const std::string& _application_name);
+
+ void load_tracing(const configuration_element &_element);
void load_trace_channels(const boost::property_tree::ptree &_tree);
void load_trace_channel(const boost::property_tree::ptree &_tree);
void load_trace_filters(const boost::property_tree::ptree &_tree);
@@ -256,17 +256,19 @@ private:
const boost::property_tree::ptree &_data,
std::tuple<service_t, instance_t, method_t> &_match);
- void load_network(const element &_element);
+ void load_network(const configuration_element &_element);
+ void load_device(const configuration_element &_element);
- void load_unicast_address(const element &_element);
- void load_netmask(const element &_element);
- void load_diagnosis_address(const element &_element);
- void load_shutdown_timeout(const element &_element);
+ void load_unicast_address(const configuration_element &_element);
+ void load_netmask(const configuration_element &_element);
+ void load_diagnosis_address(const configuration_element &_element);
+ void load_shutdown_timeout(const configuration_element &_element);
- void load_service_discovery(const element &_element);
+ void load_service_discovery(const configuration_element &_element);
void load_delays(const boost::property_tree::ptree &_tree);
- void load_services(const element &_element);
+ void load_npdu_default_timings(const configuration_element &_element);
+ void load_services(const configuration_element &_element);
void load_servicegroup(const boost::property_tree::ptree &_tree);
void load_service(const boost::property_tree::ptree &_tree,
const std::string &_unicast_address);
@@ -275,30 +277,24 @@ private:
void load_eventgroup(std::shared_ptr<service> &_service,
const boost::property_tree::ptree &_tree);
- void load_internal_services(const element &_element);
+ void load_internal_services(const configuration_element &_element);
- void load_clients(const element &_element);
+ void load_clients(const configuration_element &_element);
void load_client(const boost::property_tree::ptree &_tree);
std::set<uint16_t> load_client_ports(const boost::property_tree::ptree &_tree);
std::pair<uint16_t, uint16_t> load_client_port_range(const boost::property_tree::ptree &_tree);
- void load_watchdog(const element &_element);
+ void load_watchdog(const configuration_element &_element);
- void load_payload_sizes(const element &_element);
- void load_permissions(const element &_element);
- void load_selective_broadcasts_support(const element &_element);
- void load_policies(const element &_element);
- void load_policy(const boost::property_tree::ptree &_tree);
- void load_credential(const boost::property_tree::ptree &_tree, ids_t &_ids);
- void load_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
- void load_instance_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
+ void load_payload_sizes(const configuration_element &_element);
+ void load_permissions(const configuration_element &_element);
- void load_security_update_whitelist(const element &_element);
- void load_service_ranges(const boost::property_tree::ptree &_tree,
- std::set<std::pair<service_t, service_t>> &_ranges);
+ void load_security(const configuration_element &_element);
- void load_debounce(const element &_element);
+ void load_selective_broadcasts_support(const configuration_element &_element);
+
+ void load_debounce(const configuration_element &_element);
void load_service_debounce(const boost::property_tree::ptree &_tree);
void load_events_debounce(const boost::property_tree::ptree &_tree,
std::map<event_t, std::shared_ptr<debounce>> &_debounces);
@@ -306,15 +302,27 @@ private:
std::map<event_t, std::shared_ptr<debounce>> &_debounces);
void load_event_debounce_ignore(const boost::property_tree::ptree &_tree,
std::map<std::size_t, byte_t> &_ignore);
- void load_offer_acceptance_required(const element &_element);
- void load_udp_receive_buffer_size(const element &_element);
-
+ void load_sd_acceptance_required(const configuration_element &_element);
+ void load_udp_receive_buffer_size(const configuration_element &_element);
+ bool load_npdu_debounce_times_configuration(
+ const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree);
+ bool load_npdu_debounce_times_for_service(
+ const std::shared_ptr<service>& _service, bool _is_request,
+ const boost::property_tree::ptree &_tree);
+ void load_someip_tp(const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree);
+ void load_someip_tp_for_service(
+ const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree, bool _is_request);
servicegroup *find_servicegroup(const std::string &_name) const;
std::shared_ptr<client> find_client(service_t _service,
instance_t _instance) const;
std::shared_ptr<service> find_service(service_t _service, instance_t _instance) const;
std::shared_ptr<service> find_service_unlocked(service_t _service, instance_t _instance) const;
+ service * find_service_by_ip_port(service_t _service, const std::string& _ip,
+ std::uint16_t _port) const;
std::shared_ptr<eventgroup> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
bool find_port(uint16_t &_port, uint16_t _remote, bool _reliable,
@@ -323,32 +331,30 @@ private:
void set_magic_cookies_unicast_address();
bool is_mandatory(const std::string &_name) const;
- bool is_remote(std::shared_ptr<service> _service) const;
+ bool is_remote(const std::shared_ptr<service>& _service) const;
bool is_internal_service(service_t _service, instance_t _instance) const;
bool is_in_port_range(uint16_t _port, std::pair<uint16_t, uint16_t> _port_range) const;
void set_mandatory(const std::string &_input);
void trim(std::string &_s);
- void load_e2e(const element &_element);
+ void load_e2e(const configuration_element &_element);
void load_e2e_protected(const boost::property_tree::ptree &_tree);
void load_ttl_factors(const boost::property_tree::ptree &_tree,
ttl_map_t* _target);
- void load_endpoint_queue_sizes(const element &_element);
+ void load_endpoint_queue_sizes(const configuration_element &_element);
- void load_tcp_restart_settings(const element &_element);
-
- std::shared_ptr<policy> find_client_id_policy(client_t _client) const;
+ void load_tcp_restart_settings(const configuration_element &_element);
private:
std::mutex mutex_;
- mutable std::mutex ids_mutex_;
- mutable std::mutex uid_to_clients_mutex_;
+ const std::string default_unicast_;
bool is_loaded_;
bool is_logging_loaded_;
+ bool is_overlay_;
std::set<std::string> mandatory_;
@@ -356,8 +362,9 @@ protected:
// Configuration data
boost::asio::ip::address unicast_;
boost::asio::ip::address netmask_;
- unsigned short diagnosis_;
- std::uint16_t diagnosis_mask_;
+ std::string device_;
+ diagnosis_t diagnosis_;
+ diagnosis_t diagnosis_mask_;
bool has_console_log_;
bool has_file_log_;
@@ -365,8 +372,21 @@ protected:
std::string logfile_;
boost::log::trivial::severity_level loglevel_;
- std::map<std::string, std::tuple<client_t, std::size_t, std::size_t,
- size_t, size_t, std::map<plugin_type_e, std::set<std::string>>, int>> applications_;
+ std::map<std::string,
+ std::tuple<
+ client_t,
+ std::size_t,
+ std::size_t,
+ std::size_t,
+ std::size_t,
+ std::map<
+ plugin_type_e,
+ std::set<std::string>
+ >,
+ int,
+ std::string
+ >
+ > applications_;
std::set<client_t> client_identifiers_;
mutable std::mutex services_mutex_;
@@ -374,6 +394,11 @@ protected:
std::map<instance_t,
std::shared_ptr<service> > > services_;
+ std::map<std::string, // IP
+ std::map<std::uint16_t, // port
+ std::map<service_t,
+ std::shared_ptr<service>>>> services_by_ip_port_;
+
std::list< std::shared_ptr<client> > clients_;
std::string routing_host_;
@@ -383,8 +408,8 @@ protected:
std::string sd_multicast_;
uint16_t sd_port_;
- int32_t sd_initial_delay_min_;
- int32_t sd_initial_delay_max_;
+ uint32_t sd_initial_delay_min_;
+ uint32_t sd_initial_delay_max_;
int32_t sd_repetitions_base_delay_;
uint8_t sd_repetitions_max_;
ttl_t sd_ttl_;
@@ -398,6 +423,7 @@ protected:
std::uint32_t max_configured_message_size_;
std::uint32_t max_local_message_size_;
std::uint32_t max_reliable_message_size_;
+ std::uint32_t max_unreliable_message_size_;
std::uint32_t buffer_shrink_threshold_;
std::shared_ptr<trace> trace_;
@@ -414,6 +440,7 @@ protected:
enum element_type_e {
ET_NETWORK,
ET_UNICAST,
+ ET_DEVICE,
ET_DIAGNOSIS,
ET_DIAGNOSIS_MASK,
ET_LOGGING_CONSOLE,
@@ -445,32 +472,21 @@ protected:
ET_ENDPOINT_QUEUE_LIMIT_LOCAL,
ET_TCP_RESTART_ABORTS_MAX,
ET_TCP_CONNECT_TIME_MAX,
- ET_OFFER_ACCEPTANCE_REQUIRED,
+ ET_SD_ACCEPTANCE_REQUIRED,
ET_NETMASK,
ET_UDP_RECEIVE_BUFFER_SIZE,
+ ET_NPDU_DEFAULT_TIMINGS,
+ ET_PLUGIN_NAME,
+ ET_PLUGIN_TYPE,
ET_ROUTING_CREDENTIALS,
ET_SHUTDOWN_TIMEOUT,
- ET_MAX = 38
+ ET_MAX = 42
};
bool is_configured_[ET_MAX];
std::uint32_t permissions_shm_;
std::uint32_t permissions_uds_;
- std::map<std::pair<uint16_t, uint16_t>, std::shared_ptr<policy>> policies_;
- std::vector<std::shared_ptr<policy> > any_client_policies_;
-
- mutable std::mutex policies_mutex_;
- mutable std::mutex any_client_policies_mutex_;
- std::map<client_t, std::pair<uint32_t, uint32_t> > ids_;
- std::map<std::pair<uint32_t, uint32_t>, std::set<client_t> > uid_to_clients_;
-
- bool policy_enabled_;
- bool check_credentials_;
- bool check_routing_credentials_;
- bool allow_remote_clients_;
- bool check_whitelist_;
-
std::string network_;
std::string configuration_path_;
@@ -495,27 +511,23 @@ protected:
uint32_t tcp_restart_aborts_max_;
uint32_t tcp_connect_time_max_;
- mutable std::mutex offer_acceptance_required_ips_mutex_;
- std::map<boost::asio::ip::address, std::string> offer_acceptance_required_ips_;
+ mutable std::mutex sd_acceptance_required_ips_mutex_;
+ sd_acceptance_required_map_t sd_acceptance_required_ips_;
bool has_issued_methods_warning_;
bool has_issued_clients_warning_;
std::uint32_t udp_receive_buffer_size_;
- mutable std::mutex service_interface_whitelist_mutex_;
- std::set<std::pair<service_t, service_t>> service_interface_whitelist_;
-
- mutable std::mutex uid_whitelist_mutex_;
- ranges_t uid_whitelist_;
-
- mutable std::mutex routing_credentials_mutex_;
- std::pair<uint32_t, uint32_t> routing_credentials_;
+ std::chrono::nanoseconds npdu_default_debounce_requ_;
+ std::chrono::nanoseconds npdu_default_debounce_resp_;
+ std::chrono::nanoseconds npdu_default_max_retention_requ_;
+ std::chrono::nanoseconds npdu_default_max_retention_resp_;
std::uint32_t shutdown_timeout_;
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_CONFIGURATION_IMPL_HPP
+#endif // VSOMEIP_V3_CFG_CONFIGURATION_IMPL_HPP
diff --git a/implementation/configuration/include/configuration_plugin.hpp b/implementation/configuration/include/configuration_plugin.hpp
new file mode 100644
index 0000000..cbb4685
--- /dev/null
+++ b/implementation/configuration/include/configuration_plugin.hpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_CONFIGURATION_PLUGIN_HPP_
+#define VSOMEIP_V3_CONFIGURATION_PLUGIN_HPP_
+
+#include <string>
+#include <memory>
+
+#define VSOMEIP_CONFIG_PLUGIN_VERSION 1
+
+namespace vsomeip_v3 {
+
+class configuration;
+
+class configuration_plugin {
+public:
+ virtual ~configuration_plugin() = default;
+ virtual std::shared_ptr<configuration> get_configuration(const std::string &_name) = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_CONFIGURATION_PLUGIN_HPP_
diff --git a/implementation/configuration/include/configuration_plugin_impl.hpp b/implementation/configuration/include/configuration_plugin_impl.hpp
new file mode 100644
index 0000000..fd95628
--- /dev/null
+++ b/implementation/configuration/include/configuration_plugin_impl.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_CONFIGURATION_CONFIGURATION_PLUGIN_IMPL_HPP_
+#define VSOMEIP_V3_CONFIGURATION_CONFIGURATION_PLUGIN_IMPL_HPP_
+
+#include <map>
+#include <mutex>
+
+#include <vsomeip/plugin.hpp>
+
+#include "configuration_plugin.hpp"
+
+namespace vsomeip_v3 {
+namespace cfg {
+
+ class configuration_impl;
+
+} // namespace cfg
+
+class configuration_plugin_impl
+ : public configuration_plugin,
+ public plugin_impl<configuration_plugin_impl> {
+public:
+ configuration_plugin_impl();
+ virtual ~configuration_plugin_impl();
+
+ std::shared_ptr<configuration> get_configuration(const std::string &_name);
+
+private:
+ std::mutex mutex_;
+ std::shared_ptr<cfg::configuration_impl> default_;
+#ifdef VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
+ std::map<std::string, std::shared_ptr<cfg::configuration_impl> > configurations_;
+#endif // VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_CONFIGURATION_CONFIGURATION_PLUGIN_IMPL_HPP_
diff --git a/implementation/configuration/include/debounce.hpp b/implementation/configuration/include/debounce.hpp
index b4ce6d3..dc61514 100644
--- a/implementation/configuration/include/debounce.hpp
+++ b/implementation/configuration/include/debounce.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_DEBOUNCE_HPP
-#define VSOMEIP_CFG_DEBOUNCE_HPP
+#ifndef VSOMEIP_V3_CFG_DEBOUNCE_HPP
+#define VSOMEIP_V3_CFG_DEBOUNCE_HPP
#include <map>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
// Messages are forwarded either because their value differs from the
@@ -34,6 +34,6 @@ struct debounce {
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_DEBOUNCE_HPP
+#endif // VSOMEIP_V3_CFG_DEBOUNCE_HPP
diff --git a/implementation/configuration/include/e2e.hpp b/implementation/configuration/include/e2e.hpp
index 94eb33d..8c873c2 100644
--- a/implementation/configuration/include/e2e.hpp
+++ b/implementation/configuration/include/e2e.hpp
@@ -3,48 +3,37 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_E2E_HPP_
-#define VSOMEIP_CFG_E2E_HPP_
+#ifndef VSOMEIP_V3_CFG_E2E_HPP_
+#define VSOMEIP_V3_CFG_E2E_HPP_
+#include <map>
#include <string>
#include <vector>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct e2e {
+ typedef std::map<std::string, std::string> custom_parameters_t;
e2e() :
data_id(0),
variant(""),
profile(""),
service_id(0),
- event_id(0),
- crc_offset(0),
- data_id_mode(0),
- data_length(0),
- data_id_nibble_offset(0),
- counter_offset(0) {
+ event_id(0) {
}
-
e2e(uint16_t _data_id, std::string _variant, std::string _profile, service_t _service_id,
- event_t _event_id,uint16_t _crc_offset,
- uint8_t _data_id_mode, uint16_t _data_length, uint16_t _data_id_nibble_offset, uint16_t _counter_offset) :
-
+ event_t _event_id, custom_parameters_t&& _custom_parameters) :
data_id(_data_id),
variant(_variant),
profile(_profile),
service_id(_service_id),
event_id(_event_id),
- crc_offset(_crc_offset),
- data_id_mode(_data_id_mode),
- data_length(_data_length),
- data_id_nibble_offset(_data_id_nibble_offset),
- counter_offset(_counter_offset) {
-
+ custom_parameters(_custom_parameters) {
}
// common config
@@ -54,16 +43,11 @@ struct e2e {
service_t service_id;
event_t event_id;
- //profile 1 specific config
- // [SWS_E2E_00018]
- uint16_t crc_offset;
- uint8_t data_id_mode;
- uint16_t data_length;
- uint16_t data_id_nibble_offset;
- uint16_t counter_offset;
+ // custom parameters
+ custom_parameters_t custom_parameters;
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_E2E_HPP_
+#endif // VSOMEIP_V3_CFG_E2E_HPP_
diff --git a/implementation/configuration/include/event.hpp b/implementation/configuration/include/event.hpp
index 499c49a..701ec0c 100644
--- a/implementation/configuration/include/event.hpp
+++ b/implementation/configuration/include/event.hpp
@@ -3,31 +3,33 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_EVENT_HPP
-#define VSOMEIP_CFG_EVENT_HPP
+#ifndef VSOMEIP_V3_CFG_EVENT_HPP
+#define VSOMEIP_V3_CFG_EVENT_HPP
#include <memory>
#include <vector>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct eventgroup;
struct event {
- event(event_t _id, bool _is_field, bool _is_reliable)
- : id_(_id), is_field_(_is_field), is_reliable_(_is_reliable) {
+ event(event_t _id, bool _is_field, reliability_type_e _reliability)
+ : id_(_id),
+ is_field_(_is_field),
+ reliability_(_reliability) {
}
event_t id_;
bool is_field_;
- bool is_reliable_;
+ reliability_type_e reliability_;
std::vector<std::weak_ptr<eventgroup> > groups_;
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_EVENT_HPP
+#endif // VSOMEIP_V3_CFG_EVENT_HPP
diff --git a/implementation/configuration/include/eventgroup.hpp b/implementation/configuration/include/eventgroup.hpp
index c26edc0..1402b51 100644
--- a/implementation/configuration/include/eventgroup.hpp
+++ b/implementation/configuration/include/eventgroup.hpp
@@ -3,14 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_EVENTGROUP_HPP
-#define VSOMEIP_CFG_EVENTGROUP_HPP
+#ifndef VSOMEIP_V3_CFG_EVENTGROUP_HPP
+#define VSOMEIP_V3_CFG_EVENTGROUP_HPP
#include <memory>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct event;
@@ -24,6 +24,6 @@ struct eventgroup {
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_EVENTGROUP_HPP
+#endif // VSOMEIP_V3_CFG_EVENTGROUP_HPP
diff --git a/implementation/configuration/include/internal.hpp.in b/implementation/configuration/include/internal.hpp.in
index b1a1372..36a6355 100644
--- a/implementation/configuration/include/internal.hpp.in
+++ b/implementation/configuration/include/internal.hpp.in
@@ -1,10 +1,10 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_INTERNAL_HPP
-#define VSOMEIP_INTERNAL_HPP
+#ifndef VSOMEIP_V3_INTERNAL_HPP_
+#define VSOMEIP_V3_INTERNAL_HPP_
#include <cstdint>
#include <limits>
@@ -13,35 +13,42 @@
#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME"
#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION"
#define VSOMEIP_ENV_CONFIGURATION_MODULE "VSOMEIP_CONFIGURATION_MODULE"
+#define VSOMEIP_ENV_E2E_PROTECTION_MODULE "VSOMEIP_E2E_PROTECTION_MODULE"
#define VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES "VSOMEIP_MANDATORY_CONFIGURATION_FILES"
#define VSOMEIP_ENV_LOAD_PLUGINS "VSOMEIP_LOAD_PLUGINS"
#define VSOMEIP_ENV_CLIENTSIDELOGGING "VSOMEIP_CLIENTSIDELOGGING"
-#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json"
+#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "@DEFAULT_CONFIGURATION_FILE@"
#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json"
#define VSOMEIP_MANDATORY_CONFIGURATION_FILES "vsomeip_std.json,vsomeip_app.json,vsomeip_plc.json,vsomeip_log.json,vsomeip_security.json,vsomeip_whitelist.json"
-#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
+#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "@DEFAULT_CONFIGURATION_FOLDER@"
#define VSOMEIP_DEBUG_CONFIGURATION_FOLDER "/var/opt/public/sin/vsomeip/"
#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip"
-#define VSOMEIP_BASE_PATH "/tmp/"
+#define VSOMEIP_BASE_PATH "@VSOMEIP_BASE_PATH@/"
-#ifdef WIN32
-#define VSOMEIP_CFG_LIBRARY "vsomeip-cfg.dll"
+#ifdef _WIN32
+#define VSOMEIP_CFG_LIBRARY "vsomeip3-cfg.dll"
+#else
+#define VSOMEIP_CFG_LIBRARY "libvsomeip3-cfg.so.@VSOMEIP_MAJOR_VERSION@"
+#endif
+
+#ifdef _WIN32
+#define VSOMEIP_SD_LIBRARY "vsomeip3-sd.dll"
#else
-#define VSOMEIP_CFG_LIBRARY "libvsomeip-cfg.so.@VSOMEIP_MAJOR_VERSION@"
+#define VSOMEIP_SD_LIBRARY "libvsomeip3-sd.so.@VSOMEIP_MAJOR_VERSION@"
#endif
-#ifdef WIN32
-#define VSOMEIP_SD_LIBRARY "vsomeip-sd.dll"
+#ifdef _WIN32
+#define VSOMEIP_E2E_LIBRARY "vsomeip3-e2e.dll"
#else
-#define VSOMEIP_SD_LIBRARY "libvsomeip-sd.so.@VSOMEIP_MAJOR_VERSION@"
+#define VSOMEIP_E2E_LIBRARY "libvsomeip3-e2e.so.@VSOMEIP_MAJOR_VERSION@"
#endif
-#define VSOMEIP_ROUTING "@VSOMEIP_ROUTING@"
#define VSOMEIP_ROUTING_CLIENT 0
-#define VSOMEIP_ROUTING_INFO_SIZE_INIT 256
+
+#define VSOMEIP_CLIENT_UNSET 0xFFFF
#ifdef _WIN32
#define VSOMEIP_INTERNAL_BASE_PORT 51234
@@ -57,6 +64,8 @@
#define VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT 5000
+#define VSOMEIP_DEFAULT_QUEUE_WARN_SIZE 102400
+
#define VSOMEIP_MAX_TCP_CONNECT_TIME 5000
#define VSOMEIP_MAX_TCP_RESTART_ABORTS 5
@@ -73,8 +82,6 @@
#define VSOMEIP_MAX_DISPATCHERS 10
#define VSOMEIP_MAX_DISPATCH_TIME 100
-#define VSOMEIP_MAX_DESERIALIZER 5
-
#define VSOMEIP_REQUEST_DEBOUNCE_TIME 10
#define VSOMEIP_COMMAND_HEADER_SIZE 7
@@ -85,11 +92,13 @@
#define VSOMEIP_COMMAND_SIZE_POS_MAX 6
#define VSOMEIP_COMMAND_PAYLOAD_POS 7
-#define VSOMEIP_REGISTER_APPLICATION 0x00
-#define VSOMEIP_DEREGISTER_APPLICATION 0x01
-#define VSOMEIP_APPLICATION_LOST 0x02
-#define VSOMEIP_ROUTING_INFO 0x03
-#define VSOMEIP_REGISTERED_ACK 0x04
+#define VSOMEIP_ASSIGN_CLIENT 0x00
+#define VSOMEIP_ASSIGN_CLIENT_ACK 0x01
+#define VSOMEIP_REGISTER_APPLICATION 0x02
+#define VSOMEIP_DEREGISTER_APPLICATION 0x03
+#define VSOMEIP_APPLICATION_LOST 0x04
+#define VSOMEIP_ROUTING_INFO 0x05
+#define VSOMEIP_REGISTERED_ACK 0x06
#define VSOMEIP_PING 0x0E
#define VSOMEIP_PONG 0x0F
@@ -123,29 +132,27 @@
#define VSOMEIP_UPDATE_SECURITY_CREDENTIALS 0x27
#define VSOMEIP_DISTRIBUTE_SECURITY_POLICIES 0x28
-#define VSOMEIP_SEND_COMMAND_SIZE 14
+#define VSOMEIP_SEND_COMMAND_SIZE 13
#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN 7
#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MAX 8
-#define VSOMEIP_SEND_COMMAND_FLUSH_POS 9
-#define VSOMEIP_SEND_COMMAND_RELIABLE_POS 10
-#define VSOMEIP_SEND_COMMAND_VALID_CRC_POS 11
-#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN 12
-#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MAX 13
-#define VSOMEIP_SEND_COMMAND_PAYLOAD_POS 14
+#define VSOMEIP_SEND_COMMAND_RELIABLE_POS 9
+#define VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS 10
+#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN 11
+#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MAX 12
+#define VSOMEIP_SEND_COMMAND_PAYLOAD_POS 13
+#define VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE 9
#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 16
-#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 17
+#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 16
#define VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE 11
#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 16
-#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 19
+#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18
#define VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE 19
#define VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE 19
#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 17
#define VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE 15
-#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 15
+#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 16
#define VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE 14
-#define VSOMEIP_ID_RESPONSE_COMMAND_SIZE 12
-#define VSOMEIP_ID_REQUEST_COMMAND_SIZE 13
#define VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE 8
#define VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE 11
#define VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE 19
@@ -170,7 +177,7 @@
#define VSOMEIP_ROUTING_READY_MESSAGE "@VSOMEIP_ROUTING_READY_MESSAGE@"
-namespace vsomeip {
+namespace vsomeip_v3 {
typedef enum {
RIE_ADD_CLIENT = 0x0,
@@ -184,7 +191,6 @@ struct service_data_t {
instance_t instance_;
major_version_t major_;
minor_version_t minor_;
- bool use_exclusive_proxy_; // only used for requests!
bool operator<(const service_data_t &_other) const {
return (service_ < _other.service_
@@ -199,27 +205,20 @@ typedef enum {
IS_SUBSCRIBING
} subscription_state_e;
-struct configuration_data_t {
-#ifndef _WIN32
- volatile char initialized_;
- pthread_mutex_t mutex_;
- pid_t pid_;
-#endif
- unsigned short client_base_;
- unsigned short max_clients_;
- int max_used_client_ids_index_;
- unsigned short max_assigned_client_id_;
- unsigned short routing_manager_host_;
- // array of used client ids here, pointer to it is kept in utility class
-};
-
const std::uint32_t MESSAGE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
const std::uint32_t QUEUE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+#define VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO 2 * 1000 * 1000
+#define VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO 5 * 1000 * 1000
+
const std::uint32_t MAX_RECONNECTS_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+const std::uint32_t ANY_UID = 0xFFFFFFFF;
+const std::uint32_t ANY_GID = 0xFFFFFFFF;
+
+typedef std::pair<std::uint32_t, std::uint32_t> credentials_t;
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_INTERNAL_HPP
+#endif // VSOMEIP_V3_INTERNAL_HPP_
diff --git a/implementation/configuration/include/internal_android.hpp b/implementation/configuration/include/internal_android.hpp
new file mode 100644
index 0000000..9f770ac
--- /dev/null
+++ b/implementation/configuration/include/internal_android.hpp
@@ -0,0 +1,206 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_INTERNAL_HPP_
+#define VSOMEIP_V3_INTERNAL_HPP_
+
+#include <cstdint>
+#include <limits>
+#include <vsomeip/primitive_types.hpp>
+
+#define VSOMEIP_ENV_APPLICATION_NAME "VSOMEIP_APPLICATION_NAME"
+#define VSOMEIP_ENV_CONFIGURATION "VSOMEIP_CONFIGURATION"
+#define VSOMEIP_ENV_CONFIGURATION_MODULE "VSOMEIP_CONFIGURATION_MODULE"
+#define VSOMEIP_ENV_E2E_PROTECTION_MODULE "VSOMEIP_E2E_PROTECTION_MODULE"
+#define VSOMEIP_ENV_MANDATORY_CONFIGURATION_FILES "VSOMEIP_MANDATORY_CONFIGURATION_FILES"
+#define VSOMEIP_ENV_LOAD_PLUGINS "VSOMEIP_LOAD_PLUGINS"
+#define VSOMEIP_ENV_CLIENTSIDELOGGING "VSOMEIP_CLIENTSIDELOGGING"
+
+#define VSOMEIP_DEFAULT_CONFIGURATION_FILE "/etc/vsomeip.json"
+#define VSOMEIP_LOCAL_CONFIGURATION_FILE "./vsomeip.json"
+#define VSOMEIP_MANDATORY_CONFIGURATION_FILES "vsomeip_std.json,vsomeip_app.json,vsomeip_plc.json,vsomeip_log.json,vsomeip_security.json,vsomeip_whitelist.json"
+
+#define VSOMEIP_DEFAULT_CONFIGURATION_FOLDER "/etc/vsomeip"
+#define VSOMEIP_DEBUG_CONFIGURATION_FOLDER "/var/opt/public/sin/vsomeip/"
+#define VSOMEIP_LOCAL_CONFIGURATION_FOLDER "./vsomeip"
+
+#define VSOMEIP_BASE_PATH "/storage/"
+
+#define VSOMEIP_CFG_LIBRARY "libvsomeip_cfg.so"
+
+#define VSOMEIP_SD_LIBRARY "libvsomeip_sd.so"
+
+#define VSOMEIP_E2E_LIBRARY "libvsomeip-e2e.so.3"
+
+#define VSOMEIP_ROUTING_CLIENT 0
+
+#define VSOMEIP_CLIENT_UNSET 0xFFFF
+
+#define VSOMEIP_UNICAST_ADDRESS "127.0.0.1"
+#define VSOMEIP_NETMASK "255.255.255.0"
+
+#define VSOMEIP_DEFAULT_CONNECT_TIMEOUT 100
+#define VSOMEIP_MAX_CONNECT_TIMEOUT 1600
+#define VSOMEIP_DEFAULT_FLUSH_TIMEOUT 1000
+
+#define VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT 5000
+
+#define VSOMEIP_DEFAULT_QUEUE_WARN_SIZE 102400
+
+#define VSOMEIP_MAX_TCP_CONNECT_TIME 5000
+#define VSOMEIP_MAX_TCP_RESTART_ABORTS 5
+
+#define VSOMEIP_DEFAULT_BUFFER_SHRINK_THRESHOLD 5
+
+#define VSOMEIP_DEFAULT_WATCHDOG_TIMEOUT 5000
+#define VSOMEIP_DEFAULT_MAX_MISSING_PONGS 3
+
+#define VSOMEIP_DEFAULT_UDP_RCV_BUFFER_SIZE 1703936
+
+#define VSOMEIP_IO_THREAD_COUNT 2
+#define VSOMEIP_IO_THREAD_NICE_LEVEL 255
+
+#define VSOMEIP_MAX_DISPATCHERS 10
+#define VSOMEIP_MAX_DISPATCH_TIME 100
+
+#define VSOMEIP_MAX_DESERIALIZER 5
+
+#define VSOMEIP_REQUEST_DEBOUNCE_TIME 10
+
+#define VSOMEIP_COMMAND_HEADER_SIZE 7
+
+#define VSOMEIP_COMMAND_TYPE_POS 0
+#define VSOMEIP_COMMAND_CLIENT_POS 1
+#define VSOMEIP_COMMAND_SIZE_POS_MIN 3
+#define VSOMEIP_COMMAND_SIZE_POS_MAX 6
+#define VSOMEIP_COMMAND_PAYLOAD_POS 7
+
+#define VSOMEIP_ASSIGN_CLIENT 0x00
+#define VSOMEIP_ASSIGN_CLIENT_ACK 0x01
+#define VSOMEIP_REGISTER_APPLICATION 0x02
+#define VSOMEIP_DEREGISTER_APPLICATION 0x03
+#define VSOMEIP_APPLICATION_LOST 0x04
+#define VSOMEIP_ROUTING_INFO 0x05
+#define VSOMEIP_REGISTERED_ACK 0x06
+
+#define VSOMEIP_PING 0x0E
+#define VSOMEIP_PONG 0x0F
+
+#define VSOMEIP_OFFER_SERVICE 0x10
+#define VSOMEIP_STOP_OFFER_SERVICE 0x11
+#define VSOMEIP_SUBSCRIBE 0x12
+#define VSOMEIP_UNSUBSCRIBE 0x13
+#define VSOMEIP_REQUEST_SERVICE 0x14
+#define VSOMEIP_RELEASE_SERVICE 0x15
+#define VSOMEIP_SUBSCRIBE_NACK 0x16
+#define VSOMEIP_SUBSCRIBE_ACK 0x17
+
+#define VSOMEIP_SEND 0x18
+#define VSOMEIP_NOTIFY 0x19
+#define VSOMEIP_NOTIFY_ONE 0x1A
+
+#define VSOMEIP_REGISTER_EVENT 0x1B
+#define VSOMEIP_UNREGISTER_EVENT 0x1C
+#define VSOMEIP_ID_RESPONSE 0x1D
+#define VSOMEIP_ID_REQUEST 0x1E
+#define VSOMEIP_OFFERED_SERVICES_REQUEST 0x1F
+#define VSOMEIP_OFFERED_SERVICES_RESPONSE 0x20
+#define VSOMEIP_UNSUBSCRIBE_ACK 0x21
+#define VSOMEIP_RESEND_PROVIDED_EVENTS 0x22
+
+#define VSOMEIP_UPDATE_SECURITY_POLICY 0x23
+#define VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE 0x24
+#define VSOMEIP_REMOVE_SECURITY_POLICY 0x25
+#define VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE 0x26
+#define VSOMEIP_UPDATE_SECURITY_CREDENTIALS 0x27
+#define VSOMEIP_DISTRIBUTE_SECURITY_POLICIES 0x28
+
+#define VSOMEIP_SEND_COMMAND_SIZE 13
+#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN 7
+#define VSOMEIP_SEND_COMMAND_INSTANCE_POS_MAX 8
+#define VSOMEIP_SEND_COMMAND_RELIABLE_POS 9
+#define VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS 10
+#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN 11
+#define VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MAX 12
+#define VSOMEIP_SEND_COMMAND_PAYLOAD_POS 13
+
+#define VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE 9
+#define VSOMEIP_OFFER_SERVICE_COMMAND_SIZE 16
+#define VSOMEIP_REQUEST_SERVICE_COMMAND_SIZE 16
+#define VSOMEIP_RELEASE_SERVICE_COMMAND_SIZE 11
+#define VSOMEIP_STOP_OFFER_SERVICE_COMMAND_SIZE 16
+#define VSOMEIP_SUBSCRIBE_COMMAND_SIZE 18
+#define VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE 19
+#define VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE 19
+#define VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE 17
+#define VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE 15
+#define VSOMEIP_REGISTER_EVENT_COMMAND_SIZE 16
+#define VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE 14
+#define VSOMEIP_OFFERED_SERVICES_COMMAND_SIZE 8
+#define VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE 11
+#define VSOMEIP_REMOVE_SECURITY_POLICY_COMMAND_SIZE 19
+#define VSOMEIP_UPDATE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE 11
+#define VSOMEIP_REMOVE_SECURITY_POLICY_RESPONSE_COMMAND_SIZE 11
+#define VSOMEIP_PING_COMMAND_SIZE 7
+#define VSOMEIP_PONG_COMMAND_SIZE 7
+#define VSOMEIP_REGISTER_APPLICATION_COMMAND_SIZE 7
+#define VSOMEIP_DEREGISTER_APPLICATION_COMMAND_SIZE 7
+#define VSOMEIP_REGISTERED_ACK_COMMAND_SIZE 7
+
+#include <pthread.h>
+
+#define VSOMEIP_DATA_ID 0x677D
+#define VSOMEIP_DIAGNOSIS_ADDRESS 0x01
+
+#define VSOMEIP_DEFAULT_SHM_PERMISSION 0666
+#define VSOMEIP_DEFAULT_UDS_PERMISSIONS 0666
+
+#define VSOMEIP_ROUTING_READY_MESSAGE "SOME/IP routing ready."
+
+namespace vsomeip_v3 {
+
+typedef enum {
+ RIE_ADD_CLIENT = 0x0,
+ RIE_ADD_SERVICE_INSTANCE = 0x1,
+ RIE_DEL_SERVICE_INSTANCE = 0x2,
+ RIE_DEL_CLIENT = 0x3,
+} routing_info_entry_e;
+
+struct service_data_t {
+ service_t service_;
+ instance_t instance_;
+ major_version_t major_;
+ minor_version_t minor_;
+
+ bool operator<(const service_data_t &_other) const {
+ return (service_ < _other.service_
+ || (service_ == _other.service_
+ && instance_ < _other.instance_));
+ }
+};
+
+typedef enum {
+ SUBSCRIPTION_ACKNOWLEDGED,
+ SUBSCRIPTION_NOT_ACKNOWLEDGED,
+ IS_SUBSCRIBING
+} subscription_state_e;
+
+const std::uint32_t MESSAGE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+
+const std::uint32_t QUEUE_SIZE_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+
+#define VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO 2 * 1000 * 1000
+#define VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO 5 * 1000 * 1000
+
+const std::uint32_t MAX_RECONNECTS_UNLIMITED = (std::numeric_limits<std::uint32_t>::max)();
+
+const std::uint32_t ANY_UID = 0xFFFFFFFF;
+const std::uint32_t ANY_GID = 0xFFFFFFFF;
+
+typedef std::pair<std::uint32_t, std::uint32_t> credentials_t;
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_INTERNAL_HPP_
diff --git a/implementation/configuration/include/service.hpp b/implementation/configuration/include/service.hpp
index b33cf72..e0e0c72 100644
--- a/implementation/configuration/include/service.hpp
+++ b/implementation/configuration/include/service.hpp
@@ -3,14 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_SERVICE_HPP
-#define VSOMEIP_CFG_SERVICE_HPP
+#ifndef VSOMEIP_V3_CFG_SERVICE_HPP
+#define VSOMEIP_V3_CFG_SERVICE_HPP
#include <memory>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct event;
@@ -30,12 +30,22 @@ struct service {
std::string protocol_;
+ // [0] = debounce_time
+ // [1] = retention_time
+ typedef std::map<method_t, std::array<std::chrono::nanoseconds, 2>> npdu_time_configuration_t;
+ npdu_time_configuration_t debounce_times_requests_;
+ npdu_time_configuration_t debounce_times_responses_;
+
std::shared_ptr<servicegroup> group_;
std::map<event_t, std::shared_ptr<event> > events_;
std::map<eventgroup_t, std::shared_ptr<eventgroup> > eventgroups_;
+
+ // SOME/IP-TP
+ std::set<method_t> tp_segment_messages_client_to_service_;
+ std::set<method_t> tp_segment_messages_service_to_client_;
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_SERVICE_HPP
+#endif // VSOMEIP_V3_CFG_SERVICE_HPP
diff --git a/implementation/configuration/include/service_instance_range.hpp b/implementation/configuration/include/service_instance_range.hpp
index bf5f415..a585d7a 100644
--- a/implementation/configuration/include/service_instance_range.hpp
+++ b/implementation/configuration/include/service_instance_range.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_SERVICE_INSTANCE_RANGE_HPP
-#define VSOMEIP_CFG_SERVICE_INSTANCE_RANGE_HPP
+#ifndef VSOMEIP_V3_CFG_SERVICE_INSTANCE_RANGE_HPP
+#define VSOMEIP_V3_CFG_SERVICE_INSTANCE_RANGE_HPP
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct service_instance_range {
@@ -18,7 +18,7 @@ struct service_instance_range {
instance_t last_instance_;
};
-}
-}
+} // namespace cfg
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_SERVICE_INSTANCE_RANGE_HPP
+#endif // VSOMEIP_V3_CFG_SERVICE_INSTANCE_RANGE_HPP
diff --git a/implementation/configuration/include/trace.hpp b/implementation/configuration/include/trace.hpp
index 3d4e1f4..c9eb8cb 100644
--- a/implementation/configuration/include/trace.hpp
+++ b/implementation/configuration/include/trace.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef CFG_TRACE_HPP_
-#define CFG_TRACE_HPP_
+#ifndef VSOMEIP_V3_CFG_TRACE_HPP_
+#define VSOMEIP_V3_CFG_TRACE_HPP_
#include <string>
#include <vector>
@@ -12,7 +12,7 @@
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/trace.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct trace_channel {
@@ -29,7 +29,7 @@ struct trace_filter {
std::vector<trace_channel_t> channels_;
bool is_positive_;
bool is_range_;
- std::vector<vsomeip::trace::match_t> matches_;
+ std::vector<vsomeip_v3::trace::match_t> matches_;
};
struct trace {
@@ -48,6 +48,6 @@ struct trace {
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // CFG_TRACE_HPP_
+#endif // VSOMEIP_V3_CFG_TRACE_HPP_
diff --git a/implementation/configuration/include/watchdog.hpp b/implementation/configuration/include/watchdog.hpp
index 00fdb69..9fe81ff 100644
--- a/implementation/configuration/include/watchdog.hpp
+++ b/implementation/configuration/include/watchdog.hpp
@@ -2,10 +2,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_WATCHDOG_HPP_
-#define VSOMEIP_CFG_WATCHDOG_HPP_
+#ifndef VSOMEIP_V3_CFG_WATCHDOG_HPP_
+#define VSOMEIP_V3_CFG_WATCHDOG_HPP_
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
struct watchdog {
@@ -21,6 +21,6 @@ struct watchdog {
};
} // namespace cfg
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif /* VSOMEIP_CFG_WATCHDOG_HPP_ */
+#endif // VSOMEIP_V3_CFG_WATCHDOG_HPP_
diff --git a/implementation/configuration/src/configuration_impl.cpp b/implementation/configuration/src/configuration_impl.cpp
index b574841..7c0cf6a 100644
--- a/implementation/configuration/src/configuration_impl.cpp
+++ b/implementation/configuration/src/configuration_impl.cpp
@@ -26,22 +26,21 @@
#include "../include/event.hpp"
#include "../include/eventgroup.hpp"
#include "../include/service.hpp"
-#include "../include/internal.hpp"
#include "../../logging/include/logger_impl.hpp"
#include "../../routing/include/event.hpp"
#include "../../service_discovery/include/defines.hpp"
#include "../../utility/include/utility.hpp"
#include "../../plugin/include/plugin_manager.hpp"
+#include "../../security/include/security.hpp"
-VSOMEIP_PLUGIN(vsomeip::cfg::configuration_impl)
-
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
configuration_impl::configuration_impl()
- : plugin_impl("vsomeip cfg plugin", 1, plugin_type_e::CONFIGURATION_PLUGIN),
+ : default_unicast_("local"),
is_loaded_(false),
is_logging_loaded_(false),
+ is_overlay_(false),
diagnosis_(VSOMEIP_DIAGNOSIS_ADDRESS),
diagnosis_mask_(0xFF00),
has_console_log_(true),
@@ -64,6 +63,7 @@ configuration_impl::configuration_impl()
max_configured_message_size_(0),
max_local_message_size_(0),
max_reliable_message_size_(0),
+ max_unreliable_message_size_(0),
buffer_shrink_threshold_(VSOMEIP_DEFAULT_BUFFER_SHRINK_THRESHOLD),
trace_(std::make_shared<trace>()),
watchdog_(std::make_shared<watchdog>()),
@@ -71,11 +71,6 @@ configuration_impl::configuration_impl()
log_version_interval_(10),
permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
- policy_enabled_(false),
- check_credentials_(false),
- check_routing_credentials_(false),
- allow_remote_clients_(true),
- check_whitelist_(false),
network_("vsomeip"),
e2e_enabled_(false),
log_memory_(false),
@@ -89,6 +84,10 @@ configuration_impl::configuration_impl()
has_issued_methods_warning_(false),
has_issued_clients_warning_(false),
udp_receive_buffer_size_(VSOMEIP_DEFAULT_UDP_RCV_BUFFER_SIZE),
+ npdu_default_debounce_requ_(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO),
+ npdu_default_debounce_resp_(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO),
+ npdu_default_max_retention_requ_(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO),
+ npdu_default_max_retention_resp_(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO),
shutdown_timeout_(VSOMEIP_DEFAULT_SHUTDOWN_TIMEOUT) {
unicast_ = unicast_.from_string(VSOMEIP_UNICAST_ADDRESS);
netmask_ = netmask_.from_string(VSOMEIP_NETMASK);
@@ -97,14 +96,16 @@ configuration_impl::configuration_impl()
}
configuration_impl::configuration_impl(const configuration_impl &_other)
- : plugin_impl("vsomeip cfg plugin", 1, plugin_type_e::CONFIGURATION_PLUGIN),
- std::enable_shared_from_this<configuration_impl>(_other),
+ : std::enable_shared_from_this<configuration_impl>(_other),
+ default_unicast_(_other.default_unicast_),
is_loaded_(_other.is_loaded_),
is_logging_loaded_(_other.is_logging_loaded_),
+ is_overlay_(_other.is_overlay_),
mandatory_(_other.mandatory_),
max_configured_message_size_(_other.max_configured_message_size_),
max_local_message_size_(_other.max_local_message_size_),
max_reliable_message_size_(_other.max_reliable_message_size_),
+ max_unreliable_message_size_(_other.max_unreliable_message_size_),
buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
permissions_shm_(VSOMEIP_DEFAULT_SHM_PERMISSION),
permissions_uds_(VSOMEIP_DEFAULT_UDS_PERMISSIONS),
@@ -113,6 +114,10 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
tcp_restart_aborts_max_(_other.tcp_restart_aborts_max_),
tcp_connect_time_max_(_other.tcp_connect_time_max_),
udp_receive_buffer_size_(_other.udp_receive_buffer_size_),
+ npdu_default_debounce_requ_(_other.npdu_default_debounce_requ_),
+ npdu_default_debounce_resp_(_other.npdu_default_debounce_resp_),
+ npdu_default_max_retention_requ_(_other.npdu_default_max_retention_requ_),
+ npdu_default_max_retention_resp_(_other.npdu_default_max_retention_resp_),
shutdown_timeout_(_other.shutdown_timeout_) {
applications_.insert(_other.applications_.begin(), _other.applications_.end());
@@ -122,6 +127,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
unicast_ = _other.unicast_;
netmask_ = _other.netmask_;
+ device_ = _other.device_;
diagnosis_ = _other.diagnosis_;
diagnosis_mask_ = _other.diagnosis_mask_;
@@ -161,15 +167,6 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
for (auto i = 0; i < ET_MAX; i++)
is_configured_[i] = _other.is_configured_[i];
- policies_ = _other.policies_;
- any_client_policies_ = _other.any_client_policies_;
- ids_ = _other.ids_;
- policy_enabled_ = _other.policy_enabled_;
- check_credentials_ = _other.check_credentials_;
- check_routing_credentials_ = _other.check_routing_credentials_;
- allow_remote_clients_ = _other.allow_remote_clients_;
- check_whitelist_ = _other.check_whitelist_;
-
network_ = _other.network_;
configuration_path_ = _other.configuration_path_;
@@ -187,7 +184,7 @@ configuration_impl::configuration_impl(const configuration_impl &_other)
debounces_ = _other.debounces_;
endpoint_queue_limits_ = _other.endpoint_queue_limits_;
- offer_acceptance_required_ips_ = _other.offer_acceptance_required_ips_;
+ sd_acceptance_required_ips_ = _other.sd_acceptance_required_ips_;
has_issued_methods_warning_ = _other.has_issued_methods_warning_;
has_issued_clients_warning_ = _other.has_issued_clients_warning_;
@@ -257,8 +254,8 @@ bool configuration_impl::load(const std::string &_name) {
std::set<std::string> its_failed;
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
- std::vector<element> its_mandatory_elements;
- std::vector<element> its_optional_elements;
+ std::vector<configuration_element> its_mandatory_elements;
+ std::vector<configuration_element> its_optional_elements;
// Dummy initialization; maybe we'll find no logging configuration
logger_impl::init(shared_from_this());
@@ -299,17 +296,18 @@ bool configuration_impl::load(const std::string &_name) {
VSOMEIP_INFO << "Using configuration folder: \"" << i << "\".";
}
- if (policy_enabled_ && check_credentials_)
- VSOMEIP_INFO << "Security configuration is active.";
-
- if (policy_enabled_ && !check_credentials_)
- VSOMEIP_INFO << "Security configuration is active but in audit mode (allow all)";
-
is_loaded_ = true;
return is_loaded_;
}
+bool
+configuration_impl::check_routing_credentials(
+ client_t _client, uint32_t _uid, uint32_t _gid) const {
+ return (_client != get_id(routing_host_)) ||
+ security::get()->check_routing_credentials(_client, _uid, _gid);
+}
+
bool configuration_impl::remote_offer_info_add(service_t _service,
instance_t _instance,
std::uint16_t _port,
@@ -327,7 +325,7 @@ bool configuration_impl::remote_offer_info_add(service_t _service,
_reliable ?
its_service->reliable_ = _port :
its_service->unreliable_ = _port;
- its_service->unicast_address_ = "local";
+ its_service->unicast_address_ = default_unicast_;
its_service->multicast_address_ = "";
its_service->multicast_port_ = ILLEGAL_PORT;
its_service->protocol_ = "someip";
@@ -406,11 +404,11 @@ bool configuration_impl::remote_offer_info_remove(service_t _service,
}
void configuration_impl::read_data(const std::set<std::string> &_input,
- std::vector<element> &_elements, std::set<std::string> &_failed,
+ std::vector<configuration_element> &_elements, std::set<std::string> &_failed,
bool _mandatory_only) {
for (auto i : _input) {
if (utility::is_file(i)) {
- if (is_mandatory(i) != _mandatory_only) {
+ if (is_mandatory(i) == _mandatory_only) {
boost::property_tree::ptree its_tree;
try {
boost::property_tree::json_parser::read_json(i, its_tree);
@@ -430,7 +428,7 @@ void configuration_impl::read_data(const std::set<std::string> &_input,
j++) {
auto its_file_path = j->path();
if (!boost::filesystem::is_directory(its_file_path)) {
- std::string its_name = its_file_path.string();
+ const std::string& its_name = its_file_path.string();
if (is_mandatory(its_name) == _mandatory_only) {
boost::property_tree::ptree its_tree;
try {
@@ -448,12 +446,12 @@ void configuration_impl::read_data(const std::set<std::string> &_input,
}
-bool configuration_impl::load_data(const std::vector<element> &_elements,
+bool configuration_impl::load_data(const std::vector<configuration_element> &_elements,
bool _load_mandatory, bool _load_optional) {
// Load logging configuration data
std::set<std::string> its_warnings;
if (!is_logging_loaded_) {
- for (auto e : _elements)
+ for (const auto& e : _elements)
is_logging_loaded_
= load_logging(e, its_warnings) || is_logging_loaded_;
@@ -468,7 +466,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
bool has_applications(false);
if (_load_mandatory) {
// Load mandatory configuration data
- for (auto e : _elements) {
+ for (const auto& e : _elements) {
has_routing = load_routing(e) || has_routing;
has_applications = load_applications(e) || has_applications;
load_network(e);
@@ -478,19 +476,19 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
load_endpoint_queue_sizes(e);
load_tcp_restart_settings(e);
load_permissions(e);
- load_policies(e);
+ load_security(e);
load_tracing(e);
load_udp_receive_buffer_size(e);
- load_security_update_whitelist(e);
- load_routing_credentials(e);
}
}
if (_load_optional) {
- for (auto e : _elements) {
+ for (const auto& e : _elements) {
load_unicast_address(e);
load_netmask(e);
+ load_device(e);
load_service_discovery(e);
+ load_npdu_default_timings(e);
load_services(e);
load_internal_services(e);
load_clients(e);
@@ -498,7 +496,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
load_selective_broadcasts_support(e);
load_e2e(e);
load_debounce(e);
- load_offer_acceptance_required(e);
+ load_sd_acceptance_required(e);
}
}
@@ -506,7 +504,7 @@ bool configuration_impl::load_data(const std::vector<element> &_elements,
}
bool configuration_impl::load_logging(
- const element &_element, std::set<std::string> &_warnings) {
+ const configuration_element &_element, std::set<std::string> &_warnings) {
try {
auto its_logging = _element.tree_.get_child("logging");
for (auto i = its_logging.begin(); i != its_logging.end(); ++i) {
@@ -601,7 +599,8 @@ bool configuration_impl::load_logging(
return true;
}
-bool configuration_impl::load_routing(const element &_element) {
+bool
+configuration_impl::load_routing(const configuration_element &_element) {
try {
auto its_routing = _element.tree_.get_child("routing");
if (is_configured_[ET_ROUTING]) {
@@ -617,54 +616,9 @@ bool configuration_impl::load_routing(const element &_element) {
return true;
}
-bool configuration_impl::load_routing_credentials(const element &_element) {
- try {
- auto its_routing_cred = _element.tree_.get_child("routing-credentials");
- if (is_configured_[ET_ROUTING_CREDENTIALS]) {
- VSOMEIP_WARNING << "vSomeIP Security: Multiple definitions of routing-credentials."
- << " Ignoring definition from " << _element.name_;
- } else {
- for (auto i = its_routing_cred.begin();
- i != its_routing_cred.end();
- ++i) {
- std::string its_key(i->first);
- std::string its_value(i->second.data());
- std::stringstream its_converter;
- if (its_key == "uid") {
- uint32_t its_uid(0);
- if (its_value.find("0x") == 0) {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_uid;
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- std::get<0>(routing_credentials_) = its_uid;
- } else if (its_key == "gid") {
- uint32_t its_gid(0);
- if (its_value.find("0x") == 0) {
- its_converter << std::hex << its_value;
- } else {
- its_converter << std::dec << its_value;
- }
- its_converter >> its_gid;
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- std::get<1>(routing_credentials_) = its_gid;
- }
- }
- check_routing_credentials_ = true;
- is_configured_[ET_ROUTING_CREDENTIALS] = true;
- }
- } catch (...) {
- return false;
- }
- return true;
-}
-
-
-bool configuration_impl::load_applications(const element &_element) {
+bool
+configuration_impl::load_applications(const configuration_element &_element) {
try {
- std::stringstream its_converter;
auto its_applications = _element.tree_.get_child("applications");
for (auto i = its_applications.begin();
i != its_applications.end();
@@ -680,13 +634,14 @@ bool configuration_impl::load_applications(const element &_element) {
void configuration_impl::load_application_data(
const boost::property_tree::ptree &_tree, const std::string &_file_name) {
std::string its_name("");
- client_t its_id(0);
+ client_t its_id(VSOMEIP_CLIENT_UNSET);
std::size_t its_max_dispatchers(VSOMEIP_MAX_DISPATCHERS);
std::size_t its_max_dispatch_time(VSOMEIP_MAX_DISPATCH_TIME);
std::size_t its_io_thread_count(VSOMEIP_IO_THREAD_COUNT);
std::size_t its_request_debounce_time(VSOMEIP_REQUEST_DEBOUNCE_TIME);
std::map<plugin_type_e, std::set<std::string>> plugins;
int its_io_thread_nice_level(VSOMEIP_IO_THREAD_NICE_LEVEL);
+ std::string its_overlay;
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
std::string its_value(i->second.data());
@@ -727,42 +682,14 @@ void configuration_impl::load_application_data(
its_request_debounce_time = 10000;
}
} else if (its_key == "plugins") {
- for (auto l = i->second.begin(); l != i->second.end(); ++l) {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- std::string its_inner_key(n->first);
- std::string its_inner_value(n->second.data());
- #ifdef _WIN32
- std::string library(its_inner_value);
- library += ".dll";
- #else
- std::string library("lib");
- library += its_inner_value;
- library += ".so";
- #endif
- if (its_inner_key == "application_plugin") {
- #ifndef _WIN32
- library += ".";
- library += std::to_string(std::uint32_t(VSOMEIP_APPLICATION_PLUGIN_VERSION));
- #endif
- plugins[plugin_type_e::APPLICATION_PLUGIN].insert(library);
- } else if (its_inner_key == "configuration_plugin") {
- #ifndef _WIN32
- library += ".";
- library += std::to_string(std::uint32_t(VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION));
- #endif
- plugins[plugin_type_e::PRE_CONFIGURATION_PLUGIN].insert(library);
- } else {
- VSOMEIP_WARNING << "Unknown plug-in type ("
- << its_inner_key << ") configured for client: "
- << its_name;
- }
- }
- }
+ plugins = load_plugins(i->second, its_name);
+ } else if (its_key == "overlay") {
+ its_overlay = its_value;
}
}
if (its_name != "") {
if (applications_.find(its_name) == applications_.end()) {
- if (its_id > 0) {
+ if (its_id != VSOMEIP_CLIENT_UNSET) {
if (!is_configured_client_id(its_id)) {
client_identifiers_.insert(its_id);
} else {
@@ -770,13 +697,14 @@ void configuration_impl::load_application_data(
<< " client identifier " << std::hex << its_id
<< ". Ignoring the configuration for application "
<< its_name;
- its_id = 0;
+ its_id = VSOMEIP_CLIENT_UNSET;
}
}
applications_[its_name]
= std::make_tuple(its_id, its_max_dispatchers,
its_max_dispatch_time, its_io_thread_count,
- its_request_debounce_time, plugins, its_io_thread_nice_level);
+ its_request_debounce_time, plugins, its_io_thread_nice_level,
+ its_overlay);
} else {
VSOMEIP_WARNING << "Multiple configurations for application "
<< its_name << ". Ignoring a configuration from "
@@ -785,9 +713,86 @@ void configuration_impl::load_application_data(
}
}
-void configuration_impl::load_tracing(const element &_element) {
+std::map<plugin_type_e, std::set<std::string>> configuration_impl::load_plugins(
+ const boost::property_tree::ptree &_tree,
+ const std::string& _application_name) {
+ std::map<plugin_type_e, std::set<std::string>> its_plugins;
+ std::string its_name("");
+ std::string its_type;
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ bool its_configured[ET_MAX] = { 0 };
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ std::string its_inner_key(l->first);
+ std::string its_inner_value(l->second.data());
+
+ if (its_inner_key == "name") {
+ if (its_configured[ET_PLUGIN_NAME]) {
+ VSOMEIP_WARNING << "Multiple definitions of plugins.name."
+ << " Ignoring definition from " << its_inner_value;
+ } else {
+ its_name = its_inner_value;
+ its_configured[ET_PLUGIN_NAME] = true;
+ }
+ } else if (its_inner_key == "type") {
+ if (its_configured[ET_PLUGIN_TYPE]) {
+ VSOMEIP_WARNING << "Multiple definitions of plugins.type."
+ << " Ignoring definition from " << its_inner_value;
+ } else {
+ its_type = its_inner_value;
+ its_configured[ET_PLUGIN_TYPE] = true;
+ }
+ } else {
+ //support old config format (type : name)
+ plugin_config_data_t its_plugin_data = {
+ its_inner_value, its_inner_key };
+ add_plugin(its_plugins, its_plugin_data, _application_name);
+ }
+ }
+
+ if (its_configured[ET_PLUGIN_NAME] && its_configured[ET_PLUGIN_TYPE]) {
+ plugin_config_data_t its_plugin_data = {
+ its_name, its_type };
+ add_plugin(its_plugins, its_plugin_data, _application_name);
+ }
+ }
+
+ return its_plugins;
+}
+
+void configuration_impl::add_plugin(std::map<plugin_type_e, std::set<std::string>> &_plugins,
+ const plugin_config_data_t &_plugin_data,
+ const std::string& _application_name) {
+
+#ifdef _WIN32
+ std::string its_library(_plugin_data.name_);
+ its_library += ".dll";
+#else
+ std::string its_library("lib");
+ its_library += _plugin_data.name_;
+ its_library += ".so";
+#endif
+
+ if (_plugin_data.type_ == "application_plugin") {
+#ifndef _WIN32
+ its_library += ".";
+ its_library += (VSOMEIP_APPLICATION_PLUGIN_VERSION + '0');
+#endif
+ _plugins[plugin_type_e::APPLICATION_PLUGIN].insert(its_library);
+ } else if (_plugin_data.type_ == "configuration_plugin") {
+#ifndef _WIN32
+ its_library += ".";
+ its_library += (VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION + '0');
+#endif
+ _plugins[plugin_type_e::PRE_CONFIGURATION_PLUGIN].insert(its_library);
+ } else {
+ VSOMEIP_WARNING << "Unknown plug-in type ("
+ << _plugin_data.type_ << ") configured for client: "
+ << _application_name;
+ }
+}
+
+void configuration_impl::load_tracing(const configuration_element &_element) {
try {
- std::stringstream its_converter;
auto its_trace_configuration = _element.tree_.get_child("tracing");
for(auto i = its_trace_configuration.begin();
i != its_trace_configuration.end();
@@ -900,7 +905,7 @@ void configuration_impl::load_trace_filter_expressions(
std::shared_ptr<trace_filter> &_filter) {
if (_criteria == "services") {
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- vsomeip::trace::match_t its_match;
+ vsomeip_v3::trace::match_t its_match;
load_trace_filter_match(i->second, its_match);
_filter->matches_.push_back(its_match);
}
@@ -916,7 +921,7 @@ void configuration_impl::load_trace_filter_expressions(
}
} else if (_criteria == "matches") {
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- vsomeip::trace::match_t its_match;
+ vsomeip_v3::trace::match_t its_match;
load_trace_filter_match(i->second, its_match);
if (i->first == "from") {
_filter->is_range_ = true;
@@ -931,11 +936,11 @@ void configuration_impl::load_trace_filter_expressions(
void configuration_impl::load_trace_filter_match(
const boost::property_tree::ptree &_data,
- vsomeip::trace::match_t &_match) {
+ vsomeip_v3::trace::match_t &_match) {
std::stringstream its_converter;
if (_data.size() == 0) {
- std::string its_value(_data.data());
+ const std::string& its_value(_data.data());
service_t its_service(ANY_SERVICE);
if (its_value.find("0x") == 0) {
its_converter << std::hex << its_value;
@@ -997,10 +1002,10 @@ void configuration_impl::load_trace_filter_match(
}
}
-void configuration_impl::load_unicast_address(const element &_element) {
+void configuration_impl::load_unicast_address(const configuration_element &_element) {
try {
std::string its_value = _element.tree_.get<std::string>("unicast");
- if (is_configured_[ET_UNICAST]) {
+ if (!is_overlay_ && is_configured_[ET_UNICAST]) {
VSOMEIP_WARNING << "Multiple definitions for unicast."
"Ignoring definition from " << _element.name_;
} else {
@@ -1012,10 +1017,10 @@ void configuration_impl::load_unicast_address(const element &_element) {
}
}
-void configuration_impl::load_netmask(const element &_element) {
+void configuration_impl::load_netmask(const configuration_element &_element) {
try {
std::string its_value = _element.tree_.get<std::string>("netmask");
- if (is_configured_[ET_NETMASK]) {
+ if (!is_overlay_ && is_configured_[ET_NETMASK]) {
VSOMEIP_WARNING << "Multiple definitions for netmask."
"Ignoring definition from " << _element.name_;
} else {
@@ -1027,10 +1032,25 @@ void configuration_impl::load_netmask(const element &_element) {
}
}
-void configuration_impl::load_network(const element &_element) {
+void configuration_impl::load_device(const configuration_element &_element) {
+ try {
+ std::string its_value = _element.tree_.get<std::string>("device");
+ if (!is_overlay_ && is_configured_[ET_DEVICE]) {
+ VSOMEIP_WARNING << "Multiple definitions for device."
+ "Ignoring definition from " << _element.name_;
+ } else {
+ device_ = its_value;
+ is_configured_[ET_DEVICE] = true;
+ }
+ } catch (...) {
+ // intentionally left empty!
+ }
+}
+
+void configuration_impl::load_network(const configuration_element &_element) {
try {
std::string its_value(_element.tree_.get<std::string>("network"));
- if (is_configured_[ET_NETWORK]) {
+ if (!is_overlay_ && is_configured_[ET_NETWORK]) {
VSOMEIP_WARNING << "Multiple definitions for network."
"Ignoring definition from " << _element.name_;
} else {
@@ -1042,10 +1062,10 @@ void configuration_impl::load_network(const element &_element) {
}
}
-void configuration_impl::load_diagnosis_address(const element &_element) {
+void configuration_impl::load_diagnosis_address(const configuration_element &_element) {
try {
std::string its_value = _element.tree_.get<std::string>("diagnosis");
- if (is_configured_[ET_DIAGNOSIS]) {
+ if (!is_overlay_ && is_configured_[ET_DIAGNOSIS]) {
VSOMEIP_WARNING << "Multiple definitions for diagnosis."
"Ignoring definition from " << _element.name_;
} else {
@@ -1060,7 +1080,7 @@ void configuration_impl::load_diagnosis_address(const element &_element) {
is_configured_[ET_DIAGNOSIS] = true;
}
std::string its_mask = _element.tree_.get<std::string>("diagnosis_mask");
- if (is_configured_[ET_DIAGNOSIS_MASK]) {
+ if (!is_overlay_ && is_configured_[ET_DIAGNOSIS_MASK]) {
VSOMEIP_WARNING << "Multiple definitions for diagnosis_mask."
"Ignoring definition from " << _element.name_;
} else {
@@ -1074,12 +1094,20 @@ void configuration_impl::load_diagnosis_address(const element &_element) {
its_converter >> diagnosis_mask_;
is_configured_[ET_DIAGNOSIS_MASK] = true;
}
+ if (is_configured_[ET_DIAGNOSIS] && is_configured_[ET_DIAGNOSIS_MASK]
+ && (static_cast<std::uint16_t>(diagnosis_ << 8) & diagnosis_mask_)
+ != static_cast<std::uint16_t>(diagnosis_ << 8)) {
+ VSOMEIP_WARNING << "Diagnosis mask masks bits of diagnosis prefix! "
+ "Client IDs will start at 0x" << std::hex <<
+ (static_cast<std::uint16_t>(diagnosis_ << 8) & diagnosis_mask_)
+ << " not at 0x" << static_cast<std::uint16_t>(diagnosis_ << 8);
+ }
} catch (...) {
// intentionally left empty
}
}
-void configuration_impl::load_shutdown_timeout(const element &_element) {
+void configuration_impl::load_shutdown_timeout(const configuration_element &_element) {
const std::string shutdown_timeout("shutdown_timeout");
try {
if (_element.tree_.get_child_optional(shutdown_timeout)) {
@@ -1105,7 +1133,7 @@ void configuration_impl::load_shutdown_timeout(const element &_element) {
}
void configuration_impl::load_service_discovery(
- const element &_element) {
+ const configuration_element &_element) {
try {
auto its_service_discovery = _element.tree_.get_child("service-discovery");
for (auto i = its_service_discovery.begin();
@@ -1114,7 +1142,7 @@ void configuration_impl::load_service_discovery(
std::string its_value(i->second.data());
std::stringstream its_converter;
if (its_key == "enable") {
- if (is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_ENABLE]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.enabled."
" Ignoring definition from " << _element.name_;
} else {
@@ -1122,7 +1150,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_ENABLE] = true;
}
} else if (its_key == "multicast") {
- if (is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_MULTICAST]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.multicast."
" Ignoring definition from " << _element.name_;
} else {
@@ -1130,7 +1158,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_MULTICAST] = true;
}
} else if (its_key == "port") {
- if (is_configured_[ET_SERVICE_DISCOVERY_PORT]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_PORT]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.port."
" Ignoring definition from " << _element.name_;
} else {
@@ -1143,7 +1171,7 @@ void configuration_impl::load_service_discovery(
}
}
} else if (its_key == "protocol") {
- if (is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.protocol."
" Ignoring definition from " << _element.name_;
} else {
@@ -1151,7 +1179,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_PROTOCOL] = true;
}
} else if (its_key == "initial_delay_min") {
- if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_min."
" Ignoring definition from " << _element.name_;
} else {
@@ -1160,7 +1188,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MIN] = true;
}
} else if (its_key == "initial_delay_max") {
- if (is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.initial_delay_max."
" Ignoring definition from " << _element.name_;
} else {
@@ -1169,7 +1197,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_INITIAL_DELAY_MAX] = true;
}
} else if (its_key == "repetitions_base_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_base_delay."
" Ignoring definition from " << _element.name_;
} else {
@@ -1178,7 +1206,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_REPETITION_BASE_DELAY] = true;
}
} else if (its_key == "repetitions_max") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.repetition_max."
" Ignoring definition from " << _element.name_;
} else {
@@ -1191,18 +1219,22 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_REPETITION_MAX] = true;
}
} else if (its_key == "ttl") {
- if (is_configured_[ET_SERVICE_DISCOVERY_TTL]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl."
" Ignoring definition from " << _element.name_;
} else {
its_converter << its_value;
its_converter >> sd_ttl_;
// We do _not_ accept 0 as this would mean "STOP OFFER"
- if (sd_ttl_ == 0) sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL;
+ if (sd_ttl_ == 0) {
+ VSOMEIP_WARNING << "TTL=0 is not allowed. Using default ("
+ << std::dec << VSOMEIP_SD_DEFAULT_TTL << ")";
+ sd_ttl_ = VSOMEIP_SD_DEFAULT_TTL;
+ }
else is_configured_[ET_SERVICE_DISCOVERY_TTL] = true;
}
} else if (its_key == "cyclic_offer_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.cyclic_offer_delay."
" Ignoring definition from " << _element.name_;
} else {
@@ -1211,7 +1243,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_CYCLIC_OFFER_DELAY] = true;
}
} else if (its_key == "request_response_delay") {
- if (is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.request_response_delay."
" Ignoring definition from " << _element.name_;
} else {
@@ -1220,7 +1252,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_REQUEST_RESPONSE_DELAY] = true;
}
} else if (its_key == "offer_debounce_time") {
- if (is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.offer_debounce."
" Ignoring definition from " << _element.name_;
} else {
@@ -1229,7 +1261,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_OFFER_DEBOUNCE_TIME] = true;
}
} else if (its_key == "ttl_factor_offers") {
- if (is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_offers."
" Ignoring definition from " << _element.name_;
} else {
@@ -1237,7 +1269,7 @@ void configuration_impl::load_service_discovery(
is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_OFFERS] = true;
}
} else if (its_key == "ttl_factor_subscriptions") {
- if (is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS]) {
+ if (!is_overlay_ && is_configured_[ET_SERVICE_DISCOVERY_TTL_FACTOR_SUBSCRIPTIONS]) {
VSOMEIP_WARNING << "Multiple definitions for service_discovery.ttl_factor_subscriptions."
" Ignoring definition from " << _element.name_;
} else {
@@ -1288,12 +1320,51 @@ void configuration_impl::load_delays(
}
}
-void configuration_impl::load_services(const element &_element) {
+void configuration_impl::load_npdu_default_timings(const configuration_element &_element) {
+ const std::string ndt("npdu-default-timings");
+ const std::string dreq("debounce-time-request");
+ const std::string dres("debounce-time-response");
+ const std::string rreq("max-retention-time-request");
+ const std::string rresp("max-retention-time-response");
+ try {
+ if (_element.tree_.get_child_optional(ndt)) {
+ if (!is_overlay_ && is_configured_[ET_NPDU_DEFAULT_TIMINGS]) {
+ VSOMEIP_WARNING << "Multiple definitions of " << ndt
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ for (const auto& e : _element.tree_.get_child(ndt)) {
+ std::chrono::nanoseconds its_time(0);
+ try {
+ its_time = std::chrono::nanoseconds(
+ std::strtoull(e.second.data().c_str(), NULL, 10)
+ * 1000000);
+ } catch (const std::exception& e) {
+ continue;
+ }
+ if (e.first.data() == dreq) {
+ npdu_default_debounce_requ_ = its_time;
+ } else if (e.first.data() == dres) {
+ npdu_default_debounce_resp_ = its_time;
+ } else if (e.first.data() == rreq) {
+ npdu_default_max_retention_requ_ = its_time;
+ } else if (e.first.data() == rresp) {
+ npdu_default_max_retention_resp_ = its_time;
+ }
+ }
+ is_configured_[ET_NPDU_DEFAULT_TIMINGS] = true;
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
+void configuration_impl::load_services(const configuration_element &_element) {
std::lock_guard<std::mutex> its_lock(services_mutex_);
try {
auto its_services = _element.tree_.get_child("services");
for (auto i = its_services.begin(); i != its_services.end(); ++i)
- load_service(i->second, "local");
+ load_service(i->second, default_unicast_);
} catch (...) {
try {
auto its_servicegroups = _element.tree_.get_child("servicegroups");
@@ -1308,7 +1379,7 @@ void configuration_impl::load_services(const element &_element) {
void configuration_impl::load_servicegroup(
const boost::property_tree::ptree &_tree) {
try {
- std::string its_unicast_address("local");
+ std::string its_unicast_address(default_unicast_);
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
std::string its_key(i->first);
@@ -1393,6 +1464,10 @@ void configuration_impl::load_service(
load_event(its_service, i->second);
} else if (its_key == "eventgroups") {
load_eventgroup(its_service, i->second);
+ } else if (its_key == "debounce-times") {
+ load_npdu_debounce_times_configuration(its_service, i->second);
+ } else if (its_key == "someip-tp") {
+ load_someip_tp(its_service, i->second);
} else {
// Trim "its_value"
if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
@@ -1427,6 +1502,40 @@ void configuration_impl::load_service(
if (use_magic_cookies) {
magic_cookies_[its_service->unicast_address_].insert(its_service->reliable_);
}
+
+ if (its_service->unicast_address_ == default_unicast_) {
+ // local services
+ if(its_service->reliable_ != ILLEGAL_PORT) {
+ services_by_ip_port_[unicast_.to_string()]
+ [its_service->reliable_]
+ [its_service->service_] = its_service;
+ }
+ if (its_service->unreliable_ != ILLEGAL_PORT) {
+ services_by_ip_port_[unicast_.to_string()]
+ [its_service->unreliable_]
+ [its_service->service_] = its_service;
+ // This is necessary as all udp server endpoints listen on
+ // INADDR_ANY instead of a specific address
+ services_by_ip_port_[boost::asio::ip::address_v4::any().to_string()]
+ [its_service->unreliable_]
+ [its_service->service_] = its_service;
+ services_by_ip_port_[boost::asio::ip::address_v6::any().to_string()]
+ [its_service->unreliable_]
+ [its_service->service_] = its_service;
+ }
+ } else {
+ // remote services
+ if (its_service->reliable_ != ILLEGAL_PORT) {
+ services_by_ip_port_[its_service->unicast_address_]
+ [its_service->reliable_]
+ [its_service->service_] = its_service;
+ }
+ if (its_service->unreliable_ != ILLEGAL_PORT) {
+ services_by_ip_port_[its_service->unicast_address_]
+ [its_service->unreliable_]
+ [its_service->service_] = its_service;
+ }
+ }
}
} catch (...) {
// Intentionally left empty
@@ -1439,7 +1548,7 @@ void configuration_impl::load_event(
for (auto i = _tree.begin(); i != _tree.end(); ++i) {
event_t its_event_id(0);
bool its_is_field(false);
- bool its_is_reliable(false);
+ reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
for (auto j = i->second.begin(); j != i->second.end(); ++j) {
std::string its_key(j->first);
@@ -1455,7 +1564,10 @@ void configuration_impl::load_event(
} else if (its_key == "is_field") {
its_is_field = (its_value == "true");
} else if (its_key == "is_reliable") {
- its_is_reliable = (its_value == "true");
+ if (its_value == "true")
+ its_reliability = reliability_type_e::RT_RELIABLE;
+ else
+ its_reliability = reliability_type_e::RT_UNRELIABLE;
}
}
@@ -1467,8 +1579,23 @@ void configuration_impl::load_event(
<< _service->instance_ << "."
<< its_event_id << "]";
} else {
+ // If event reliability type was not configured,
+ if (its_reliability == reliability_type_e::RT_UNKNOWN) {
+ if (_service->reliable_ != ILLEGAL_PORT) {
+ its_reliability = reliability_type_e::RT_RELIABLE;
+ } else if (_service->unreliable_ != ILLEGAL_PORT) {
+ its_reliability = reliability_type_e::RT_UNRELIABLE;
+ }
+ VSOMEIP_WARNING << "Reliability type for event ["
+ << std::hex << _service->service_ << "."
+ << _service->instance_ << "."
+ << its_event_id << "] was not configured Using : "
+ << ((its_reliability == reliability_type_e::RT_RELIABLE)
+ ? "RT_RELIABLE" : "RT_UNRELIABLE");
+ }
+
std::shared_ptr<event> its_event = std::make_shared<event>(
- its_event_id, its_is_field, its_is_reliable);
+ its_event_id, its_is_field, its_reliability);
_service->events_[its_event_id] = its_event;
}
}
@@ -1534,7 +1661,7 @@ void configuration_impl::load_eventgroup(
its_event = find_event->second;
} else {
its_event = std::make_shared<event>(its_event_id,
- false, false);
+ false, reliability_type_e::RT_UNRELIABLE);
}
if (its_event) {
its_event->groups_.push_back(its_eventgroup);
@@ -1552,7 +1679,7 @@ void configuration_impl::load_eventgroup(
}
}
-void configuration_impl::load_internal_services(const element &_element) {
+void configuration_impl::load_internal_services(const configuration_element &_element) {
try {
auto optional = _element.tree_.get_child_optional("internal_services");
if (!optional) {
@@ -1623,7 +1750,7 @@ void configuration_impl::load_internal_services(const element &_element) {
}
}
-void configuration_impl::load_clients(const element &_element) {
+void configuration_impl::load_clients(const configuration_element &_element) {
try {
auto its_clients = _element.tree_.get_child("clients");
for (auto i = its_clients.begin(); i != its_clients.end(); ++i)
@@ -1731,7 +1858,7 @@ std::pair<uint16_t,uint16_t> configuration_impl::load_client_port_range(
return its_port_range;
}
-void configuration_impl::load_watchdog(const element &_element) {
+void configuration_impl::load_watchdog(const configuration_element &_element) {
try {
auto its_service_discovery = _element.tree_.get_child("watchdog");
for (auto i = its_service_discovery.begin();
@@ -1771,36 +1898,34 @@ void configuration_impl::load_watchdog(const element &_element) {
}
}
-void configuration_impl::load_payload_sizes(const element &_element) {
+void configuration_impl::load_payload_sizes(const configuration_element &_element) {
const std::string payload_sizes("payload-sizes");
const std::string max_local_payload_size("max-payload-size-local");
const std::string buffer_shrink_threshold("buffer-shrink-threshold");
const std::string max_reliable_payload_size("max-payload-size-reliable");
+ const std::string max_unreliable_payload_size("max-payload-size-unreliable");
try {
- if (_element.tree_.get_child_optional(max_local_payload_size)) {
- auto mpsl = _element.tree_.get_child(max_local_payload_size);
- std::string s(mpsl.data());
- try {
- // add 16 Byte for the SOME/IP header
- max_local_message_size_ = static_cast<std::uint32_t>(std::stoul(
- s.c_str(), NULL, 10) + 16);
- } catch (const std::exception &e) {
- VSOMEIP_ERROR<< __func__ << ": " << max_local_payload_size
- << " " << e.what();
- }
- }
- if (_element.tree_.get_child_optional(max_reliable_payload_size)) {
- auto mpsl = _element.tree_.get_child(max_reliable_payload_size);
- std::string s(mpsl.data());
- try {
- // add 16 Byte for the SOME/IP header
- max_reliable_message_size_ = static_cast<std::uint32_t>(std::stoul(
- s.c_str(), NULL, 10) + 16);
- } catch (const std::exception &e) {
- VSOMEIP_ERROR<< __func__ << ": " << max_reliable_payload_size
- << " " << e.what();
+ for (const auto& s : { max_local_payload_size,
+ max_reliable_payload_size, max_unreliable_payload_size }) {
+ if (_element.tree_.get_child_optional(s)) {
+ const std::string size_str(_element.tree_.get_child(s).data());
+ try {
+ // add 16 Byte for the SOME/IP header
+ const std::uint32_t its_size = static_cast<std::uint32_t>(
+ std::stoul(size_str.c_str(), NULL, 10) + 16);
+ if (s == max_local_payload_size) {
+ max_local_message_size_ = its_size;
+ } else if (s == max_reliable_payload_size) {
+ max_reliable_message_size_ = its_size;
+ } else if (s == max_unreliable_payload_size) {
+ max_unreliable_message_size_ = its_size;
+ }
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR<< __func__ << ": " << s << " " << e.what();
+ }
}
}
+
if (_element.tree_.get_child_optional(buffer_shrink_threshold)) {
auto bst = _element.tree_.get_child(buffer_shrink_threshold);
std::string s(bst.data());
@@ -1841,9 +1966,8 @@ void configuration_impl::load_payload_sizes(const element &_element) {
NULL, 10));
std::string s(j->second.get_child(max_payload_size).data());
// add 16 Byte for the SOME/IP header
- its_message_size = static_cast<std::uint32_t>(std::stoul(
- s.c_str(),
- NULL, 10) + 16);
+ its_message_size = static_cast<std::uint32_t>(
+ std::stoul(s.c_str(), NULL, 10) + 16);
} catch (const std::exception &e) {
VSOMEIP_ERROR << __func__ << ":" << e.what();
}
@@ -1881,12 +2005,24 @@ void configuration_impl::load_payload_sizes(const element &_element) {
<< "local message distribution.";
max_local_message_size_ = max_reliable_message_size_;
}
+ if (max_local_message_size_ != 0
+ && max_unreliable_message_size_ != 0
+ && max_unreliable_message_size_ > max_local_message_size_) {
+ VSOMEIP_WARNING << max_local_payload_size << " ("
+ << max_local_message_size_ - 16 << ") is configured"
+ << " smaller than " << max_unreliable_payload_size << " ("
+ << max_unreliable_message_size_ - 16 << "). "
+ << max_local_payload_size << " will be increased to "
+ << max_unreliable_message_size_ - 16 << " to ensure "
+ << "local message distribution.";
+ max_local_message_size_ = max_unreliable_message_size_;
+ }
}
} catch (...) {
}
}
-void configuration_impl::load_permissions(const element &_element) {
+void configuration_impl::load_permissions(const configuration_element &_element) {
const std::string file_permissions("file-permissions");
try {
if (_element.tree_.get_child_optional(file_permissions)) {
@@ -1911,644 +2047,34 @@ void configuration_impl::load_permissions(const element &_element) {
}
}
-void configuration_impl::load_selective_broadcasts_support(const element &_element) {
+void configuration_impl::load_security(const configuration_element &_element) {
+ security::get()->load(_element);
+}
+
+void configuration_impl::load_selective_broadcasts_support(const configuration_element &_element) {
try {
auto its_service_discovery = _element.tree_.get_child("supports_selective_broadcasts");
for (auto i = its_service_discovery.begin();
i != its_service_discovery.end(); ++i) {
- std::string its_key(i->first);
std::string its_value(i->second.data());
- std::stringstream its_converter;
- if (its_key == "address") {
- supported_selective_addresses.insert(its_value);
- }
+ supported_selective_addresses.insert(its_value);
}
} catch (...) {
}
}
-
-
-void configuration_impl::load_policies(const element &_element) {
-#ifdef _WIN32
- return;
-#endif
- try {
- auto optional = _element.tree_.get_child_optional("security");
- if (!optional) {
- return;
- }
- policy_enabled_ = true;
- auto found_policy = _element.tree_.get_child("security");
- for (auto its_security = found_policy.begin();
- its_security != found_policy.end(); ++its_security) {
- if (its_security->first == "check_credentials") {
- if (its_security->second.data() == "true") {
- check_credentials_ = true;
- } else {
- check_credentials_ = false;
- }
- } else if (its_security->first == "allow_remote_clients") {
- if (its_security->second.data() == "true") {
- allow_remote_clients_ = true;
- } else {
- allow_remote_clients_ = false;
- }
- } else if (its_security->first == "policies") {
- for (auto its_policy = its_security->second.begin();
- its_policy != its_security->second.end(); ++its_policy) {
- load_policy(its_policy->second);
- }
- }
- }
- } catch (...) {
- }
-}
-
-void configuration_impl::load_policy(const boost::property_tree::ptree &_tree) {
- client_t client = 0x0;
- std::shared_ptr<policy> policy(std::make_shared<policy>());
- bool has_been_inserted(false);
- bool allow_deny_set(false);
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- if (i->first == "client") {
- std::string value = i->second.data();
- if (value == "") {
- client_t firstClient(ILLEGAL_CLIENT);
- client_t lastClient(ILLEGAL_CLIENT);
- for (auto n = i->second.begin();
- n != i->second.end(); ++n) {
- if (n->first == "first") {
- std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> firstClient;
- } else if (n->first == "last") {
- std::stringstream its_converter;
- std::string value = n->second.data();
- its_converter << std::hex << value;
- its_converter >> lastClient;
- }
- }
- if (firstClient < lastClient && lastClient != ANY_CLIENT) {
- uint32_t overrides(0);
- for (client_t c = firstClient; c <= lastClient; ++c) {
- if (find_client_id_policy(c)) {
- overrides++;
- }
- }
- if (overrides) {
- VSOMEIP_WARNING << std::hex << "Security configuration: "
- << "for client range 0x" << firstClient
- << " - 0x" << lastClient
- << " will be ignored as it would override an already existing policy of "
- << std::dec << overrides << " clients!";
- } else {
- std::lock_guard<std::mutex> its_lock(policies_mutex_);
- policies_[std::make_pair(firstClient, lastClient)] = policy;
- }
- has_been_inserted = true;
- } else {
- VSOMEIP_WARNING << std::hex << "Security configuration: "
- << "Client range have to be ascending, \"first\"=0x"
- << firstClient << " : \"last\"=0x" << lastClient
- << " ~> Skip policy.";
- }
- } else {
- std::stringstream its_converter;
- its_converter << std::hex << value;
- its_converter >> client;
- if (client != 0x0) {
- if (find_client_id_policy(client)) {
- VSOMEIP_WARNING << std::hex << "Security configuration for client "
- << client
- << " will be ignored as it would overwrite an already existing policy!";
- } else {
- std::lock_guard<std::mutex> its_lock(policies_mutex_);
- policies_[std::make_pair(client, client)] = policy;
- }
- has_been_inserted= true;
- }
- }
- } else if (i->first == "credentials") {
- std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
- ranges_t its_uid_ranges, its_gid_ranges;
-
- bool has_uid(false), has_gid(false);
- bool has_uid_range(false), has_gid_range(false);
- for (auto n = i->second.begin();
- n != i->second.end(); ++n) {
- std::string its_key(n->first);
- std::string its_value(n->second.data());
- if (its_key == "uid") {
- if(n->second.data().empty()) {
- load_ranges(n->second, its_uid_ranges);
- has_uid_range = true;
- } else {
- if (its_value != "any") {
- uint32_t its_uid;
- std::stringstream its_converter;
- its_converter << std::dec << its_value;
- its_converter >> its_uid;
- std::get<0>(its_uid_range) = its_uid;
- std::get<1>(its_uid_range) = its_uid;
- } else {
- std::get<0>(its_uid_range) = 0;
- std::get<1>(its_uid_range) = 0xFFFFFFFF;
- }
- has_uid = true;
- }
- } else if (its_key == "gid") {
- if(n->second.data().empty()) {
- load_ranges(n->second, its_gid_ranges);
- has_gid_range = true;
- } else {
- if (its_value != "any") {
- uint32_t its_gid;
- std::stringstream its_converter;
- its_converter << std::dec << its_value;
- its_converter >> its_gid;
- std::get<0>(its_gid_range) = its_gid;
- std::get<1>(its_gid_range) = its_gid;
- } else {
- std::get<0>(its_gid_range) = 0;
- std::get<1>(its_gid_range) = 0xFFFFFFFF;
- }
- has_gid = true;
- }
- } else if (its_key == "allow" || its_key == "deny") {
- policy->allow_who_ = (its_key == "allow");
- load_credential(n->second, policy->ids_);
- }
- }
-
- if (has_uid && has_gid) {
- std::set<std::pair<uint32_t, uint32_t>> its_uids, its_gids;
-
- its_uids.insert(its_uid_range);
- its_gids.insert(its_gid_range);
-
- policy->allow_who_ = true;
- policy->ids_.insert(std::make_pair(its_uids, its_gids));
- }
- if (has_uid_range && has_gid_range) {
- policy->allow_who_ = true;
- policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
- }
- } else if (i->first == "allow") {
- if (allow_deny_set) {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"allow\" tag overrides "
- << "already set \"deny\" tag. "
- << "Either \"deny\" or \"allow\" is allowed.";
- }
- allow_deny_set = true;
- policy->allow_what_ = true;
- for (auto l = i->second.begin(); l != i->second.end(); ++l) {
- if (l->first == "requests") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t service = 0x0;
- instance_t instance = 0x0;
- ids_t its_instance_method_ranges;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- std::stringstream its_converter;
- if (k->first == "service") {
- std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> service;
- } else if (k->first == "instance") { // legacy definition for instances
- ranges_t its_instance_ranges;
- ranges_t its_method_ranges;
- std::string value = k->second.data();
- if (value != "any") {
- its_converter << std::hex << value;
- its_converter >> instance;
- if (instance != 0x0) {
- its_instance_ranges.insert(std::make_pair(instance, instance));
- its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- } else {
- its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
- its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
- } else if (k->first == "instances") { // new instances definition
- for (auto p = k->second.begin(); p != k->second.end(); ++p) {
- ranges_t its_instance_ranges;
- ranges_t its_method_ranges;
- for (auto m = p->second.begin(); m != p->second.end(); ++m) {
- if (m->first == "ids") {
- load_instance_ranges(m->second, its_instance_ranges);
- } else if (m->first == "methods") {
- load_instance_ranges(m->second, its_method_ranges);
- }
- if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
- its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
- }
- }
- }
- if (its_instance_method_ranges.empty()) {
- ranges_t its_legacy_instance_ranges;
- ranges_t its_legacy_method_ranges;
- its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- // try to only load instance ranges with any method to be allowed
- load_instance_ranges(k->second, its_legacy_instance_ranges);
- if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
- its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
- its_legacy_method_ranges));
- }
- }
- }
- }
- if (service != 0x0 && !its_instance_method_ranges.empty()) {
- policy->services_.insert(
- std::make_pair(service, its_instance_method_ranges));
- }
- }
- } else if (l->first == "offers") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t service = 0x0;
- instance_t instance = 0x0;
- ranges_t its_instance_ranges;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- std::stringstream its_converter;
- if (k->first == "service") {
- std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> service;
- } else if (k->first == "instance") { // legacy definition for instances
- std::string value = k->second.data();
- if (value != "any") {
- its_converter << std::hex << value;
- its_converter >> instance;
- if (instance != 0x0) {
- its_instance_ranges.insert(std::make_pair(instance, instance));
- }
- } else {
- its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- } else if (k->first == "instances") { // new instances definition
- load_instance_ranges(k->second, its_instance_ranges);
- }
- }
- if (service != 0x0 && !its_instance_ranges.empty()) {
- policy->offers_.insert(
- std::make_pair(service, its_instance_ranges));
- }
- }
- }
- }
- } else if (i->first == "deny") {
- if (allow_deny_set) {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"deny\" tag overrides "
- << "already set \"allow\" tag. "
- << "Either \"deny\" or \"allow\" is allowed.";
- }
- allow_deny_set = true;
- policy->allow_what_ = false;
- for (auto l = i->second.begin(); l != i->second.end(); ++l) {
- if (l->first == "requests") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t service = 0x0;
- instance_t instance = 0x0;
- ids_t its_instance_method_ranges;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- std::stringstream its_converter;
- if (k->first == "service") {
- std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> service;
- } else if (k->first == "instance") { // legacy definition for instances
- ranges_t its_instance_ranges;
- ranges_t its_method_ranges;
- std::string value = k->second.data();
- if (value != "any") {
- its_converter << std::hex << value;
- its_converter >> instance;
- if (instance != 0x0) {
- its_instance_ranges.insert(std::make_pair(instance, instance));
- its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- } else {
- its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
- its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
- } else if (k->first == "instances") { // new instances definition
- for (auto p = k->second.begin(); p != k->second.end(); ++p) {
- ranges_t its_instance_ranges;
- ranges_t its_method_ranges;
- for (auto m = p->second.begin(); m != p->second.end(); ++m) {
- if (m->first == "ids") {
- load_instance_ranges(m->second, its_instance_ranges);
- } else if (m->first == "methods") {
- load_instance_ranges(m->second, its_method_ranges);
- }
- if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
- its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
- }
- }
- }
- if (its_instance_method_ranges.empty()) {
- ranges_t its_legacy_instance_ranges;
- ranges_t its_legacy_method_ranges;
- its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
- // try to only load instance ranges with any method to be allowed
- load_instance_ranges(k->second, its_legacy_instance_ranges);
- if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
- its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
- its_legacy_method_ranges));
- }
- }
- }
- }
- if (service != 0x0 && !its_instance_method_ranges.empty()) {
- policy->services_.insert(
- std::make_pair(service, its_instance_method_ranges));
- }
- }
- }
- if (l->first == "offers") {
- for (auto n = l->second.begin(); n != l->second.end(); ++n) {
- service_t service = 0x0;
- instance_t instance = 0x0;
- ranges_t its_instance_ranges;
- for (auto k = n->second.begin(); k != n->second.end(); ++k) {
- std::stringstream its_converter;
- if (k->first == "service") {
- std::string value = k->second.data();
- its_converter << std::hex << value;
- its_converter >> service;
- } else if (k->first == "instance") { // legacy definition for instances
- std::string value = k->second.data();
- if (value != "any") {
- its_converter << std::hex << value;
- its_converter >> instance;
- if (instance != 0x0) {
- its_instance_ranges.insert(std::make_pair(instance, instance));
- }
- } else {
- its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
- }
- } else if (k->first == "instances") { // new instances definition
- load_instance_ranges(k->second, its_instance_ranges);
- }
- }
- if (service != 0x0 && !its_instance_ranges.empty()) {
- policy->offers_.insert(
- std::make_pair(service, its_instance_ranges));
- }
- }
- }
- }
- }
- }
-
- if (!has_been_inserted) {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- any_client_policies_.push_back(policy);
- }
-}
-
-void configuration_impl::load_credential(
- const boost::property_tree::ptree &_tree, ids_t &_ids) {
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- ranges_t its_uid_ranges, its_gid_ranges;
- for (auto j = i->second.begin(); j != i->second.end(); ++j) {
- std::string its_key(j->first);
- if (its_key == "uid") {
- load_ranges(j->second, its_uid_ranges);
- } else if (its_key == "gid") {
- load_ranges(j->second, its_gid_ranges);
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
- << "Malformed credential (contains illegal key \""
- << its_key << "\"";
- }
- }
-
- _ids.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
- }
-}
-
-void configuration_impl::load_security_update_whitelist(const element &_element) {
-#ifdef _WIN32
- return;
-#endif
- try {
- auto optional = _element.tree_.get_child_optional("security-update-whitelist");
- if (!optional) {
- return;
- }
- auto found_whitelist = _element.tree_.get_child("security-update-whitelist");
- for (auto its_whitelist = found_whitelist.begin();
- its_whitelist != found_whitelist.end(); ++its_whitelist) {
-
- if (its_whitelist->first == "uids") {
- {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- load_ranges(its_whitelist->second, uid_whitelist_);
- }
- } else if (its_whitelist->first == "services") {
- {
- std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
- load_service_ranges(its_whitelist->second, service_interface_whitelist_);
- }
- } else if (its_whitelist->first == "check-whitelist") {
- if (its_whitelist->second.data() == "true") {
- check_whitelist_ = true;
- } else {
- check_whitelist_ = false;
- }
- }
- }
- } catch (...) {
- }
-}
-
-void configuration_impl::load_ranges(
- const boost::property_tree::ptree &_tree, ranges_t &_range) {
- ranges_t its_ranges;
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- auto its_data = i->second;
- if (!its_data.data().empty()) {
- uint32_t its_id;
- std::stringstream its_converter;
- its_converter << std::dec << its_data.data();
- its_converter >> its_id;
- its_ranges.insert(std::make_pair(its_id, its_id));
- } else {
- uint32_t its_first, its_last;
- bool has_first(false), has_last(false);
- for (auto j = its_data.begin(); j != its_data.end(); ++j) {
- std::string its_key(j->first);
- std::string its_value(j->second.data());
- if (its_key == "first") {
- if (its_value == "max") {
- its_first = 0xFFFFFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::dec << j->second.data();
- its_converter >> its_first;
- }
- has_first = true;
- } else if (its_key == "last") {
- if (its_value == "max") {
- its_last = 0xFFFFFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::dec << j->second.data();
- its_converter >> its_last;
- }
- has_last = true;
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
- << " Malformed range. Contains illegal key ("
- << its_key << ")";
- }
- }
-
- if (has_first && has_last) {
- its_ranges.insert(std::make_pair(its_first, its_last));
- }
- }
- }
-
- _range = its_ranges;
-}
-
-void configuration_impl::load_instance_ranges(
- const boost::property_tree::ptree &_tree, ranges_t &_range) {
- ranges_t its_ranges;
- std::string key(_tree.data());
- if (key == "any") {
- its_ranges.insert(std::make_pair(0x01, 0xFFFF));
- _range = its_ranges;
- return;
- }
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- auto its_data = i->second;
- if (!its_data.data().empty()) {
- uint32_t its_id = 0x0;
- std::stringstream its_converter;
- its_converter << std::hex << its_data.data();
- its_converter >> its_id;
- if (its_id != 0x0) {
- its_ranges.insert(std::make_pair(its_id, its_id));
- }
- } else {
- uint32_t its_first, its_last;
- bool has_first(false), has_last(false);
- for (auto j = its_data.begin(); j != its_data.end(); ++j) {
- std::string its_key(j->first);
- std::string its_value(j->second.data());
- if (its_key == "first") {
- if (its_value == "max") {
- its_first = 0xFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::hex << j->second.data();
- its_converter >> its_first;
- }
- has_first = true;
- } else if (its_key == "last") {
- if (its_value == "max") {
- its_last = 0xFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::hex << j->second.data();
- its_converter >> its_last;
- }
- has_last = true;
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
- << " Malformed range. Contains illegal key ("
- << its_key << ")";
- }
- }
-
- if (has_first && has_last) {
- if( its_last > its_first) {
- its_ranges.insert(std::make_pair(its_first, its_last));
- }
- }
- }
- }
-
- _range = its_ranges;
-}
-
-void configuration_impl::load_service_ranges(
- const boost::property_tree::ptree &_tree, std::set<std::pair<service_t, service_t>> &_ranges) {
- std::set<std::pair<service_t, service_t>> its_ranges;
- std::string key(_tree.data());
- if (key == "any") {
- its_ranges.insert(std::make_pair(0x01, 0xFFFF));
- _ranges = its_ranges;
- return;
- }
- for (auto i = _tree.begin(); i != _tree.end(); ++i) {
- auto its_data = i->second;
- if (!its_data.data().empty()) {
- service_t its_id = 0x0;
- std::stringstream its_converter;
- its_converter << std::hex << its_data.data();
- its_converter >> its_id;
- if (its_id != 0x0) {
- its_ranges.insert(std::make_pair(its_id, its_id));
- }
- } else {
- service_t its_first, its_last;
- bool has_first(false), has_last(false);
- for (auto j = its_data.begin(); j != its_data.end(); ++j) {
- std::string its_key(j->first);
- std::string its_value(j->second.data());
- if (its_key == "first") {
- if (its_value == "max") {
- its_first = 0xFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::hex << j->second.data();
- its_converter >> its_first;
- }
- has_first = true;
- } else if (its_key == "last") {
- if (its_value == "max") {
- its_last = 0xFFFF;
- } else {
- std::stringstream its_converter;
- its_converter << std::hex << j->second.data();
- its_converter >> its_last;
- }
- has_last = true;
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Security interface whitelist configuration: "
- << " Malformed range. Contains illegal key ("
- << its_key << ")";
- }
- }
-
- if (has_first && has_last) {
- if( its_last >= its_first) {
- its_ranges.insert(std::make_pair(its_first, its_last));
- }
- }
- }
- }
-
- _ranges = its_ranges;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Internal helper
///////////////////////////////////////////////////////////////////////////////
void configuration_impl::set_magic_cookies_unicast_address() {
// get services with static routing that have magic cookies enabled
std::map<std::string, std::set<uint16_t> > its_magic_cookies_ = magic_cookies_;
- its_magic_cookies_.erase("local");
+ its_magic_cookies_.erase(default_unicast_);
//set unicast address of host for all services without static routing
- its_magic_cookies_[get_unicast_address().to_string()].insert(magic_cookies_["local"].begin(),
- magic_cookies_["local"].end());
+ its_magic_cookies_[get_unicast_address().to_string()].insert(
+ magic_cookies_[default_unicast_].begin(),
+ magic_cookies_[default_unicast_].end());
magic_cookies_.clear();
magic_cookies_ = its_magic_cookies_;
}
@@ -2592,11 +2118,15 @@ const boost::asio::ip::address& configuration_impl::get_netmask() const {
return netmask_;
}
-unsigned short configuration_impl::get_diagnosis_address() const {
+const std::string &configuration_impl::get_device() const {
+ return device_;
+}
+
+diagnosis_t configuration_impl::get_diagnosis_address() const {
return diagnosis_;
}
-std::uint16_t configuration_impl::get_diagnosis_mask() const {
+diagnosis_t configuration_impl::get_diagnosis_mask() const {
return diagnosis_mask_;
}
@@ -2636,7 +2166,7 @@ std::string configuration_impl::get_unicast_address(service_t _service,
its_unicast_address = its_service->unicast_address_;
}
- if (its_unicast_address == "local" || its_unicast_address == "") {
+ if (its_unicast_address == default_unicast_ || its_unicast_address == "") {
its_unicast_address = get_unicast_address().to_string();
}
return its_unicast_address;
@@ -2664,6 +2194,50 @@ uint16_t configuration_impl::get_unreliable_port(service_t _service,
return its_unreliable;
}
+void configuration_impl::get_configured_timing_requests(
+ service_t _service, std::string _ip_target,
+ std::uint16_t _port_target, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const {
+ if (_debounce_time == nullptr || _max_retention_time == nullptr) {
+ return;
+ }
+ service *its_service = find_service_by_ip_port(_service, _ip_target,
+ _port_target);
+ if (its_service) {
+ auto find_method = its_service->debounce_times_requests_.find(_method);
+ if (find_method != its_service->debounce_times_requests_.end()) {
+ *_debounce_time = find_method->second[0];
+ *_max_retention_time = find_method->second[1];
+ return;
+ }
+ }
+ *_debounce_time = npdu_default_debounce_requ_;
+ *_max_retention_time = npdu_default_max_retention_requ_;
+}
+
+void configuration_impl::get_configured_timing_responses(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method,
+ std::chrono::nanoseconds *_debounce_time,
+ std::chrono::nanoseconds *_max_retention_time) const {
+ if (_debounce_time == nullptr || _max_retention_time == nullptr) {
+ return;
+ }
+ service *its_service = find_service_by_ip_port(_service, _ip_service,
+ _port_service);
+ if (its_service) {
+ auto find_method = its_service->debounce_times_responses_.find(_method);
+ if (find_method != its_service->debounce_times_responses_.end()) {
+ *_debounce_time = find_method->second[0];
+ *_max_retention_time = find_method->second[1];
+ return;
+ }
+ }
+ *_debounce_time = npdu_default_debounce_resp_;
+ *_max_retention_time = npdu_default_max_retention_resp_;
+}
+
bool configuration_impl::is_someip(service_t _service,
instance_t _instance) const {
auto its_service = find_service(_service, _instance);
@@ -2708,6 +2282,7 @@ bool configuration_impl::get_client_port(
if (!is_configured) {
// Neither specific not generic configurarion available,
// use dynamic port configuration!
+ _client_port = 0;
return true;
}
@@ -2739,7 +2314,7 @@ const std::string & configuration_impl::get_routing_host() const {
}
client_t configuration_impl::get_id(const std::string &_name) const {
- client_t its_client = 0;
+ client_t its_client(VSOMEIP_CLIENT_UNSET);
auto found_application = applications_.find(_name);
if (found_application != applications_.end()) {
@@ -2813,8 +2388,8 @@ std::set<std::pair<service_t, instance_t> >
configuration_impl::get_remote_services() const {
std::lock_guard<std::mutex> its_lock(services_mutex_);
std::set<std::pair<service_t, instance_t> > its_remote_services;
- for (auto i : services_) {
- for (auto j : i.second) {
+ for (const auto& i : services_) {
+ for (const auto& j : i.second) {
if (is_remote(j.second)) {
its_remote_services.insert(std::make_pair(i.first, j.first));
}
@@ -2825,7 +2400,7 @@ configuration_impl::get_remote_services() const {
bool configuration_impl::is_mandatory(const std::string &_name) const {
std::set<std::string> its_candidates;
- for (auto m : mandatory_) {
+ for (const auto& m : mandatory_) {
if (m.size() <= _name.size()) {
its_candidates.insert(m);
}
@@ -2834,7 +2409,7 @@ bool configuration_impl::is_mandatory(const std::string &_name) const {
if (its_candidates.empty())
return false;
- for (auto c : its_candidates) {
+ for (const auto& c : its_candidates) {
if (std::equal(c.rbegin(), c.rend(), _name.rbegin())) {
return true;
}
@@ -2879,8 +2454,8 @@ void configuration_impl::trim(std::string &_s) {
);
}
-bool configuration_impl::is_remote(std::shared_ptr<service> _service) const {
- return (_service->unicast_address_ != "local" &&
+bool configuration_impl::is_remote(const std::shared_ptr<service>& _service) const {
+ return (_service->unicast_address_ != default_unicast_ &&
_service->unicast_address_ != "" &&
_service->unicast_address_ != unicast_.to_string() &&
_service->unicast_address_ != VSOMEIP_UNICAST_ADDRESS);
@@ -2945,23 +2520,39 @@ bool configuration_impl::find_port(uint16_t &_port, uint16_t _remote, bool _reli
return is_configured;
}
-bool configuration_impl::is_event_reliable(service_t _service,
+reliability_type_e
+configuration_impl::get_event_reliability(service_t _service,
instance_t _instance, event_t _event) const {
std::lock_guard<std::mutex> its_lock(services_mutex_);
- bool is_reliable(false);
+ reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
auto its_service = find_service_unlocked(_service, _instance);
if (its_service) {
auto its_event = its_service->events_.find(_event);
if (its_event != its_service->events_.end()) {
- return its_event->second->is_reliable_;
- } else {
- if (its_service->reliable_ != ILLEGAL_PORT &&
- its_service->unreliable_ == ILLEGAL_PORT) {
- is_reliable = true;
+ its_reliability = its_event->second->reliability_;
+ }
+ }
+ return its_reliability;
+}
+
+reliability_type_e
+configuration_impl::get_service_reliability(service_t _service,
+ instance_t _instance) const {
+ std::lock_guard<std::mutex> its_lock(services_mutex_);
+ reliability_type_e its_reliability(reliability_type_e::RT_UNKNOWN);
+ auto its_service = find_service_unlocked(_service, _instance);
+ if (its_service) {
+ if (its_service->reliable_ != ILLEGAL_PORT) {
+ if (its_service->unreliable_ != ILLEGAL_PORT) {
+ its_reliability = reliability_type_e::RT_BOTH;
+ } else {
+ its_reliability = reliability_type_e::RT_RELIABLE;
}
+ } else {
+ its_reliability = reliability_type_e::RT_UNRELIABLE;
}
}
- return is_reliable;
+ return its_reliability;
}
std::shared_ptr<service> configuration_impl::find_service(service_t _service,
@@ -2983,6 +2574,22 @@ std::shared_ptr<service> configuration_impl::find_service_unlocked(service_t _se
return its_service;
}
+service* configuration_impl::find_service_by_ip_port(
+ service_t _service, const std::string& _ip, std::uint16_t _port) const {
+ service *its_service(0);
+ auto find_ip = services_by_ip_port_.find(_ip);
+ if(find_ip != services_by_ip_port_.end()) {
+ auto find_port = find_ip->second.find(_port);
+ if(find_port != find_ip->second.end()) {
+ auto find_service = find_port->second.find(_service);
+ if(find_service != find_port->second.end()) {
+ its_service = find_service->second.get();
+ }
+ }
+ }
+ return its_service;
+}
+
std::shared_ptr<eventgroup> configuration_impl::find_eventgroup(
service_t _service, instance_t _instance,
eventgroup_t _eventgroup) const {
@@ -3036,6 +2643,11 @@ std::uint32_t configuration_impl::get_max_message_size_reliable(
VSOMEIP_MAX_TCP_MESSAGE_SIZE) : max_reliable_message_size_;
}
+std::uint32_t configuration_impl::get_max_message_size_unreliable() const {
+ return (max_unreliable_message_size_ == 0) ?
+ MESSAGE_SIZE_UNLIMITED : max_unreliable_message_size_;
+}
+
std::uint32_t configuration_impl::get_buffer_shrink_threshold() const {
return buffer_shrink_threshold_;
}
@@ -3087,11 +2699,11 @@ const std::string & configuration_impl::get_sd_protocol() const {
return sd_protocol_;
}
-int32_t configuration_impl::get_sd_initial_delay_min() const {
+uint32_t configuration_impl::get_sd_initial_delay_min() const {
return sd_initial_delay_min_;
}
-int32_t configuration_impl::get_sd_initial_delay_max() const {
+uint32_t configuration_impl::get_sd_initial_delay_max() const {
return sd_initial_delay_max_;
}
@@ -3144,420 +2756,6 @@ std::uint32_t configuration_impl::get_permissions_shm() const {
return permissions_shm_;
}
-bool configuration_impl::is_security_enabled() const {
- return policy_enabled_;
-}
-
-bool configuration_impl::is_audit_mode_enabled() const {
- return check_credentials_;
-}
-
-bool configuration_impl::check_credentials(client_t _client, uint32_t _uid,
- uint32_t _gid) {
- if (!policy_enabled_) {
- return true;
- }
-
- std::vector<std::shared_ptr<policy> > its_policies;
- bool has_id(false);
- auto found_policy = find_client_id_policy(_client);
- if (found_policy) {
- its_policies.push_back(found_policy);
- } else {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- for (const auto &p : its_policies) {
- for (auto its_credential : p->ids_) {
- bool has_uid(false), has_gid(false);
- for (auto its_range : std::get<0>(its_credential)) {
- if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
- has_uid = true;
- break;
- }
- }
- for (auto its_range : std::get<1>(its_credential)) {
- if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
- has_gid = true;
- break;
- }
- }
-
- if (has_uid && has_gid) {
- has_id = true;
- break;
- }
- }
-
- if ((has_id && p->allow_who_) || (!has_id && !p->allow_who_)) {
- if (!store_client_to_uid_gid_mapping(_client,_uid, _gid)) {
- std::string security_mode_text = "!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << _uid << "/" << _gid
- << " : Check credentials failed as existing credentials would be overwritten"
- << security_mode_text;
-
- return !check_credentials_;
- }
- store_uid_gid_to_client_mapping(_uid, _gid, _client);
- return true;
- }
- }
-
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << _uid << "/" << _gid
- << " : Check credentials failed" << security_mode_text;
-
-
- return !check_credentials_;
-}
-
-bool configuration_impl::is_client_allowed(client_t _client, service_t _service,
- instance_t _instance, method_t _method, bool _is_request_service) const {
- if (!policy_enabled_) {
- return true;
- }
-
- uint32_t its_uid(0xffffffff), its_gid(0xffffffff);
- bool must_apply(true);
- std::vector<std::shared_ptr<policy> > its_policies;
- auto found_policy = find_client_id_policy(_client);
- if (found_policy)
- its_policies.push_back(found_policy);
- else {
- must_apply = false;
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_id = ids_.find(_client);
- if (found_id != ids_.end()) {
- its_uid = found_id->second.first;
- its_gid = found_id->second.second;
- } else {
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " : Cannot determine uid/gid. Therefore it isn't allowed to communicate to service/instance "
- << _service << "/" << _instance
- << security_mode_text;
-
- return !check_credentials_;
- }
- }
-
- for (const auto &p : its_policies) {
- bool has_uid(false), has_gid(false), has_service(false), has_instance_id(false), has_method_id(false);
- if (must_apply) {
- has_uid = has_gid = p->allow_who_;
- } else {
- for (auto its_credential : p->ids_) {
- has_uid = has_gid = false;
- for (auto its_range : std::get<0>(its_credential)) {
- if (std::get<0>(its_range) <= its_uid && its_uid <= std::get<1>(its_range)) {
- has_uid = true;
- break;
- }
- }
- for (auto its_range : std::get<1>(its_credential)) {
- if (std::get<0>(its_range) <= its_gid && its_gid <= std::get<1>(its_range)) {
- has_gid = true;
- break;
- }
- }
-
- if (has_uid && has_gid)
- break;
- }
- }
-
- for (auto its_offer : p->services_) {
- if (std::get<0>(its_offer) == _service) {
- for (auto its_ids : std::get<1>(its_offer)) {
- has_service = has_instance_id = has_method_id = false;
- for (auto its_instance_range : std::get<0>(its_ids)) {
- if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
- has_instance_id = true;
- break;
- }
- }
- if (!_is_request_service) {
- for (auto its_method_range : std::get<1>(its_ids)) {
- if (std::get<0>(its_method_range) <= _method && _method <= std::get<1>(its_method_range)) {
- has_method_id = true;
- break;
- }
- }
- } else {
- // handle VSOMEIP_REQUEST_SERVICE
- has_method_id = true;
- }
-
- if (has_instance_id && has_method_id) {
- has_service = true;
- break;
- }
- }
- if (has_service)
- break;
- }
- }
-
- if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
- if (p->allow_what_) {
- // allow policy
- if (has_service) {
- return true;
- }
- } else {
- // deny policy
- // allow client if the service / instance / !ANY_METHOD was not found
- if ((!has_service && (_method != ANY_METHOD))
- // allow client if the service / instance / ANY_METHOD was not found
- // and it is a "deny nothing" policy
- || (!has_service && (_method == ANY_METHOD) && p->services_.empty())) {
- return true;
- }
- }
- }
- }
-
- std::string security_mode_text = " ~> Skip!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
- << " : Isn't allowed to communicate with service/instance/(method / event) " << std::hex
- << _service << "/" << _instance << "/" << _method
- << security_mode_text;
-
- return !check_credentials_;
-}
-
-bool configuration_impl::is_offer_allowed(client_t _client, service_t _service,
- instance_t _instance) const {
- if (!policy_enabled_) {
- return true;
- }
-
- uint32_t its_uid(0xffffffff), its_gid(0xffffffff);
- bool must_apply(true);
- std::vector<std::shared_ptr<policy> > its_policies;
- auto found_policy = find_client_id_policy(_client);
- if (found_policy)
- its_policies.push_back(found_policy);
- else {
- must_apply = false;
- {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- its_policies = any_client_policies_;
- }
-
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_id = ids_.find(_client);
- if (found_id != ids_.end()) {
- its_uid = found_id->second.first;
- its_gid = found_id->second.second;
- } else {
- std::string audit_mode_text = " ~> Skip offer!";
- if (!check_credentials_) {
- audit_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " : Cannot determine uid/gid. Therefore it isn't allowed to offer service/instance "
- << _service << "/" << _instance << audit_mode_text;
-
- return !check_credentials_;
- }
- }
-
- for (const auto &p : its_policies) {
- bool has_uid(false), has_gid(false), has_offer(false);
- if (must_apply) {
- has_uid = has_gid = p->allow_who_;
- } else {
- for (auto its_credential : p->ids_) {
- has_uid = has_gid = false;
- for (auto its_range : std::get<0>(its_credential)) {
- if (std::get<0>(its_range) <= its_uid && its_uid <= std::get<1>(its_range)) {
- has_uid = true;
- break;
- }
- }
- for (auto its_range : std::get<1>(its_credential)) {
- if (std::get<0>(its_range) <= its_gid && its_gid <= std::get<1>(its_range)) {
- has_gid = true;
- break;
- }
- }
-
- if (has_uid && has_gid)
- break;
- }
- }
-
- for (auto its_offer : p->offers_) {
- has_offer = false;
- if (std::get<0>(its_offer) == _service) {
- for (auto its_instance_range : std::get<1>(its_offer)) {
- if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
- has_offer = true;
- break;
- }
- }
- if (has_offer)
- break;
- }
- }
-
- if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
- if (p->allow_what_ == has_offer) {
- return true;
- }
- }
- }
-
- std::string security_mode_text = " ~> Skip offer!";
- if (!check_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
- }
-
- VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
- << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
- << " isn't allowed to offer service/instance " << std::hex
- << _service << "/" << _instance
- << security_mode_text;
-
-
- return !check_credentials_;
-}
-
-bool configuration_impl::store_client_to_uid_gid_mapping(client_t _client,
- uint32_t _uid, uint32_t _gid) {
- {
- // store the client -> (uid, gid) mapping
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_client = ids_.find(_client);
- if (found_client != ids_.end()) {
- if (found_client->second != std::make_pair(_uid, _gid)) {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x"
- << std::hex << _client << " with UID/GID="
- << std::dec << _uid << "/" << _gid << " : Overwriting existing credentials UID/GID="
- << std::dec << std::get<0>(found_client->second) << "/"
- << std::get<1>(found_client->second);
- found_client->second = std::make_pair(_uid, _gid);
- return true;
- }
- } else {
- ids_[_client] = std::make_pair(_uid, _gid);
- }
- return true;
- }
-}
-
-bool configuration_impl::get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid) {
- {
- // get the UID / GID of the client
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- if (ids_.find(_client) != ids_.end()) {
- _uid_gid = ids_[_client];
- return true;
- }
- return false;
- }
-}
-
-bool configuration_impl::remove_client_to_uid_gid_mapping(client_t _client) {
- std::pair<uint32_t, uint32_t> its_uid_gid;
- bool client_removed(false);
- bool uid_gid_removed(false);
- {
- std::lock_guard<std::mutex> its_lock(ids_mutex_);
- auto found_client = ids_.find(_client);
- if (found_client != ids_.end()) {
- its_uid_gid = found_client->second;
- ids_.erase(found_client);
- client_removed = true;
- }
- }
- {
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- if (client_removed) {
- auto found_uid_gid = uid_to_clients_.find(its_uid_gid);
- if (found_uid_gid != uid_to_clients_.end()) {
- auto its_client = found_uid_gid->second.find(_client);
- if (its_client != found_uid_gid->second.end()) {
- found_uid_gid->second.erase(its_client);
- if (found_uid_gid->second.empty()) {
- uid_to_clients_.erase(found_uid_gid);
- }
- uid_gid_removed = true;
- }
- }
- } else {
- for (auto its_uid_gid = uid_to_clients_.begin();
- its_uid_gid != uid_to_clients_.end(); ++its_uid_gid) {
- auto its_client = its_uid_gid->second.find(_client);
- if (its_client != its_uid_gid->second.end()) {
- its_uid_gid->second.erase(its_client);
- if (its_uid_gid->second.empty()) {
- uid_to_clients_.erase(its_uid_gid);
- }
- uid_gid_removed = true;
- break;
- }
- }
- }
- }
- return (client_removed && uid_gid_removed);
-}
-
-void configuration_impl::store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
- client_t _client) {
- {
- // store the uid gid to clients mapping
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- std::set<client_t> mapped_clients;
- if (uid_to_clients_.find(std::make_pair(_uid, _gid)) != uid_to_clients_.end()) {
- mapped_clients = uid_to_clients_[std::make_pair(_uid, _gid)];
- mapped_clients.insert(_client);
- uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
- } else {
- mapped_clients.insert(_client);
- uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
- }
- }
-}
-
-bool configuration_impl::get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
- std::set<client_t> &_clients) {
- {
- // get the clients corresponding to uid, gid
- std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
- if (uid_to_clients_.find(_uid_gid) != uid_to_clients_.end()) {
- _clients = uid_to_clients_[_uid_gid];
- return true;
- }
- return false;
- }
-}
-
std::map<plugin_type_e, std::set<std::string>> configuration_impl::get_plugins(
const std::string &_name) const {
std::map<plugin_type_e, std::set<std::string>> result;
@@ -3578,7 +2776,7 @@ bool configuration_impl::is_e2e_enabled() const {
return e2e_enabled_;
}
-void configuration_impl::load_e2e(const element &_element) {
+void configuration_impl::load_e2e(const configuration_element &_element) {
#ifdef _WIN32
return;
#endif
@@ -3614,15 +2812,10 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
service_t service_id(0);
event_t event_id(0);
- uint16_t crc_offset(0);
- uint8_t data_id_mode(0);
- uint16_t data_length(0);
- uint16_t data_id_nibble_offset(12); // data id nibble behind 4 bit counter value
- uint16_t counter_offset(8); // counter field behind CRC8
+ e2e::custom_parameters_t custom_parameters;
for (auto l = _tree.begin(); l != _tree.end(); ++l) {
std::stringstream its_converter;
- uint16_t tmp;
if (l->first == "data_id" && data_id == 0) {
std::string value = l->second.data();
if (value.size() > 1 && value[0] == '0' && value[1] == 'x') {
@@ -3655,28 +2848,8 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
std::string value = l->second.data();
its_converter << value;
its_converter >> profile;
- } else if (l->first == "crc_offset") {
- std::string value = l->second.data();
- its_converter << value;
- its_converter >> crc_offset;
- } else if (l->first == "counter_offset") {
- std::string value = l->second.data();
- its_converter << value;
- its_converter >> counter_offset;
- } else if (l->first == "data_id_mode") {
- std::string value = l->second.data();
- its_converter << value;
- its_converter >> tmp;
- data_id_mode = static_cast<uint8_t>(tmp);
- } else if (l->first == "data_id_nibble_offset") {
- std::string value = l->second.data();
- its_converter << value;
- its_converter >> data_id_nibble_offset;
- }
- else if (l->first == "data_length") {
- std::string value = l->second.data();
- its_converter << value;
- its_converter >> data_length;
+ } else {
+ custom_parameters[l->first.data()] = l->second.data();
}
}
e2e_configuration_[std::make_pair(service_id, event_id)] = std::make_shared<cfg::e2e>(
@@ -3685,11 +2858,7 @@ void configuration_impl::load_e2e_protected(const boost::property_tree::ptree &_
profile,
service_id,
event_id,
- crc_offset,
- data_id_mode,
- data_length,
- data_id_nibble_offset,
- counter_offset
+ std::move(custom_parameters)
);
}
@@ -3780,7 +2949,8 @@ configuration_impl::get_endpoint_queue_limit_local() const {
return endpoint_queue_limit_local_;
}
-void configuration_impl::load_endpoint_queue_sizes(const element &_element) {
+void
+configuration_impl::load_endpoint_queue_sizes(const configuration_element &_element) {
const std::string endpoint_queue_limits("endpoint-queue-limits");
const std::string endpoint_queue_limit_external("endpoint-queue-limit-external");
const std::string endpoint_queue_limit_local("endpoint-queue-limit-local");
@@ -3838,13 +3008,13 @@ void configuration_impl::load_endpoint_queue_sizes(const element &_element) {
const std::string port("port");
const std::string queue_size_limit("queue-size-limit");
- for (const auto i : _element.tree_.get_child(endpoint_queue_limits)) {
+ for (const auto& i : _element.tree_.get_child(endpoint_queue_limits)) {
if (!i.second.get_child_optional(unicast)
|| !i.second.get_child_optional(ports)) {
continue;
}
std::string its_unicast(i.second.get_child(unicast).data());
- for (const auto j : i.second.get_child(ports)) {
+ for (const auto& j : i.second.get_child(ports)) {
if (!j.second.get_child_optional(port)
|| !j.second.get_child_optional(queue_size_limit)) {
@@ -3878,7 +3048,8 @@ void configuration_impl::load_endpoint_queue_sizes(const element &_element) {
}
}
-void configuration_impl::load_debounce(const element &_element) {
+void
+configuration_impl::load_debounce(const configuration_element &_element) {
try {
auto its_debounce = _element.tree_.get_child("debounce");
for (auto i = its_debounce.begin(); i != its_debounce.end(); ++i) {
@@ -3888,8 +3059,8 @@ void configuration_impl::load_debounce(const element &_element) {
}
}
-void configuration_impl::load_service_debounce(
- const boost::property_tree::ptree &_tree) {
+void
+configuration_impl::load_service_debounce(const boost::property_tree::ptree &_tree) {
service_t its_service(0);
instance_t its_instance(0);
std::map<event_t, std::shared_ptr<debounce>> its_debounces;
@@ -4034,25 +3205,146 @@ void configuration_impl::load_event_debounce_ignore(
}
}
-void configuration_impl::load_offer_acceptance_required(
- const element &_element) {
- const std::string oar("offer_acceptance_required");
+void
+configuration_impl::load_sd_acceptance_required(
+ const configuration_element &_element) {
+ const std::string sar("sd_acceptance_required");
try {
- std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
- if (_element.tree_.get_child_optional(oar)) {
- if (is_configured_[ET_OFFER_ACCEPTANCE_REQUIRED]) {
- VSOMEIP_WARNING << "Multiple definitions of " << oar
+ std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
+ if (_element.tree_.get_child_optional(sar)) {
+ if (is_configured_[ET_SD_ACCEPTANCE_REQUIRED]) {
+ VSOMEIP_WARNING << "Multiple definitions of " << sar
<< " Ignoring definition from " << _element.name_;
} else {
- for (const auto& ipe : _element.tree_.get_child(oar)) {
+ for (const auto& ipe : _element.tree_.get_child(sar)) {
boost::system::error_code ec;
boost::asio::ip::address its_address =
boost::asio::ip::address::from_string(ipe.first.data(), ec);
if (!its_address.is_unspecified()) {
- offer_acceptance_required_ips_[its_address] = ipe.second.data();
+ sd_acceptance_required_ips_[{its_address, ANY_PORT}] = ipe.second.data();
}
}
- is_configured_[ET_OFFER_ACCEPTANCE_REQUIRED] = true;
+ is_configured_[ET_SD_ACCEPTANCE_REQUIRED] = true;
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
+bool configuration_impl::load_npdu_debounce_times_configuration(
+ const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree) {
+ bool is_loaded(true);
+ try {
+ for (const auto& i : _tree) {
+ const std::string its_key(i.first);
+ if (its_key == "requests") {
+ if (!load_npdu_debounce_times_for_service(_service, true, i.second)) {
+ is_loaded = false;
+ }
+ } else if (its_key == "responses") {
+ if (!load_npdu_debounce_times_for_service(_service, false, i.second)) {
+ is_loaded = false;
+ }
+ }
+ }
+ } catch (...) {
+ is_loaded = false;
+ }
+ return is_loaded;
+}
+
+bool configuration_impl::load_npdu_debounce_times_for_service(
+ const std::shared_ptr<service>& _service, bool _is_request,
+ const boost::property_tree::ptree &_tree) {
+ const std::string dtime("debounce-time");
+ const std::string rtime("maximum-retention-time");
+
+ bool is_loaded(true);
+ try {
+ std::stringstream its_converter;
+ for (const auto& i : _tree) {
+ const std::string its_method_str(i.first.data());
+ if (its_method_str.size()) {
+ method_t its_method = 0xFFFF;
+ if (its_method_str.size() > 1 && its_method_str[0] == '0'
+ && its_method_str[1] == 'x') {
+ its_converter << std::hex << its_method_str;
+ } else {
+ its_converter << std::dec << its_method_str;
+ }
+ its_converter >> its_method;
+ its_converter.str("");
+ its_converter.clear();
+
+ std::chrono::nanoseconds its_debounce_time(
+ npdu_default_debounce_requ_);
+ std::chrono::nanoseconds its_retention_time(
+ npdu_default_max_retention_requ_);
+ for (const auto& j : i.second) {
+ const std::string& key = j.first;
+ const std::uint64_t value = std::strtoull(
+ j.second.data().c_str(),
+ NULL, 10) * 1000000;
+ if (key == dtime) {
+ its_debounce_time = std::chrono::nanoseconds(value);
+ } else if (key == rtime) {
+ its_retention_time = std::chrono::nanoseconds(value);
+ }
+ }
+ if (_is_request) {
+ _service->debounce_times_requests_[its_method]
+ = {its_debounce_time, its_retention_time};
+ } else {
+ _service->debounce_times_responses_[its_method]
+ = { its_debounce_time, its_retention_time};
+ }
+ }
+ }
+ } catch (...) {
+ is_loaded = false;
+ }
+ return is_loaded;
+}
+
+void configuration_impl::load_someip_tp(
+ const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree) {
+ try {
+ for (const auto& i : _tree) {
+ const std::string its_key(i.first);
+ if (its_key == "client-to-service") {
+ load_someip_tp_for_service(_service, i.second, true);
+ } else if (its_key == "service-to-client") {
+ load_someip_tp_for_service(_service, i.second, false);
+ }
+ }
+ } catch (...) {
+ // intentionally left empty
+ }
+}
+
+void configuration_impl::load_someip_tp_for_service(
+ const std::shared_ptr<service>& _service,
+ const boost::property_tree::ptree &_tree, bool _is_request) {
+ try {
+ std::stringstream its_converter;
+ for (const auto& method : _tree) {
+ method_t its_method = 0xFFFF;
+ const std::string its_value(method.second.data());
+ if (its_value.size() > 1 && its_value[0] == '0' && its_value[1] == 'x') {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_method;
+ its_converter.str("");
+ its_converter.clear();
+ if (_is_request) {
+ _service->tp_segment_messages_client_to_service_.insert(its_method);
+ } else {
+ _service->tp_segment_messages_service_to_client_.insert(its_method);
}
}
} catch (...) {
@@ -4060,7 +3352,8 @@ void configuration_impl::load_offer_acceptance_required(
}
}
-void configuration_impl::load_udp_receive_buffer_size(const element &_element) {
+void
+configuration_impl::load_udp_receive_buffer_size(const configuration_element &_element) {
const std::string urbs("udp-receive-buffer-size");
try {
if (_element.tree_.get_child_optional(urbs)) {
@@ -4098,7 +3391,8 @@ std::shared_ptr<debounce> configuration_impl::get_debounce(
return nullptr;
}
-void configuration_impl::load_tcp_restart_settings(const element &_element) {
+void
+configuration_impl::load_tcp_restart_settings(const configuration_element &_element) {
const std::string tcp_restart_aborts_max("tcp-restart-aborts-max");
const std::string tcp_connect_time_max("tcp-connect-time-max");
@@ -4154,240 +3448,102 @@ std::uint32_t configuration_impl::get_max_tcp_connect_time() const {
return tcp_connect_time_max_;
}
-bool configuration_impl::offer_acceptance_required(
- const boost::asio::ip::address& _address) const {
- std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
- return offer_acceptance_required_ips_.find(_address)
- != offer_acceptance_required_ips_.end();
+bool configuration_impl::sd_acceptance_required(
+ const boost::asio::ip::address& _address, std::uint16_t _port) const {
+ std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
+ return sd_acceptance_required_ips_.find({_address, _port})
+ != sd_acceptance_required_ips_.end();
}
-void configuration_impl::set_offer_acceptance_required(
- const boost::asio::ip::address& _address, const std::string& _path,
- bool _enable) {
- std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
+void configuration_impl::set_sd_acceptance_required(
+ const boost::asio::ip::address& _address, std::uint16_t _port,
+ const std::string& _path, bool _enable) {
+ std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
if (_enable) {
- const auto found_address = offer_acceptance_required_ips_.find(_address);
- if (found_address != offer_acceptance_required_ips_.end()) {
+ const auto found_address = sd_acceptance_required_ips_.find({_address, _port});
+ if (found_address != sd_acceptance_required_ips_.end()) {
boost::system::error_code ec;
VSOMEIP_WARNING << __func__ << " configuration for: "
- << found_address->first.to_string(ec) << " -> "
- << found_address->second << " already configured."
+ << found_address->first.first.to_string(ec) << ":"
+ << std::dec << _port << " -> "
+ << found_address->first.second << " already configured."
<< " Won't update with: "<< _path;
} else {
- offer_acceptance_required_ips_[_address] = _path;
+ sd_acceptance_required_ips_[{_address, _port}] = _path;
}
} else {
- offer_acceptance_required_ips_.erase(_address);
+ sd_acceptance_required_ips_.erase({_address, _port});
}
}
-std::map<boost::asio::ip::address, std::string>
-configuration_impl::get_offer_acceptance_required() {
- std::lock_guard<std::mutex> its_lock(offer_acceptance_required_ips_mutex_);
- return offer_acceptance_required_ips_;
+configuration::sd_acceptance_required_map_t configuration_impl::get_sd_acceptance_required() {
+ std::lock_guard<std::mutex> its_lock(sd_acceptance_required_ips_mutex_);
+ return sd_acceptance_required_ips_;
}
std::uint32_t configuration_impl::get_udp_receive_buffer_size() const {
return udp_receive_buffer_size_;
}
-std::shared_ptr<policy> configuration_impl::find_client_id_policy(client_t _client) const {
- std::lock_guard<std::mutex> its_lock(policies_mutex_);
- for (auto client_id_pair : policies_) {
- if (std::get<0>(client_id_pair.first) <= _client
- && _client <= std::get<1>(client_id_pair.first)) {
- return client_id_pair.second;
- }
- }
- return nullptr;
-}
-
-bool configuration_impl::remove_security_policy(uint32_t _uid, uint32_t _gid) {
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- bool was_removed(false);
- if (!any_client_policies_.empty()) {
- std::vector<std::shared_ptr<policy>>::iterator p_it = any_client_policies_.begin();
- while (p_it != any_client_policies_.end()) {
- bool has_uid(false), has_gid(false);
- for (auto its_credential : p_it->get()->ids_) {
- has_uid = has_gid = false;
- for (auto its_range : std::get<0>(its_credential)) {
- if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
- has_uid = true;
- break;
- }
- }
- for (auto its_range : std::get<1>(its_credential)) {
- if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
- has_gid = true;
- break;
- }
- }
- // only remove "credentials allow" policies to prevent removal of
- // blacklist configured in file
- if (has_uid && has_gid && p_it->get()->allow_who_) {
- was_removed = true;
- break;
- }
- }
- if (was_removed) {
- p_it = any_client_policies_.erase(p_it);
- break;
- } else {
- ++p_it;
- }
- }
+bool configuration_impl::tp_segment_messages_client_to_service(
+ service_t _service, std::string _ip_target, std::uint16_t _port_target,
+ method_t _method) const {
+ bool ret(false);
+ const service* const its_service = find_service_by_ip_port(_service,
+ _ip_target, _port_target);
+ if (its_service) {
+ ret = (its_service->tp_segment_messages_client_to_service_.find(_method)
+ != its_service->tp_segment_messages_client_to_service_.end());
}
- return was_removed;
-}
-
-void configuration_impl::update_security_policy(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy) {
- remove_security_policy(_uid, _gid);
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- any_client_policies_.push_back(_policy);
+ return ret;
}
-void configuration_impl::add_security_credentials(uint32_t _uid, uint32_t _gid,
- ::std::shared_ptr<policy> _credentials_policy, client_t _client) {
-
- bool was_found(false);
- std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
- for (auto its_policy : any_client_policies_) {
- bool has_uid(false), has_gid(false);
- for (auto its_credential : its_policy->ids_) {
- has_uid = has_gid = false;
- for (auto its_range : std::get<0>(its_credential)) {
- if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
- has_uid = true;
- break;
- }
- }
- for (auto its_range : std::get<1>(its_credential)) {
- if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
- has_gid = true;
- break;
- }
- }
- if (has_uid && has_gid && its_policy->allow_who_) {
- was_found = true;
- break;
- }
- }
- if (was_found) {
- break;
- }
- }
- // Do not add the new (credentials-only-policy) if a allow credentials policy with same credentials was found
- if (!was_found) {
- any_client_policies_.push_back(_credentials_policy);
- VSOMEIP_INFO << __func__ << " Added security credentials at client: 0x"
- << std::hex << _client << std::dec << " with UID: " << _uid << " GID: " << _gid;
+bool configuration_impl::tp_segment_messages_service_to_client(
+ service_t _service, std::string _ip_service,
+ std::uint16_t _port_service, method_t _method) const {
+ bool ret(false);
+ const service* const its_service = find_service_by_ip_port(_service,
+ _ip_service, _port_service);
+ if (its_service) {
+ ret = (its_service->tp_segment_messages_service_to_client_.find(_method)
+ != its_service->tp_segment_messages_service_to_client_.end());
}
+ return ret;
}
-bool configuration_impl::is_remote_client_allowed() const {
- if (!check_credentials_) {
- return true;
- }
- return allow_remote_clients_;
+#ifdef VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
+bool
+configuration_impl::has_overlay(const std::string &_name) const {
+ auto its_application = applications_.find(_name);
+ return (its_application != applications_.end()
+ && !std::get<7>(its_application->second).empty());
}
-bool configuration_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
- bool uid_allowed(false);
- {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- for (auto its_uid_range : uid_whitelist_) {
- if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
- uid_allowed = true;
- break;
- }
- }
- }
-
- if (uid_allowed) {
- std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
- for (auto its_request : _policy->services_) {
- auto its_requested_service = std::get<0>(its_request);
- bool has_service(false);
- for (auto its_service_range : service_interface_whitelist_) {
- if (std::get<0>(its_service_range) <= its_requested_service
- && its_requested_service <= std::get<1>(its_service_range)) {
- has_service = true;
- break;
- }
- }
- if (!has_service) {
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy update requesting service ID: "
- << std::hex << its_requested_service
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy update requesting service ID: "
- << std::hex << its_requested_service
- << " is not allowed! -> ignore update";
- }
- return !check_whitelist_;
- }
- }
- return true;
- } else {
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
- << " is not allowed! -> ignore update";
- }
- return !check_whitelist_;
- }
-}
+void
+configuration_impl::load_overlay(const std::string &_name) {
+ std::set<std::string> its_input;
+ std::vector<element> its_elements;
+ std::set<std::string> its_failed;
-bool configuration_impl::is_policy_removal_allowed(uint32_t _uid) const {
- std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
- for (auto its_uid_range : uid_whitelist_) {
- if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
- return true;
- }
- }
+ auto its_application = applications_.find(_name);
+ if (its_application != applications_.end()) {
+ std::string its_overlay(std::get<7>(its_application->second));
- if (!check_whitelist_) {
- VSOMEIP_INFO << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
- << " is not allowed, but will be allowed due to whitelist audit mode is active!";
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
- << " is not allowed! -> ignore removal";
- }
- return !check_whitelist_;
-}
+ its_input.insert(its_overlay);
+ read_data(its_input, its_elements, its_failed, false);
-bool configuration_impl::check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const {
- if (_client != get_id(routing_host_)) {
- return true;
- } else {
- std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
- if ( std::get<0>(routing_credentials_) == _uid
- && std::get<1>(routing_credentials_) == _gid) {
- return true;
- }
- }
+ for (const auto f : its_failed)
+ VSOMEIP_ERROR << "Reading configuration data from " << f << " failed!";
- std::string security_mode_text = "!";
- if (!check_routing_credentials_) {
- security_mode_text = " but will be allowed due to audit mode is active!";
+ is_overlay_ = true;
+ load_data(its_elements, true, true);
}
- VSOMEIP_INFO << "vSomeIP Security: Client 0x"
- << std::hex << _client << " and UID/GID=" << std::dec << _uid
- << "/" << _gid << " : Check routing credentials failed as "
- << "configured routing manager credentials "
- << "do not match with routing manager credentials"
- << security_mode_text;
-
- return !check_routing_credentials_;
}
+#endif // VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
std::uint32_t configuration_impl::get_shutdown_timeout() const {
return shutdown_timeout_;
}
} // namespace config
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/configuration/src/configuration_plugin_impl.cpp b/implementation/configuration/src/configuration_plugin_impl.cpp
new file mode 100644
index 0000000..df175f3
--- /dev/null
+++ b/implementation/configuration/src/configuration_plugin_impl.cpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/configuration_plugin_impl.hpp"
+#include "../include/configuration_impl.hpp"
+
+VSOMEIP_PLUGIN(vsomeip_v3::configuration_plugin_impl)
+
+namespace vsomeip_v3 {
+
+configuration_plugin_impl::configuration_plugin_impl()
+ : plugin_impl("vsomeip-configuration-plugin",
+ VSOMEIP_CONFIG_PLUGIN_VERSION,
+ plugin_type_e::CONFIGURATION_PLUGIN) {
+}
+
+configuration_plugin_impl::~configuration_plugin_impl() {
+}
+
+std::shared_ptr<configuration>
+configuration_plugin_impl::get_configuration(const std::string &_name) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (!default_) {
+ default_ = std::make_shared<cfg::configuration_impl>();
+ default_->load(_name);
+ }
+
+#ifdef VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
+ auto its_configuration(default_);
+ if (its_configuration->has_overlay(_name)) {
+ VSOMEIP_INFO << "Loading configuration overlay for \"" << _name << "\"";
+ auto its_iterator = configurations_.find(_name);
+ if (its_iterator != configurations_.end()) {
+ its_configuration = its_iterator->second;
+ } else {
+ its_configuration = std::make_shared<cfg::configuration_impl>(
+ *(its_configuration.get()));
+ its_configuration->load_overlay(_name);
+ configurations_[_name] = its_configuration;
+ }
+ }
+ return its_configuration;
+#else
+ return default_;
+#endif // VSOMEIP_ENABLE_CONFIGURATION_OVERLAYS
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/include/buffer/buffer.hpp b/implementation/e2e_protection/include/buffer/buffer.hpp
index 5ddcf2e..8583ede 100644
--- a/implementation/e2e_protection/include/buffer/buffer.hpp
+++ b/implementation/e2e_protection/include/buffer/buffer.hpp
@@ -3,15 +3,15 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_BUFFER_HPP
-#define VSOMEIP_E2E_BUFFER_HPP
+#ifndef VSOMEIP_V3_E2E_BUFFER_HPP
+#define VSOMEIP_V3_E2E_BUFFER_HPP
#include <stdexcept>
#include <cstdint>
#include <ostream>
#include <vector>
-namespace vsomeip {
+namespace vsomeip_v3 {
using e2e_buffer = std::vector<uint8_t>;
@@ -43,6 +43,6 @@ private:
std::ostream &operator<<(std::ostream &_os, const e2e_buffer &_buffer);
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_BUFFER_HPP
+#endif // VSOMEIP_V3_E2E_BUFFER_HPP
diff --git a/implementation/e2e_protection/include/crc/crc.hpp b/implementation/e2e_protection/include/crc/crc.hpp
index 1a54312..6120d86 100644
--- a/implementation/e2e_protection/include/crc/crc.hpp
+++ b/implementation/e2e_protection/include/crc/crc.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_CRC_HPP
-#define VSOMEIP_E2E_CRC_HPP
+#ifndef VSOMEIP_V3_E2E_CRC_HPP
+#define VSOMEIP_V3_E2E_CRC_HPP
#include <cstdint>
#include "../buffer/buffer.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class e2e_crc {
public:
@@ -27,6 +27,6 @@ class e2e_crc {
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_CRC_HPP
+#endif // VSOMEIP_V3_E2E_CRC_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/e2e_provider.hpp b/implementation/e2e_protection/include/e2e/profile/e2e_provider.hpp
new file mode 100644
index 0000000..aa45829
--- /dev/null
+++ b/implementation/e2e_protection/include/e2e/profile/e2e_provider.hpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_E2E_PROVIDER_HPP
+#define VSOMEIP_V3_E2E_PROVIDER_HPP
+
+#include <string>
+#include <memory>
+
+#include "../../buffer/buffer.hpp"
+#include "../../e2exf/config.hpp"
+#include "../../../../configuration/include/e2e.hpp"
+#include "profile_interface/profile_interface.hpp"
+
+namespace vsomeip_v3 {
+namespace e2e {
+
+class e2e_provider {
+public:
+ virtual bool add_configuration(std::shared_ptr<cfg::e2e> config) = 0;
+
+ virtual bool is_protected(e2exf::data_identifier_t id) const = 0;
+ virtual bool is_checked(e2exf::data_identifier_t id) const = 0;
+
+ virtual void protect(e2exf::data_identifier_t id, e2e_buffer &_buffer) = 0;
+ virtual void check(e2exf::data_identifier_t id, const e2e_buffer &_buffer,
+ e2e::profile_interface::check_status_t &_generic_check_status) = 0;
+};
+
+} // namespace e2e
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_E2E_PROVIDER_HPP
+
diff --git a/implementation/e2e_protection/include/e2e/profile/e2e_provider_impl.hpp b/implementation/e2e_protection/include/e2e/profile/e2e_provider_impl.hpp
new file mode 100644
index 0000000..b7d41a6
--- /dev/null
+++ b/implementation/e2e_protection/include/e2e/profile/e2e_provider_impl.hpp
@@ -0,0 +1,67 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_E2E_PROVIDER_IMPL_HPP
+#define VSOMEIP_V3_E2E_PROVIDER_IMPL_HPP
+
+#include <map>
+#include <memory>
+
+#include "e2e_provider.hpp"
+#include "profile_interface/checker.hpp"
+#include "profile_interface/protector.hpp"
+
+#include "../../../../../interface/vsomeip/export.hpp"
+#include "../../../../../interface/vsomeip/plugin.hpp"
+
+namespace vsomeip_v3 {
+namespace e2e {
+
+class e2e_provider_impl :
+ public e2e_provider,
+ public plugin_impl<e2e_provider_impl>,
+ public std::enable_shared_from_this<e2e_provider_impl> {
+public:
+ VSOMEIP_EXPORT e2e_provider_impl();
+ VSOMEIP_EXPORT ~e2e_provider_impl();
+
+ VSOMEIP_EXPORT bool add_configuration(std::shared_ptr<cfg::e2e> config) override;
+
+ VSOMEIP_EXPORT bool is_protected(e2exf::data_identifier_t id) const override;
+ VSOMEIP_EXPORT bool is_checked(e2exf::data_identifier_t id) const override;
+
+ VSOMEIP_EXPORT void protect(e2exf::data_identifier_t id, e2e_buffer &_buffer) override;
+ VSOMEIP_EXPORT void check(e2exf::data_identifier_t id, const e2e_buffer &_buffer,
+ profile_interface::check_status_t &_generic_check_status) override;
+
+private:
+ std::map<e2exf::data_identifier_t, std::shared_ptr<profile_interface::protector>> custom_protectors;
+ std::map<e2exf::data_identifier_t, std::shared_ptr<profile_interface::checker>> custom_checkers;
+
+ template<typename config_t>
+ config_t make_e2e_profile_config(const std::shared_ptr<cfg::e2e>& config);
+
+ template<typename config_t, typename checker_t, typename protector_t>
+ void process_e2e_profile(std::shared_ptr<cfg::e2e> config) {
+ const e2exf::data_identifier_t data_identifier = {config->service_id, config->event_id};
+ config_t profile_config = make_e2e_profile_config<config_t>(config);
+
+ std::shared_ptr<e2e::profile_interface::checker> checker;
+ if ((config->variant == "checker") || (config->variant == "both")) {
+ custom_checkers[data_identifier] = std::make_shared<checker_t>(profile_config);
+ }
+
+ std::shared_ptr<e2e::profile_interface::protector> protector;
+ if ((config->variant == "protector") || (config->variant == "both")) {
+ custom_protectors[data_identifier] = std::make_shared<protector_t>(profile_config);
+ }
+ }
+};
+
+} // namespace e2e
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_E2E_PROVIDER_IMPL_HPP
+
diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp
index 5fa243a..3010949 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile01/checker.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE01_CHECKER_HPP
-#define VSOMEIP_E2E_PROFILE01_CHECKER_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE01_CHECKER_HPP
+#define VSOMEIP_V3_E2E_PROFILE01_CHECKER_HPP
#include "../profile01/profile_01.hpp"
#include "../profile_interface/checker.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
@@ -23,7 +23,7 @@ class profile_01_checker final : public e2e::profile_interface::checker {
config_(_config) {}
virtual void check(const e2e_buffer &_buffer,
- e2e::profile_interface::generic_check_status &_generic_check_status) override final;
+ e2e::profile_interface::check_status_t &_generic_check_status) override final;
private:
profile_config config_;
@@ -33,6 +33,6 @@ private:
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE01_CHECKER_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE01_CHECKER_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
index 810ec56..c6cd5cf 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile01/profile_01.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE01_PROFILE01_HPP
-#define VSOMEIP_E2E_PROFILE01_PROFILE01_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE01_PROFILE01_HPP
+#define VSOMEIP_V3_E2E_PROFILE01_PROFILE01_HPP
#include <cstdint>
#include "../../../buffer/buffer.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
@@ -51,6 +51,6 @@ struct profile_config {
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE01_PROFILE01_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE01_PROFILE01_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
index 204c7a1..fe8b603 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile01/protector.hpp
@@ -3,14 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE01_PROTECTOR_HPP
-#define VSOMEIP_E2E_PROFILE01_PROTECTOR_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE01_PROTECTOR_HPP
+#define VSOMEIP_V3_E2E_PROFILE01_PROTECTOR_HPP
#include <mutex>
#include "../profile01/profile_01.hpp"
#include "../profile_interface/protector.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
@@ -41,6 +41,6 @@ class protector final : public e2e::profile_interface::protector {
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE01_PROTECTOR_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE01_PROTECTOR_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp
index 7080329..73f1bbb 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/checker.hpp
@@ -3,27 +3,28 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_CUSTOM_CHECKER_HPP
-#define VSOMEIP_E2E_PROFILE_CUSTOM_CHECKER_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_CUSTOM_CHECKER_HPP
+#define VSOMEIP_V3_E2E_PROFILE_CUSTOM_CHECKER_HPP
#include "../profile_custom/profile_custom.hpp"
#include "../profile_interface/checker.hpp"
#include <mutex>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
-class profile_custom_checker final : public vsomeip::e2e::profile_interface::checker {
+class profile_custom_checker final
+ : public e2e::profile_interface::checker {
- public:
+public:
profile_custom_checker(void) = delete;
- explicit profile_custom_checker(const vsomeip::e2e::profile_custom::profile_config &_config) :
+ explicit profile_custom_checker(const e2e::profile_custom::profile_config &_config) :
config_(_config) {}
virtual void check(const e2e_buffer &_buffer,
- vsomeip::e2e::profile_interface::generic_check_status &_generic_check_status);
+ e2e::profile_interface::check_status_t &_generic_check_status);
private:
uint32_t read_crc(const e2e_buffer &_buffer) const;
@@ -36,6 +37,6 @@ private:
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_CUSTOM_CHECKER_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_CUSTOM_CHECKER_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp
index f41942c..1cabefa 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
-#define VSOMEIP_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
+#define VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
#include <cstdint>
#include "../../../buffer/buffer.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
@@ -36,6 +36,6 @@ struct profile_config {
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROFILE_CUSTOM_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp
index 4b6c3b4..31b976b 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_custom/protector.hpp
@@ -3,18 +3,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
-#define VSOMEIP_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
+#define VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
#include <mutex>
#include "../profile_custom/profile_custom.hpp"
#include "../profile_interface/protector.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
-class protector final : public vsomeip::e2e::profile_interface::protector {
+class protector final : public e2e::profile_interface::protector {
public:
protector(void) = delete;
@@ -33,6 +33,6 @@ class protector final : public vsomeip::e2e::profile_interface::protector {
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_CUSTOM_PROTECTOR_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp
index c66d1b0..f160ea1 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/checker.hpp
@@ -3,25 +3,25 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_INTERFACE_CHECKER_HPP
-#define VSOMEIP_E2E_PROFILE_INTERFACE_CHECKER_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_INTERFACE_CHECKER_HPP
+#define VSOMEIP_V3_E2E_PROFILE_INTERFACE_CHECKER_HPP
#include "../profile_interface/profile_interface.hpp"
#include "../../../buffer/buffer.hpp"
#include <mutex>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_interface {
class checker : public profile_interface {
public:
virtual void check(const e2e_buffer &_buffer,
- vsomeip::e2e::profile_interface::generic_check_status &_generic_check_status) = 0;
+ check_status_t &_generic_check_status) = 0;
};
} // namespace profile_interface
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_INTERFACE_CHECKER_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_INTERFACE_CHECKER_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp
index 377bbee..dc72aac 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/profile_interface.hpp
@@ -3,16 +3,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
-#define VSOMEIP_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
+#define VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
#include <cstdint>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_interface {
-enum class generic_check_status : uint8_t { E2E_OK, E2E_WRONG_CRC, E2E_ERROR};
+typedef uint8_t check_status_t;
+enum generic_check_status : check_status_t { E2E_OK, E2E_WRONG_CRC, E2E_ERROR};
+
class profile_interface {
public:
@@ -22,6 +24,6 @@ public:
} // namespace profile_interface
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROFILE_INTERFACE_HPP
diff --git a/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp b/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp
index a031a9e..5bae188 100644
--- a/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp
+++ b/implementation/e2e_protection/include/e2e/profile/profile_interface/protector.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
-#define VSOMEIP_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
+#ifndef VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
+#define VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
#include "../../../buffer/buffer.hpp"
#include "../profile_interface/profile_interface.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_interface {
@@ -20,6 +20,6 @@ class protector : public profile_interface {
} // namespace profile_interface
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
+#endif // VSOMEIP_V3_E2E_PROFILE_INTERFACE_PROTECTOR_HPP
diff --git a/implementation/e2e_protection/include/e2exf/config.hpp b/implementation/e2e_protection/include/e2exf/config.hpp
index bf1fb50..a022d8c 100644
--- a/implementation/e2e_protection/include/e2exf/config.hpp
+++ b/implementation/e2e_protection/include/e2exf/config.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_E2EXF_CONFIG_HPP
-#define VSOMEIP_E2EXF_CONFIG_HPP
+#ifndef VSOMEIP_V3_E2EXF_CONFIG_HPP
+#define VSOMEIP_V3_E2EXF_CONFIG_HPP
#include <vsomeip/primitive_types.hpp>
#include "../e2e/profile/profile_interface/checker.hpp"
@@ -13,7 +13,7 @@
#include <memory>
#include <map>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2exf {
using data_identifier_t = std::pair<service_t, event_t>;
@@ -21,6 +21,6 @@ using data_identifier_t = std::pair<service_t, event_t>;
std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier_t &_data_identifier);
} // namespace e2exf
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_E2EXF_CONFIG_HPP
+#endif // VSOMEIP_V3_E2EXF_CONFIG_HPP
diff --git a/implementation/e2e_protection/src/buffer/buffer.cpp b/implementation/e2e_protection/src/buffer/buffer.cpp
index e133d42..d50310b 100644
--- a/implementation/e2e_protection/src/buffer/buffer.cpp
+++ b/implementation/e2e_protection/src/buffer/buffer.cpp
@@ -6,7 +6,7 @@
#include "../../../e2e_protection/include/buffer/buffer.hpp"
#include <iomanip>
-namespace vsomeip {
+namespace vsomeip_v3 {
std::ostream &operator<<(std::ostream &_os, const e2e_buffer &_buffer) {
for (auto b : _buffer) {
@@ -19,4 +19,4 @@ std::ostream &operator<<(std::ostream &_os, const e2e_buffer &_buffer) {
return _os;
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/crc/crc.cpp b/implementation/e2e_protection/src/crc/crc.cpp
index d9f1f99..335b48d 100644
--- a/implementation/e2e_protection/src/crc/crc.cpp
+++ b/implementation/e2e_protection/src/crc/crc.cpp
@@ -8,7 +8,7 @@
#include <string>
#include <iomanip>
-namespace vsomeip {
+namespace vsomeip_v3 {
/**
* Calculates the crc over the provided range.
@@ -178,5 +178,5 @@ const uint32_t e2e_crc::lookup_table_profile_custom_[256] = {
0xB3667A2EU, 0xC4614AB8U, 0x5D681B02U, 0x2A6F2B94U, 0xB40BBE37U, 0xC30C8EA1U, 0x5A05DF1BU, 0x2D02EF8DU
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/e2e_provider_impl.cpp b/implementation/e2e_protection/src/e2e/profile/e2e_provider_impl.cpp
new file mode 100644
index 0000000..7a82446
--- /dev/null
+++ b/implementation/e2e_protection/src/e2e/profile/e2e_provider_impl.cpp
@@ -0,0 +1,122 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../../../../e2e_protection/include/e2e/profile/e2e_provider_impl.hpp"
+
+#include "../../../../e2e_protection/include/e2e/profile/profile01/checker.hpp"
+#include "../../../../e2e_protection/include/e2e/profile/profile01/profile_01.hpp"
+#include "../../../../e2e_protection/include/e2e/profile/profile01/protector.hpp"
+
+#include "../../../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp"
+#include "../../../../e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp"
+#include "../../../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp"
+
+#include <sstream>
+
+namespace {
+
+template<typename value_t>
+value_t read_value_from_config(const std::shared_ptr<vsomeip_v3::cfg::e2e>& config,
+ const std::string& name,
+ value_t default_value = value_t()) {
+ if(config && config->custom_parameters.count(name)) {
+ value_t value;
+ std::stringstream its_converter;
+ its_converter << config->custom_parameters[name];
+ its_converter >> value;
+ return value;
+ }
+
+ return default_value;
+}
+
+} // namespace
+
+
+VSOMEIP_PLUGIN(vsomeip_v3::e2e::e2e_provider_impl)
+
+namespace vsomeip_v3 {
+namespace e2e {
+
+e2e_provider_impl::e2e_provider_impl()
+ : plugin_impl("vsomeip e2e plugin", 1, plugin_type_e::APPLICATION_PLUGIN)
+{
+}
+
+e2e_provider_impl::~e2e_provider_impl()
+{
+}
+
+bool e2e_provider_impl::add_configuration(std::shared_ptr<cfg::e2e> config)
+{
+ if(config->profile == "CRC8") {
+ process_e2e_profile<profile01::profile_config, profile01::profile_01_checker, profile01::protector>(config);
+ return true;
+ }
+
+ if(config->profile == "CRC32") {
+ process_e2e_profile<profile_custom::profile_config, profile_custom::profile_custom_checker, profile_custom::protector>(config);
+ return true;
+ }
+
+ return false;
+}
+
+bool e2e_provider_impl::is_protected(e2exf::data_identifier_t id) const
+{
+ return custom_protectors.count(id) > 0;
+}
+
+bool e2e_provider_impl::is_checked(e2exf::data_identifier_t id) const
+{
+ return custom_checkers.count(id) > 0;
+}
+
+void e2e_provider_impl::protect(e2exf::data_identifier_t id, e2e_buffer &_buffer)
+{
+ auto protector = custom_protectors.find(id);
+ if(protector != custom_protectors.end()) {
+ protector->second->protect(_buffer);
+ }
+}
+
+void e2e_provider_impl::check(e2exf::data_identifier_t id, const e2e_buffer &_buffer,
+ profile_interface::check_status_t &_generic_check_status)
+{
+ auto checker = custom_checkers.find(id);
+ if(checker != custom_checkers.end()) {
+ checker->second->check(_buffer, _generic_check_status);
+ }
+}
+
+template<>
+vsomeip_v3::e2e::profile01::profile_config
+e2e_provider_impl::make_e2e_profile_config(const std::shared_ptr<cfg::e2e>& config) {
+ uint16_t crc_offset = read_value_from_config<uint16_t>(config, "crc_offset");
+ uint16_t data_length = read_value_from_config<uint16_t>(config, "data_length");
+
+ // counter field behind CRC8
+ uint16_t counter_offset = read_value_from_config<uint16_t>(config, "counter_offset", 8);
+
+ // data id nibble behind 4 bit counter value
+ uint16_t data_id_nibble_offset = read_value_from_config<uint16_t>(config, "data_id_nibble_offset", 12);
+
+ e2e::profile01::p01_data_id_mode data_id_mode =
+ static_cast<e2e::profile01::p01_data_id_mode>(
+ read_value_from_config<uint16_t>(config, "data_id_mode"));
+
+ return e2e::profile01::profile_config(crc_offset, config->data_id, data_id_mode,
+ data_length, counter_offset, data_id_nibble_offset);
+}
+
+template<>
+e2e::profile_custom::profile_config
+e2e_provider_impl::make_e2e_profile_config(const std::shared_ptr<cfg::e2e>& config) {
+ uint16_t crc_offset = read_value_from_config<uint16_t>(config, "crc_offset");
+ return e2e::profile_custom::profile_config(crc_offset);
+}
+
+} // namespace e2e
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp
index e4c0504..bea8dc1 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile01/checker.cpp
@@ -4,20 +4,20 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../../../../../e2e_protection/include/e2e/profile/profile01/checker.hpp"
-#include "../../../../../logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <algorithm>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
// [SWS_E2E_00196]
void profile_01_checker::check(const e2e_buffer &_buffer,
- e2e::profile_interface::generic_check_status &_generic_check_status) {
+ e2e::profile_interface::check_status_t &_generic_check_status) {
std::lock_guard<std::mutex> lock(check_mutex_);
_generic_check_status = e2e::profile_interface::generic_check_status::E2E_ERROR;
@@ -39,4 +39,4 @@ void profile_01_checker::check(const e2e_buffer &_buffer,
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
index 72bd14c..358dd4e 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile01/profile_01.cpp
@@ -10,7 +10,7 @@
#include <string>
#include <iomanip>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
@@ -88,7 +88,7 @@ uint8_t profile_01::compute_crc(const profile_config &_config, const e2e_buffer
// Compute the area after CRC, if CRC is not the last byte. Start with the byte after CRC, finish with the last byte of Data.
if ((_config.crc_offset_) < (_config.data_length_ / 8) - 1) {
// CRC = Crc_CalculateCRC8 (& Data[Config->CRCOffset/8 + 1], (Config->DataLength / 8 - Config->CRCOffset / 8 - 1), CRC, FALSE)
- computed_crc = e2e_crc::calculate_profile_01(buffer_view(_buffer, _config.crc_offset_ + 1, _buffer.size()), computed_crc);
+ computed_crc = e2e_crc::calculate_profile_01(buffer_view(_buffer, static_cast<size_t>(_config.crc_offset_ + 1), _buffer.size()), computed_crc);
}
// CRC = CRC ^ 0xFF
@@ -107,4 +107,4 @@ bool profile_01::is_buffer_length_valid(const profile_config &_config, const e2e
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
index 0bf0199..551a801 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile01/protector.cpp
@@ -4,14 +4,14 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../../../../../e2e_protection/include/e2e/profile/profile01/protector.hpp"
-#include "../../../../../logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile01 {
@@ -76,4 +76,4 @@ void protector::increment_counter(void) {
} // namespace profile01
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp
index eb6f557..42e1ca8 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/checker.cpp
@@ -4,19 +4,19 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../../../../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp"
-#include "../../../../../logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <algorithm>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
void profile_custom_checker::check(const e2e_buffer &_buffer,
- e2e::profile_interface::generic_check_status &_generic_check_status) {
+ e2e::profile_interface::check_status_t &_generic_check_status) {
std::lock_guard<std::mutex> lock(check_mutex_);
_generic_check_status = e2e::profile_interface::generic_check_status::E2E_ERROR;
@@ -46,4 +46,4 @@ uint32_t profile_custom_checker::read_crc(const e2e_buffer &_buffer) const {
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp
index d7de34b..5ab53ca 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/profile_custom.cpp
@@ -10,12 +10,12 @@
#include <string>
#include <iomanip>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
uint32_t profile_custom::compute_crc(const profile_config &_config, const e2e_buffer &_buffer) {
- uint32_t computed_crc = e2e_crc::calculate_profile_custom(buffer_view(_buffer, _config.crc_offset_ + 4, _buffer.size()));
+ uint32_t computed_crc = e2e_crc::calculate_profile_custom(buffer_view(_buffer, static_cast<size_t>(_config.crc_offset_ + 4), _buffer.size()));
return computed_crc;
}
@@ -25,4 +25,4 @@ bool profile_custom::is_buffer_length_valid(const profile_config &_config, const
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp b/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp
index f061e55..276c02b 100644
--- a/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp
+++ b/implementation/e2e_protection/src/e2e/profile/profile_custom/protector.cpp
@@ -4,7 +4,6 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../../../../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp"
-#include "../../../../../logging/include/logger.hpp"
#include <iostream>
#include <sstream>
@@ -13,7 +12,7 @@
#include <iostream>
#include <sstream>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace e2e {
namespace profile_custom {
@@ -37,4 +36,4 @@ void protector::write_crc(e2e_buffer &_buffer, uint32_t _computed_crc) {
} // namespace profile_custom
} // namespace e2e
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/e2e_protection/src/e2exf/config.cpp b/implementation/e2e_protection/src/e2exf/config.cpp
index c7df18a..20a3b71 100644
--- a/implementation/e2e_protection/src/e2exf/config.cpp
+++ b/implementation/e2e_protection/src/e2exf/config.cpp
@@ -6,11 +6,11 @@
#include <ostream>
#include "../../../e2e_protection/include/e2exf/config.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
std::ostream &operator<<(std::ostream &_os, const e2exf::data_identifier_t &_data_identifier) {
_os << _data_identifier.first << _data_identifier.second;
return _os;
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/include/buffer.hpp b/implementation/endpoints/include/buffer.hpp
index c384f0d..af0582d 100644
--- a/implementation/endpoints/include/buffer.hpp
+++ b/implementation/endpoints/include/buffer.hpp
@@ -3,20 +3,62 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_BUFFER_HPP
-#define VSOMEIP_BUFFER_HPP
+#ifndef VSOMEIP_V3_BUFFER_HPP_
+#define VSOMEIP_V3_BUFFER_HPP_
#include <array>
+#include <chrono>
#include <memory>
+#include <set>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/steady_timer.hpp>
#include <vsomeip/defines.hpp>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+#ifdef _WIN32
+ #define DEFAULT_NANOSECONDS_MAX 1000000000
+#else
+ #define DEFAULT_NANOSECONDS_MAX std::chrono::nanoseconds::max()
+#endif
+
+namespace vsomeip_v3 {
typedef std::vector<byte_t> message_buffer_t;
typedef std::shared_ptr<message_buffer_t> message_buffer_ptr_t;
-} // namespace vsomeip
+struct timing {
+ timing() : debouncing_(0), maximum_retention_(DEFAULT_NANOSECONDS_MAX) {};
+
+ std::chrono::nanoseconds debouncing_;
+ std::chrono::nanoseconds maximum_retention_;
+};
+
+struct train {
+ train(boost::asio::io_service& _io) : buffer_(std::make_shared<message_buffer_t>()),
+ departure_(DEFAULT_NANOSECONDS_MAX),
+ minimal_debounce_time_(DEFAULT_NANOSECONDS_MAX),
+ minimal_max_retention_time_(DEFAULT_NANOSECONDS_MAX),
+ last_departure_(std::chrono::steady_clock::now() - std::chrono::hours(1)),
+ departure_timer_(std::make_shared<boost::asio::steady_timer>(_io)) {};
+
+ message_buffer_ptr_t buffer_;
+ std::chrono::nanoseconds departure_;
+ std::chrono::nanoseconds minimal_debounce_time_;
+ std::chrono::nanoseconds minimal_max_retention_time_;
+ std::chrono::steady_clock::time_point last_departure_;
+ std::shared_ptr<boost::asio::steady_timer> departure_timer_;
+ std::set<std::pair<service_t, method_t> > passengers_;
+
+ void update_departure_time_and_stop_departure() {
+ departure_ = departure_timer_->expires_from_now();
+ boost::system::error_code ec;
+ departure_timer_->cancel(ec);
+ }
+};
+
+
+} // namespace vsomeip_v3
-#endif // VSOMEIP_BUFFER_HPP
+#endif // VSOMEIP_V3_BUFFER_HPP_
diff --git a/implementation/endpoints/include/client_endpoint.hpp b/implementation/endpoints/include/client_endpoint.hpp
index 4dc828a..ce872e8 100644
--- a/implementation/endpoints/include/client_endpoint.hpp
+++ b/implementation/endpoints/include/client_endpoint.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CLIENT_ENDPOINT_HPP_
-#define VSOMEIP_CLIENT_ENDPOINT_HPP_
+#ifndef VSOMEIP_V3_CLIENT_ENDPOINT_HPP_
+#define VSOMEIP_V3_CLIENT_ENDPOINT_HPP_
#include "endpoint.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class client_endpoint : public virtual endpoint {
public:
@@ -21,4 +21,4 @@ public:
} // namespace vsomeip
-#endif /* VSOMEIP_CLIENT_ENDPOINT_HPP_ */
+#endif // VSOMEIP_V3_CLIENT_ENDPOINT_HPP_
diff --git a/implementation/endpoints/include/client_endpoint_impl.hpp b/implementation/endpoints/include/client_endpoint_impl.hpp
index 409bba0..4411a50 100644
--- a/implementation/endpoints/include/client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/client_endpoint_impl.hpp
@@ -1,128 +1,149 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP
-#define VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP
-
-#include <condition_variable>
-#include <deque>
-#include <mutex>
-#include <vector>
-#include <atomic>
-
-#include <boost/array.hpp>
-#include <boost/asio/io_service.hpp>
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
+
+#include <condition_variable>
+#include <deque>
+#include <mutex>
+#include <vector>
+#include <atomic>
+#include <chrono>
+
+#include <boost/array.hpp>
+#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
-#include <boost/asio/ip/udp.hpp>
-#include <boost/utility.hpp>
-#include <vsomeip/constants.hpp>
-
-#include "buffer.hpp"
-#include "endpoint_impl.hpp"
-#include "client_endpoint.hpp"
-
-namespace vsomeip {
-
-class endpoint;
-class endpoint_host;
-
-template<typename Protocol>
-class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint,
- public std::enable_shared_from_this<client_endpoint_impl<Protocol> > {
-public:
- typedef typename Protocol::endpoint endpoint_type;
- typedef typename Protocol::socket socket_type;
-
- client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local, endpoint_type _remote,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit);
- virtual ~client_endpoint_impl();
-
- bool send(const uint8_t *_data, uint32_t _size, bool _flush);
- bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush = true);
- bool send_to(const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush = true);
- bool flush();
-
- virtual void stop();
- virtual void restart(bool _force = false) = 0;
-
- bool is_client() const;
-
- bool is_established() const;
- void set_established(bool _established);
- void set_connected(bool _connected);
- virtual bool get_remote_address(boost::asio::ip::address &_address) const;
- virtual std::uint16_t get_remote_port() const;
-
- std::uint16_t get_local_port() const;
-
-public:
- void connect_cbk(boost::system::error_code const &_error);
- void wait_connect_cbk(boost::system::error_code const &_error);
- virtual void send_cbk(boost::system::error_code const &_error,
- std::size_t _bytes, message_buffer_ptr_t _sent_msg);
- void flush_cbk(boost::system::error_code const &_error);
-
-public:
- virtual void connect() = 0;
- virtual void receive() = 0;
- virtual void print_status() = 0;
-
-protected:
- enum class cei_state_e : std::uint8_t {
- CLOSED,
- CONNECTING,
- CONNECTED,
- ESTABLISHED
- };
- virtual void send_queued() = 0;
- void shutdown_and_close_socket(bool _recreate_socket);
- void shutdown_and_close_socket_unlocked(bool _recreate_socket);
- void start_connect_timer();
-
- bool check_message_size(std::uint32_t _size) const;
- bool check_packetizer_space(std::uint32_t _size);
- bool check_queue_limit(const uint8_t *_data, std::uint32_t _size) const;
- void send_or_start_flush_timer(bool _flush, bool _queue_size_zero_on_entry);
-
- mutable std::mutex socket_mutex_;
- std::unique_ptr<socket_type> socket_;
- endpoint_type remote_;
-
- boost::asio::steady_timer flush_timer_;
-
- std::mutex connect_timer_mutex_;
- boost::asio::steady_timer connect_timer_;
- std::atomic<uint32_t> connect_timeout_;
- std::atomic<cei_state_e> state_;
- std::atomic<std::uint32_t> reconnect_counter_;
-
- // send data
- message_buffer_ptr_t packetizer_;
- std::deque<message_buffer_ptr_t> queue_;
- std::size_t queue_size_;
-
- std::mutex mutex_;
-
- std::atomic<bool> was_not_connected_;
-
- std::atomic<std::uint16_t> local_port_;
-
+#include <boost/asio/ip/udp.hpp>
+#include <boost/utility.hpp>
+#include <vsomeip/constants.hpp>
+
+#include "buffer.hpp"
+#include "endpoint_impl.hpp"
+#include "client_endpoint.hpp"
+#include "tp.hpp"
+
+
+namespace vsomeip_v3 {
+
+class endpoint;
+class endpoint_host;
+
+template<typename Protocol>
+class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint,
+ public std::enable_shared_from_this<client_endpoint_impl<Protocol> > {
+public:
+ typedef typename Protocol::endpoint endpoint_type;
+ typedef typename Protocol::socket socket_type;
+
+ client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local, const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~client_endpoint_impl();
+
+ bool send(const uint8_t *_data, uint32_t _size);
+ bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
+ uint32_t _size);
+ bool send_to(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ bool flush();
+
+ void prepare_stop(endpoint::prepare_stop_handler_t _handler, service_t _service);
+ virtual void stop();
+ virtual void restart(bool _force = false) = 0;
+
+ bool is_client() const;
+
+ bool is_established() const;
+ bool is_established_or_connected() const;
+ void set_established(bool _established);
+ void set_connected(bool _connected);
+ virtual bool get_remote_address(boost::asio::ip::address &_address) const;
+ virtual std::uint16_t get_remote_port() const;
+
+ std::uint16_t get_local_port() const;
+ virtual bool is_reliable() const = 0;
+
+ size_t get_queue_size() const;
+
+public:
+ void connect_cbk(boost::system::error_code const &_error);
+ void wait_connect_cbk(boost::system::error_code const &_error);
+ virtual void send_cbk(boost::system::error_code const &_error,
+ std::size_t _bytes, const message_buffer_ptr_t& _sent_msg);
+ void flush_cbk(boost::system::error_code const &_error);
+
+public:
+ virtual void connect() = 0;
+ virtual void receive() = 0;
+ virtual void print_status() = 0;
+
+protected:
+ enum class cei_state_e : std::uint8_t {
+ CLOSED,
+ CONNECTING,
+ CONNECTED,
+ ESTABLISHED
+ };
+ virtual void send_queued() = 0;
+ virtual void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const = 0;
+ void shutdown_and_close_socket(bool _recreate_socket);
+ void shutdown_and_close_socket_unlocked(bool _recreate_socket);
+ void start_connect_timer();
+ typename endpoint_impl<Protocol>::cms_ret_e check_message_size(
+ const std::uint8_t * const _data, std::uint32_t _size);
+ bool check_queue_limit(const uint8_t *_data, std::uint32_t _size) const;
+ void queue_train(bool _queue_size_zero_on_entry);
+
+protected:
+ mutable std::mutex socket_mutex_;
+ std::unique_ptr<socket_type> socket_;
+ const endpoint_type remote_;
+
+ boost::asio::steady_timer flush_timer_;
+
+ std::mutex connect_timer_mutex_;
+ boost::asio::steady_timer connect_timer_;
+ std::atomic<uint32_t> connect_timeout_;
+ std::atomic<cei_state_e> state_;
+ std::atomic<std::uint32_t> reconnect_counter_;
+
+ // send data
+ train train_;
+
+ std::deque<message_buffer_ptr_t> queue_;
+ std::size_t queue_size_;
+
+ mutable std::mutex mutex_;
+
+ std::atomic<bool> was_not_connected_;
+
+ std::atomic<std::uint16_t> local_port_;
+
boost::asio::io_service::strand strand_;
-private:
- virtual void set_local_port() = 0;
- virtual std::string get_remote_information() const = 0;
- virtual std::uint32_t get_max_allowed_reconnects() const = 0;
- virtual void max_allowed_reconnects_reached() = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_CLIENT_ENDPOINT_IMPL_HPP
+private:
+ virtual void set_local_port() = 0;
+ virtual std::string get_remote_information() const = 0;
+ virtual bool tp_segmentation_enabled(service_t _service,
+ method_t _method) const = 0;
+ virtual std::uint32_t get_max_allowed_reconnects() const = 0;
+ virtual void max_allowed_reconnects_reached() = 0;
+ void send_segments(const tp::tp_split_messages_t &_segments);
+ void wait_until_debounce_time_reached() const;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/credentials.hpp b/implementation/endpoints/include/credentials.hpp
index 63c3470..2fe9060 100644
--- a/implementation/endpoints/include/credentials.hpp
+++ b/implementation/endpoints/include/credentials.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
-#define ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
+#ifndef VSOMEIP_V3_ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
+#define VSOMEIP_V3_ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class credentials {
public:
@@ -21,6 +21,6 @@ public:
static void send_credentials(const int _fd, client_t _client);
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif /* ENDPOINTS_INCLUDE_CREDENTIALS_HPP_ */
+#endif // VSOMEIP_V3_ENDPOINTS_INCLUDE_CREDENTIALS_HPP_
diff --git a/implementation/endpoints/include/endpoint.hpp b/implementation/endpoints/include/endpoint.hpp
index b1204f0..452f92b 100644
--- a/implementation/endpoints/include/endpoint.hpp
+++ b/implementation/endpoints/include/endpoint.hpp
@@ -1,65 +1,70 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_ENDPOINT_HPP
-#define VSOMEIP_ENDPOINT_HPP
-
-#include <boost/asio/ip/address.hpp>
-
-#include <vsomeip/primitive_types.hpp>
-
-#include <vector>
-
-namespace vsomeip {
-
-class endpoint_definition;
-
-class endpoint {
-public:
- typedef std::function<void()> error_handler_t;
-
- virtual ~endpoint() {}
-
- virtual void start() = 0;
- virtual void stop() = 0;
-
- virtual bool is_established() const = 0;
-
- virtual bool send(const byte_t *_data, uint32_t _size,
- bool _flush = true) = 0;
- virtual bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush = true) = 0;
- virtual bool send_to(const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush = true) = 0;
- virtual void enable_magic_cookies() = 0;
- virtual void receive() = 0;
-
- virtual void join(const std::string &_address) = 0;
- virtual void leave(const std::string &_address) = 0;
-
- virtual void add_default_target(service_t _service,
- const std::string &_address, uint16_t _port) = 0;
- virtual void remove_default_target(service_t _service) = 0;
-
- virtual std::uint16_t get_local_port() const = 0;
- virtual bool is_reliable() const = 0;
- virtual bool is_local() const = 0;
-
- virtual void increment_use_count() = 0;
- virtual void decrement_use_count() = 0;
- virtual uint32_t get_use_count() = 0;
-
- virtual void restart(bool _force = false) = 0;
-
- virtual void register_error_handler(error_handler_t _error) = 0;
-
- virtual void print_status() = 0;
-
- virtual void set_established(bool _established) = 0; virtual void set_connected(bool _connected) = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_ENDPOINT_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ENDPOINT_HPP_
+#define VSOMEIP_V3_ENDPOINT_HPP_
+
+#include <boost/asio/ip/address.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/constants.hpp>
+
+#include <vector>
+
+namespace vsomeip_v3 {
+
+class endpoint_definition;
+
+class endpoint {
+public:
+ typedef std::function<void()> error_handler_t;
+ typedef std::function<void(const std::shared_ptr<endpoint>&, service_t)> prepare_stop_handler_t;
+
+ virtual ~endpoint() {}
+
+ virtual void start() = 0;
+ virtual void prepare_stop(prepare_stop_handler_t _handler,
+ service_t _service = ANY_SERVICE) = 0;
+ virtual void stop() = 0;
+
+ virtual bool is_established() const = 0;
+ virtual bool is_established_or_connected() const = 0;
+
+ virtual bool send(const byte_t *_data, uint32_t _size) = 0;
+ virtual bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
+ uint32_t _size) = 0;
+ virtual bool send_to(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) = 0;
+ virtual bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) = 0;
+ virtual void enable_magic_cookies() = 0;
+ virtual void receive() = 0;
+
+ virtual void add_default_target(service_t _service,
+ const std::string &_address, uint16_t _port) = 0;
+ virtual void remove_default_target(service_t _service) = 0;
+
+ virtual std::uint16_t get_local_port() const = 0;
+ virtual bool is_reliable() const = 0;
+ virtual bool is_local() const = 0;
+
+ virtual void increment_use_count() = 0;
+ virtual void decrement_use_count() = 0;
+ virtual uint32_t get_use_count() = 0;
+
+ virtual void restart(bool _force = false) = 0;
+
+ virtual void register_error_handler(error_handler_t _error) = 0;
+
+ virtual void print_status() = 0;
+ virtual size_t get_queue_size() const = 0;
+
+ virtual void set_established(bool _established) = 0;
+ virtual void set_connected(bool _connected) = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ENDPOINT_HPP_
diff --git a/implementation/endpoints/include/endpoint_definition.hpp b/implementation/endpoints/include/endpoint_definition.hpp
index 860d2d2..5a7e9eb 100644
--- a/implementation/endpoints/include/endpoint_definition.hpp
+++ b/implementation/endpoints/include/endpoint_definition.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ENDPOINT_DEFINITION_HPP
-#define VSOMEIP_ENDPOINT_DEFINITION_HPP
+#ifndef VSOMEIP_V3_ENDPOINT_DEFINITION_HPP_
+#define VSOMEIP_V3_ENDPOINT_DEFINITION_HPP_
#include <map>
#include <memory>
@@ -16,7 +16,7 @@
#include <vsomeip/export.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint_definition {
public:
@@ -48,6 +48,6 @@ private:
std::shared_ptr<endpoint_definition> > definitions_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ENDPOINT_DEFINITION_HPP
+#endif // VSOMEIP_V3_ENDPOINT_DEFINITION_HPP_
diff --git a/implementation/endpoints/include/endpoint_host.hpp b/implementation/endpoints/include/endpoint_host.hpp
index ddbb7e8..61c012c 100644
--- a/implementation/endpoints/include/endpoint_host.hpp
+++ b/implementation/endpoints/include/endpoint_host.hpp
@@ -3,45 +3,40 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ENDPOINT_HOST_HPP
-#define VSOMEIP_ENDPOINT_HOST_HPP
+#ifndef VSOMEIP_V3_ENDPOINT_HOST_HPP_
+#define VSOMEIP_V3_ENDPOINT_HOST_HPP_
#include <memory>
#include <boost/asio/ip/address.hpp>
-#include "../../configuration/include/internal.hpp"
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif
+
+namespace vsomeip_v3 {
class configuration;
class endpoint;
class endpoint_host {
public:
- virtual ~endpoint_host() {}
+ virtual ~endpoint_host() = default;
- virtual const std::shared_ptr<configuration> get_configuration() const = 0;
virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0;
- virtual void on_message(const byte_t *_data, length_t _length,
- endpoint *_receiver, const boost::asio::ip::address &_destination
- = boost::asio::ip::address(),
- client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- const boost::asio::ip::address &_remote_address = boost::asio::ip::address(),
- std::uint16_t _remote_port = 0) = 0;
virtual void on_error(const byte_t *_data, length_t _length,
- endpoint *_receiver,
+ endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) = 0;
virtual void release_port(uint16_t _port, bool _reliable) = 0;
virtual client_t get_client() const = 0;
-#ifndef _WIN32
- virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid) = 0;
-#endif
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ENDPOINT_HOST_HPP
+#endif // VSOMEIP_V3_ENDPOINT_HOST_HPP_
diff --git a/implementation/endpoints/include/endpoint_impl.hpp b/implementation/endpoints/include/endpoint_impl.hpp
index 05a6964..953201c 100644
--- a/implementation/endpoints/include/endpoint_impl.hpp
+++ b/implementation/endpoints/include/endpoint_impl.hpp
@@ -1,98 +1,107 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_ENDPOINT_IMPL_HPP
-#define VSOMEIP_ENDPOINT_IMPL_HPP
-
-#include <map>
-#include <memory>
-#include <mutex>
-#include <atomic>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/steady_timer.hpp>
-
-#include "buffer.hpp"
-#include "endpoint.hpp"
-#include "../../configuration/include/configuration.hpp"
-
-namespace vsomeip {
-
-class endpoint_host;
-
-template<typename Protocol>
-class endpoint_impl: public virtual endpoint {
-public:
- typedef typename Protocol::endpoint endpoint_type;
-
- endpoint_impl(std::shared_ptr<endpoint_host> _adapter,
- endpoint_type _local,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit);
- virtual ~endpoint_impl();
-
- void enable_magic_cookies();
-
- // Dummy implementations as we only need these for UDP (servers)
- // TODO: redesign
- void join(const std::string &);
- void leave(const std::string &);
-
- void add_default_target(service_t, const std::string &, uint16_t);
- void remove_default_target(service_t);
-
- // Dummy implementations as we only need these for server endpoints
- // TODO: redesign
- std::uint16_t get_local_port() const;
- bool is_reliable() const;
-
- void increment_use_count();
- void decrement_use_count();
- uint32_t get_use_count();
-
- void register_error_handler(error_handler_t _error_handler);
- virtual void print_status() = 0;
-
-public:
- // required
- virtual bool is_client() const = 0;
- virtual void receive() = 0;
- virtual void restart(bool _force) = 0;
-
-protected:
- uint32_t find_magic_cookie(byte_t *_buffer, size_t _size);
-
-protected:
- // Reference to service context
- boost::asio::io_service &service_;
-
- // Reference to host
- std::weak_ptr<endpoint_host> host_;
-
- bool is_supporting_magic_cookies_;
- std::atomic<bool> has_enabled_magic_cookies_;
-
- // Filter configuration
- std::map<service_t, uint8_t> opened_;
-
- std::uint32_t max_message_size_;
-
- uint32_t use_count_;
-
- std::atomic<bool> sending_blocked_;
-
- std::mutex local_mutex_;
- endpoint_type local_;
-
- error_handler_t error_handler_;
- std::mutex error_handler_mutex_;
-
- const configuration::endpoint_queue_limit_t queue_limit_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_ENDPOINT_IMPL_HPP_
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <atomic>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/steady_timer.hpp>
+
+#include "buffer.hpp"
+#include "endpoint.hpp"
+#include "../../configuration/include/configuration.hpp"
+
+namespace vsomeip_v3 {
+
+class endpoint_host;
+class routing_host;
+
+template<typename Protocol>
+class endpoint_impl: public virtual endpoint {
+public:
+ typedef typename Protocol::endpoint endpoint_type;
+
+ endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~endpoint_impl();
+
+ void enable_magic_cookies();
+
+ void add_default_target(service_t, const std::string &, uint16_t);
+ void remove_default_target(service_t);
+
+ virtual std::uint16_t get_local_port() const = 0;
+ virtual bool is_reliable() const = 0;
+
+ void increment_use_count();
+ void decrement_use_count();
+ uint32_t get_use_count();
+
+ void register_error_handler(error_handler_t _error_handler);
+ virtual void print_status() = 0;
+
+ virtual size_t get_queue_size() const = 0;
+
+public:
+ // required
+ virtual bool is_client() const = 0;
+ virtual void receive() = 0;
+ virtual void restart(bool _force) = 0;
+
+protected:
+ uint32_t find_magic_cookie(byte_t *_buffer, size_t _size);
+
+protected:
+ enum class cms_ret_e : uint8_t {
+ MSG_TOO_BIG,
+ MSG_OK,
+ MSG_WAS_SPLIT
+ };
+
+ // Reference to service context
+ boost::asio::io_service &service_;
+
+ // References to hosts
+ std::weak_ptr<endpoint_host> endpoint_host_;
+ std::weak_ptr<routing_host> routing_host_;
+
+ bool is_supporting_magic_cookies_;
+ std::atomic<bool> has_enabled_magic_cookies_;
+
+ // Filter configuration
+ std::map<service_t, uint8_t> opened_;
+
+ std::uint32_t max_message_size_;
+
+ std::atomic<uint32_t> use_count_;
+
+ std::atomic<bool> sending_blocked_;
+
+ std::mutex local_mutex_;
+ endpoint_type local_;
+
+ error_handler_t error_handler_;
+ std::mutex error_handler_mutex_;
+
+ const configuration::endpoint_queue_limit_t queue_limit_;
+
+ std::shared_ptr<configuration> configuration_;
+
+ bool is_supporting_someip_tp_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/endpoint_manager_base.hpp b/implementation/endpoints/include/endpoint_manager_base.hpp
new file mode 100644
index 0000000..2a766f9
--- /dev/null
+++ b/implementation/endpoints/include/endpoint_manager_base.hpp
@@ -0,0 +1,82 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ENDPOINT_MANAGER_BASE_HPP_
+#define VSOMEIP_V3_ENDPOINT_MANAGER_BASE_HPP_
+
+#include <mutex>
+#include <map>
+#include <set>
+#include <unordered_set>
+#include <memory>
+
+#include <boost/asio/io_service.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "endpoint.hpp"
+#include "endpoint_host.hpp"
+
+namespace vsomeip_v3 {
+
+class routing_manager_base;
+class configuration;
+class local_server_endpoint_impl;
+class routing_host;
+
+class endpoint_manager_base
+ : public std::enable_shared_from_this<endpoint_manager_base>,
+ public endpoint_host {
+public:
+ endpoint_manager_base(routing_manager_base* const _rm,
+ boost::asio::io_service& _io,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~endpoint_manager_base() = default;
+
+ std::shared_ptr<endpoint> create_local(client_t _client);
+ void remove_local(client_t _client);
+
+ std::shared_ptr<endpoint> find_or_create_local(client_t _client);
+ std::shared_ptr<endpoint> find_local(client_t _client);
+ std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance);
+
+ std::unordered_set<client_t> get_connected_clients() const;
+
+ std::shared_ptr<local_server_endpoint_impl> create_local_server(
+ const std::shared_ptr<routing_host> &_routing_host);
+
+ // endpoint_host interface
+ virtual void on_connect(std::shared_ptr<endpoint> _endpoint);
+ virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+ virtual void on_error(const byte_t *_data, length_t _length,
+ endpoint* const _receiver,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port);
+ virtual void release_port(uint16_t _port, bool _reliable);
+ client_t get_client() const;
+
+ // Statistics
+ void log_client_states() const;
+
+protected:
+ std::map<client_t, std::shared_ptr<endpoint>> get_local_endpoints() const;
+
+private:
+ std::shared_ptr<endpoint> create_local_unlocked(client_t _client);
+ std::shared_ptr<endpoint> find_local_unlocked(client_t _client);
+
+protected:
+ routing_manager_base* const rm_;
+ boost::asio::io_service& io_;
+ std::shared_ptr<configuration> configuration_;
+
+private:
+ mutable std::mutex local_endpoint_mutex_;
+ std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ENDPOINT_MANAGER_BASE_HPP_
diff --git a/implementation/endpoints/include/endpoint_manager_impl.hpp b/implementation/endpoints/include/endpoint_manager_impl.hpp
new file mode 100644
index 0000000..3f61b7a
--- /dev/null
+++ b/implementation/endpoints/include/endpoint_manager_impl.hpp
@@ -0,0 +1,133 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ENDPOINT_MANAGER_IMPL_HPP_
+#define VSOMEIP_V3_ENDPOINT_MANAGER_IMPL_HPP_
+
+#include "../include/endpoint_manager_base.hpp"
+
+namespace vsomeip_v3 {
+
+class routing_host;
+
+class endpoint_manager_impl : public endpoint_manager_base {
+public:
+ endpoint_manager_impl(routing_manager_base* const _rm,
+ boost::asio::io_service& _io,
+ const std::shared_ptr<configuration>& _configuration);
+ ~endpoint_manager_impl() = default;
+
+ std::shared_ptr<endpoint> find_or_create_remote_client(service_t _service,
+ instance_t _instance,
+ bool _reliable,
+ client_t _client);
+
+ void find_or_create_remote_client(service_t _service, instance_t _instance,
+ client_t _client);
+ void is_remote_service_known(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor,
+ const boost::asio::ip::address &_reliable_address,
+ uint16_t _reliable_port, bool* _reliable_known,
+ const boost::asio::ip::address &_unreliable_address,
+ uint16_t _unreliable_port, bool* _unreliable_known) const;
+ void add_remote_service_info(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<endpoint_definition>& _ep_definition);
+ void add_remote_service_info(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<endpoint_definition>& _ep_definition_reliable,
+ const std::shared_ptr<endpoint_definition>& _ep_definition_unreliable);
+ void clear_remote_service_info(service_t _service, instance_t _instance,
+ bool _reliable);
+
+ std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port,
+ bool _reliable,
+ bool _start);
+ std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port,
+ bool _reliable) const;
+
+ std::shared_ptr<endpoint> find_or_create_server_endpoint(
+ uint16_t _port, bool _reliable, bool _start, service_t _service,
+ instance_t _instance);
+ bool remove_server_endpoint(uint16_t _port, bool _reliable);
+
+
+ void clear_client_endpoints(service_t _service, instance_t _instance,
+ bool _reliable);
+ void find_or_create_multicast_endpoint(
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_address, uint16_t _port);
+ void clear_multicast_endpoints(service_t _service, instance_t _instance);
+
+ bool supports_selective(service_t _service, instance_t _instance) const;
+
+ void print_status() const;
+
+ std::shared_ptr<local_server_endpoint_impl> create_local_server(
+ bool* _is_socket_activated,
+ const std::shared_ptr<routing_host>& _routing_host);
+
+ instance_t find_instance(service_t _service,
+ endpoint* const _endpoint) const;
+ bool remove_instance(service_t _service, endpoint* const _endpoint);
+
+ // endpoint_host interface
+ void on_connect(std::shared_ptr<endpoint> _endpoint);
+ void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+ void on_error(const byte_t *_data, length_t _length,
+ endpoint* const _receiver,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port);
+ void release_port(uint16_t _port, bool _reliable);
+
+ // Statistics
+ void log_client_states() const;
+ void log_server_states() const;
+
+private:
+ std::shared_ptr<endpoint> find_remote_client(service_t _service,
+ instance_t _instance,
+ bool _reliable,
+ client_t _client);
+ std::shared_ptr<endpoint> create_remote_client(service_t _service,
+ instance_t _instance,
+ bool _reliable,
+ client_t _client);
+ std::shared_ptr<endpoint> create_client_endpoint(
+ const boost::asio::ip::address &_address, uint16_t _local_port,
+ uint16_t _remote_port, bool _reliable, client_t _client);
+
+private:
+ mutable std::recursive_mutex endpoint_mutex_;
+ // Client endpoints for remote services
+ std::map<service_t, std::map<instance_t,
+ std::map<bool, std::shared_ptr<endpoint_definition>>>> remote_service_info_;
+
+ typedef std::map<service_t, std::map<instance_t, std::map<client_t,
+ std::map<bool, std::shared_ptr<endpoint>>>>> remote_services_t;
+ remote_services_t remote_services_;
+
+ typedef std::map<boost::asio::ip::address, std::map<uint16_t,
+ std::map<bool, std::shared_ptr<endpoint>>>> client_endpoints_by_ip_t;
+ client_endpoints_by_ip_t client_endpoints_by_ip_;
+
+ std::map<service_t, std::map<endpoint *, instance_t> > service_instances_;
+
+ std::map<bool, std::set<uint16_t>> used_client_ports_;
+ std::mutex used_client_ports_mutex_;
+
+ // Server endpoints for local services
+ typedef std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint>>> server_endpoints_t;
+ server_endpoints_t server_endpoints_;
+
+ // Multicast endpoint info (notifications)
+ std::map<service_t, std::map<instance_t,
+ std::shared_ptr<endpoint_definition>>> multicast_info;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ENDPOINT_MANAGER_IMPL_HPP_
diff --git a/implementation/endpoints/include/local_client_endpoint_impl.hpp b/implementation/endpoints/include/local_client_endpoint_impl.hpp
index 16b3af5..0e81bf1 100644
--- a/implementation/endpoints/include/local_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_client_endpoint_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
-#define VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
+#ifndef VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_
#include <boost/asio/io_service.hpp>
#include <boost/asio/local/stream_protocol.hpp>
@@ -17,7 +17,7 @@
#include "client_endpoint_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
#ifdef _WIN32
typedef client_endpoint_impl<
@@ -31,11 +31,11 @@ typedef client_endpoint_impl<
class local_client_endpoint_impl: public local_client_endpoint_base_impl {
public:
- local_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _remote,
+ local_client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _remote,
boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit);
+ const std::shared_ptr<configuration>& _configuration);
virtual ~local_client_endpoint_impl();
@@ -50,8 +50,17 @@ public:
void restart(bool _force);
void print_status();
+ bool is_reliable() const;
+
+ // this overrides client_endpoint_impl::send to disable the pull method
+ // for local communication
+ bool send(const uint8_t *_data, uint32_t _size);
bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush = true);
+ uint32_t _size);
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
private:
void send_queued();
@@ -63,12 +72,17 @@ private:
std::size_t _bytes);
void set_local_port();
std::string get_remote_information() const;
+ bool check_packetizer_space(std::uint32_t _size);
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
std::uint32_t get_max_allowed_reconnects() const;
void max_allowed_reconnects_reached();
message_buffer_t recv_buffer_;
+
+ // send data
+ message_buffer_ptr_t send_data_buffer_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_LOCAL_CLIENT_ENDPOINT_IMPL_HPP
+#endif // VSOMEIP_V3_LOCAL_CLIENT_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/local_server_endpoint_impl.hpp b/implementation/endpoints/include/local_server_endpoint_impl.hpp
index 8ff8a10..965f03c 100644
--- a/implementation/endpoints/include/local_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/local_server_endpoint_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
-#define VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
+#ifndef VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
#include <map>
#include <thread>
@@ -12,7 +12,8 @@
#include <memory>
#include <boost/asio/io_service.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
+#include <boost/asio/local/stream_protocol_ext.hpp>
+
#ifdef _WIN32
#include <boost/asio/ip/tcp.hpp>
@@ -23,7 +24,7 @@
#include "buffer.hpp"
#include "server_endpoint_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
#ifdef _WIN32
typedef server_endpoint_impl<
@@ -31,29 +32,27 @@ typedef server_endpoint_impl<
> local_server_endpoint_base_impl;
#else
typedef server_endpoint_impl<
- boost::asio::local::stream_protocol
+ boost::asio::local::stream_protocol_ext
> local_server_endpoint_base_impl;
#endif
class local_server_endpoint_impl: public local_server_endpoint_base_impl {
public:
- local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
+ local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _mode);
+ const std::shared_ptr<configuration>& _configuration,
+ bool _is_routing_endpoint);
- local_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
+ local_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
int native_socket,
- std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _mode);
+ const std::shared_ptr<configuration>& _configuration,
+ bool _is_routing_endpoint);
virtual ~local_server_endpoint_impl();
@@ -62,9 +61,18 @@ public:
void receive();
+ // this overrides server_endpoint_impl::send to disable the nPDU feature
+ // for local communication
+ bool send(const uint8_t *_data, uint32_t _size);
bool send_to(const std::shared_ptr<endpoint_definition>,
- const byte_t *_data, uint32_t _size, bool _flush);
+ const byte_t *_data, uint32_t _size);
+ bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
void send_queued(const queue_iterator_type _queue_iterator);
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
bool get_default_target(service_t, endpoint_type &) const;
@@ -73,13 +81,18 @@ public:
void accept_client_func();
void print_status();
+ bool is_reliable() const;
+ std::uint16_t get_local_port() const;
+
+ client_t assign_client(const byte_t *_data, uint32_t _size);
+
private:
class connection: public std::enable_shared_from_this<connection> {
public:
typedef std::shared_ptr<connection> ptr;
- static ptr create(std::weak_ptr<local_server_endpoint_impl> _server,
+ static ptr create(const std::shared_ptr<local_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
boost::asio::io_service &_io_service);
@@ -89,22 +102,32 @@ private:
void start();
void stop();
- void send_queued(const queue_iterator_type _queue_iterator);
+
+ void send_queued(const message_buffer_ptr_t& _buffer);
void set_bound_client(client_t _client);
client_t get_bound_client() const;
+#ifndef _WIN32
+ void set_bound_uid_gid(uid_t _uid, gid_t _gid);
+#endif
std::size_t get_recv_buffer_capacity() const;
private:
- connection(std::weak_ptr<local_server_endpoint_impl> _server,
+ connection(const std::shared_ptr<local_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
- std::uint32_t _recv_buffer_size_initial,
+ std::uint32_t _initial_recv_buffer_size,
std::uint32_t _buffer_shrink_threshold,
boost::asio::io_service &_io_service);
+ void send_cbk(const message_buffer_ptr_t _buffer,
+ boost::system::error_code const &_error, std::size_t _bytes);
void receive_cbk(boost::system::error_code const &_error,
- std::size_t _bytes);
+ std::size_t _bytes
+#ifndef _WIN32
+ , std::uint32_t const &_uid, std::uint32_t const &_gid
+#endif
+ );
void calculate_shrink_count();
const std::string get_path_local() const;
const std::string get_path_remote() const;
@@ -124,33 +147,46 @@ private:
const std::uint32_t buffer_shrink_threshold_;
client_t bound_client_;
-
+#ifndef _WIN32
+ uid_t bound_uid_;
+ gid_t bound_gid_;
+#endif
+ bool assigned_client_;
};
std::mutex acceptor_mutex_;
#ifdef _WIN32
boost::asio::ip::tcp::acceptor acceptor_;
#else
- boost::asio::local::stream_protocol::acceptor acceptor_;
+ boost::asio::local::stream_protocol_ext::acceptor acceptor_;
#endif
- typedef std::map<endpoint_type, connection::ptr> connections_t;
+ typedef std::map<client_t, connection::ptr> connections_t;
std::mutex connections_mutex_;
connections_t connections_;
- std::mutex client_connections_mutex_;
- std::map<client_t, connection::ptr> client_connections_;
-
const std::uint32_t buffer_shrink_threshold_;
+ const bool is_routing_endpoint_;
+
private:
- void remove_connection(connection *_connection);
- void accept_cbk(connection::ptr _connection,
+ bool add_connection(const client_t &_client,
+ const std::shared_ptr<connection> &_connection);
+ void remove_connection(const client_t &_client);
+ void accept_cbk(const connection::ptr& _connection,
boost::system::error_code const &_error);
std::string get_remote_information(
const queue_iterator_type _queue_iterator) const;
+ std::string get_remote_information(
+ const endpoint_type& _remote) const;
+
+ bool check_packetizer_space(queue_iterator_type _queue_iterator,
+ message_buffer_ptr_t* _packetizer,
+ std::uint32_t _size);
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
+ void send_client_identifier(const client_t &_client);
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_LOCAL_SERVER_ENDPOINT_IMPL_HPP
+#endif // VSOMEIP_V3_LOCAL_SERVER_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/netlink_connector.hpp b/implementation/endpoints/include/netlink_connector.hpp
index 730874e..bb484b8 100644
--- a/implementation/endpoints/include/netlink_connector.hpp
+++ b/implementation/endpoints/include/netlink_connector.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_NETLINK_CONNECTOR_HPP
-#define VSOMEIP_NETLINK_CONNECTOR_HPP
+#ifndef VSOMEIP_V3_NETLINK_CONNECTOR_HPP_
+#define VSOMEIP_V3_NETLINK_CONNECTOR_HPP_
#ifndef _WIN32
@@ -15,12 +15,13 @@
#include <map>
#include <mutex>
-#include <boost/asio/ip/address.hpp>
+#include <boost/asio/io_service.hpp>
#include <boost/asio/basic_raw_socket.hpp>
+#include <boost/asio/ip/address.hpp>
#include "../../endpoints/include/buffer.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
template <typename Protocol>
class nl_endpoint {
@@ -34,15 +35,15 @@ public:
{
sockaddr.nl_family = PF_NETLINK;
sockaddr.nl_groups = 0;
- sockaddr.nl_pid = getpid();
+ sockaddr.nl_pid = static_cast<unsigned int>(getpid());
}
/// Construct an endpoint using the specified path name.
nl_endpoint(int group, int pid=getpid())
{
sockaddr.nl_family = PF_NETLINK;
- sockaddr.nl_groups = group;
- sockaddr.nl_pid = pid;
+ sockaddr.nl_groups = static_cast<unsigned int>(group);
+ sockaddr.nl_pid = static_cast<unsigned int>(pid);
}
/// Copy constructor.
@@ -85,6 +86,7 @@ public:
/// Set the underlying size of the endpoint in the native type.
void resize(std::size_t size)
{
+ (void)size;
/* nothing we can do here */
}
@@ -144,7 +146,7 @@ public:
}
~netlink_connector() {}
- void register_net_if_changes_handler(net_if_changed_handler_t _handler);
+ void register_net_if_changes_handler(const net_if_changed_handler_t& _handler);
void unregister_net_if_changes_handler();
void start();
@@ -180,8 +182,8 @@ private:
boost::asio::ip::address multicast_address_;
};
-}
+} // namespace vsomeip_v3
#endif // NOT _WIN32
-#endif // VSOMEIP_NETLINK_CONNECTOR_HPP
+#endif // VSOMEIP_V3_NETLINK_CONNECTOR_HPP_
diff --git a/implementation/endpoints/include/server_endpoint_impl.hpp b/implementation/endpoints/include/server_endpoint_impl.hpp
index 68e719b..4e03115 100644
--- a/implementation/endpoints/include/server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/server_endpoint_impl.hpp
@@ -1,87 +1,122 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SERVER_IMPL_HPP
-#define VSOMEIP_SERVER_IMPL_HPP
-
-#include <deque>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <vector>
-
-#include <boost/array.hpp>
-#include <boost/asio/io_service.hpp>
-
-#include "buffer.hpp"
-#include "endpoint_impl.hpp"
-
-namespace vsomeip {
-
-template<typename Protocol>
-class server_endpoint_impl: public endpoint_impl<Protocol>,
- public std::enable_shared_from_this<server_endpoint_impl<Protocol> > {
-public:
- typedef typename Protocol::socket socket_type;
- typedef typename Protocol::endpoint endpoint_type;
- typedef typename std::map<endpoint_type, std::pair<size_t, std::deque<message_buffer_ptr_t>>> queue_type;
- typedef typename queue_type::iterator queue_iterator_type;
-
- server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local, boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit);
- virtual ~server_endpoint_impl();
-
- bool is_client() const;
- void restart(bool _force);
- bool is_established() const;
- void set_established(bool _established);
- void set_connected(bool _connected);
- bool send(const uint8_t *_data, uint32_t _size, bool _flush);
- bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush = true);
-
- virtual void stop();
- bool flush(endpoint_type _target);
-
-public:
- void connect_cbk(boost::system::error_code const &_error);
- void send_cbk(const queue_iterator_type _queue_iterator,
- boost::system::error_code const &_error, std::size_t _bytes);
- void flush_cbk(endpoint_type _target,
- const boost::system::error_code &_error);
-
-public:
- virtual bool send_intern(endpoint_type _target, const byte_t *_data,
- uint32_t _port, bool _flush);
- virtual void send_queued(const queue_iterator_type _queue_iterator) = 0;
-
- virtual bool get_default_target(service_t _service,
- endpoint_type &_target) const = 0;
-
- virtual void print_status() = 0;
-
-protected:
- std::map<endpoint_type, message_buffer_ptr_t> packetizer_;
- queue_type queues_;
-
- std::mutex clients_mutex_;
- std::map<client_t, std::map<session_t, endpoint_type> > clients_;
- std::map<endpoint_type, client_t> endpoint_to_client_;
-
- boost::asio::steady_timer flush_timer_;
-
- std::mutex mutex_;
-
-private:
- virtual std::string get_remote_information(
- const queue_iterator_type _queue_iterator) const = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERVICE_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SERVER_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_SERVER_ENDPOINT_IMPL_HPP_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+#include <boost/array.hpp>
+#include <boost/asio/io_service.hpp>
+
+#include "buffer.hpp"
+#include "endpoint_impl.hpp"
+#include "tp.hpp"
+
+namespace vsomeip_v3 {
+
+template<typename Protocol>
+class server_endpoint_impl: public endpoint_impl<Protocol>,
+ public std::enable_shared_from_this<server_endpoint_impl<Protocol> > {
+public:
+ typedef typename Protocol::socket socket_type;
+ typedef typename Protocol::endpoint endpoint_type;
+ typedef typename std::map<endpoint_type, std::pair<size_t, std::deque<message_buffer_ptr_t>>> queue_type;
+ typedef typename queue_type::iterator queue_iterator_type;
+
+ server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ endpoint_type _local, boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~server_endpoint_impl();
+
+ bool is_client() const;
+ void restart(bool _force);
+ bool is_established() const;
+ bool is_established_or_connected() const;
+ void set_established(bool _established);
+ void set_connected(bool _connected);
+ bool send(const uint8_t *_data, uint32_t _size);
+ bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
+ uint32_t _size);
+
+ void prepare_stop(endpoint::prepare_stop_handler_t _handler,
+ service_t _service);
+ virtual void stop();
+ bool flush(endpoint_type _target,
+ const std::shared_ptr<train>& _train);
+
+ size_t get_queue_size() const;
+
+ virtual bool is_reliable() const = 0;
+ virtual std::uint16_t get_local_port() const = 0;
+
+public:
+ void connect_cbk(boost::system::error_code const &_error);
+ void send_cbk(const queue_iterator_type _queue_iterator,
+ boost::system::error_code const &_error, std::size_t _bytes);
+ void flush_cbk(endpoint_type _target,
+ const std::shared_ptr<train>& _train,
+ const boost::system::error_code &_error_code);
+
+protected:
+ virtual bool send_intern(endpoint_type _target, const byte_t *_data,
+ uint32_t _port);
+ virtual void send_queued(const queue_iterator_type _queue_iterator) = 0;
+ virtual void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const = 0;
+
+ virtual bool get_default_target(service_t _service,
+ endpoint_type &_target) const = 0;
+
+ virtual void print_status() = 0;
+
+ typename endpoint_impl<Protocol>::cms_ret_e check_message_size(
+ const std::uint8_t * const _data, std::uint32_t _size,
+ const endpoint_type& _target);
+ bool check_queue_limit(const uint8_t *_data, std::uint32_t _size,
+ std::size_t _current_queue_size) const;
+ void queue_train(const queue_iterator_type _queue_iterator,
+ const std::shared_ptr<train>& _train,
+ bool _queue_size_zero_on_entry);
+ queue_iterator_type find_or_create_queue_unlocked(const endpoint_type& _target);
+ std::shared_ptr<train> find_or_create_train_unlocked(const endpoint_type& _target);
+
+ void send_segments(const tp::tp_split_messages_t &_segments, const endpoint_type &_target);
+
+protected:
+ queue_type queues_;
+
+ std::mutex clients_mutex_;
+ std::map<client_t, std::map<session_t, endpoint_type> > clients_;
+
+ std::map<endpoint_type, std::shared_ptr<train>> trains_;
+
+ std::map<service_t, endpoint::prepare_stop_handler_t> prepare_stop_handlers_;
+
+ mutable std::mutex mutex_;
+
+private:
+ virtual std::string get_remote_information(
+ const queue_iterator_type _queue_iterator) const = 0;
+ virtual std::string get_remote_information(
+ const endpoint_type& _remote) const = 0;
+ virtual bool tp_segmentation_enabled(service_t _service,
+ method_t _method) const = 0;
+ void wait_until_debounce_time_reached(const std::shared_ptr<train>& _train) const;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SERVER_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
index 77cbd39..4765bd8 100644
--- a/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_client_endpoint_impl.hpp
@@ -1,98 +1,101 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_TCP_CLIENT_ENDPOINT_IMPL_HPP
-#define VSOMEIP_TCP_CLIENT_ENDPOINT_IMPL_HPP
-
-#include <boost/asio/ip/tcp.hpp>
-#include <chrono>
-
-#include <vsomeip/defines.hpp>
-#include "client_endpoint_impl.hpp"
-
-namespace vsomeip {
-
-typedef client_endpoint_impl<
- boost::asio::ip::tcp
- > tcp_client_endpoint_base_impl;
-
-class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl {
-public:
- tcp_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _tcp_restart_aborts_max,
- std::uint32_t _tcp_connect_time_max);
- virtual ~tcp_client_endpoint_impl();
-
- void start();
- void restart(bool _force);
-
- bool get_remote_address(boost::asio::ip::address &_address) const;
- std::uint16_t get_remote_port() const;
- bool is_reliable() const;
- bool is_local() const;
- void print_status();
-
- void send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
- message_buffer_ptr_t _sent_msg);
-private:
- void send_queued();
- bool is_magic_cookie(const message_buffer_ptr_t& _recv_buffer,
- size_t _offset) const;
- void send_magic_cookie(message_buffer_ptr_t &_buffer);
-
- void receive_cbk(boost::system::error_code const &_error,
- std::size_t _bytes,
- message_buffer_ptr_t _recv_buffer,
- std::size_t _recv_buffer_size);
-
- void connect();
- void receive();
- void receive(message_buffer_ptr_t _recv_buffer,
- std::size_t _recv_buffer_size,
- std::size_t _missing_capacity);
- void calculate_shrink_count(const message_buffer_ptr_t& _recv_buffer,
- std::size_t _recv_buffer_size);
- const std::string get_address_port_remote() const;
- const std::string get_address_port_local() const;
- void handle_recv_buffer_exception(const std::exception &_e,
- const message_buffer_ptr_t& _recv_buffer,
- std::size_t _recv_buffer_size);
- void set_local_port();
- std::size_t write_completion_condition(
- const boost::system::error_code& _error,
- std::size_t _bytes_transferred, std::size_t _bytes_to_send,
- service_t _service, method_t _method, client_t _client, session_t _session,
- std::chrono::steady_clock::time_point _start);
- std::string get_remote_information() const;
- std::uint32_t get_max_allowed_reconnects() const;
- void max_allowed_reconnects_reached();
-
- const std::uint32_t recv_buffer_size_initial_;
- message_buffer_ptr_t recv_buffer_;
- std::uint32_t shrink_count_;
- const std::uint32_t buffer_shrink_threshold_;
-
- const boost::asio::ip::address remote_address_;
- const std::uint16_t remote_port_;
- std::chrono::steady_clock::time_point last_cookie_sent_;
- const std::chrono::milliseconds send_timeout_;
- const std::chrono::milliseconds send_timeout_warning_;
-
- std::uint32_t tcp_restart_aborts_max_;
- std::uint32_t tcp_connect_time_max_;
- std::atomic<uint32_t> aborted_restart_count_;
- std::chrono::steady_clock::time_point connect_timepoint_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_TCP_CLIENT_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_TCP_CLIENT_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_TCP_CLIENT_ENDPOINT_IMPL_HPP_
+
+#include <boost/asio/ip/tcp.hpp>
+#include <chrono>
+
+#include <vsomeip/defines.hpp>
+#include "client_endpoint_impl.hpp"
+
+namespace vsomeip_v3 {
+
+typedef client_endpoint_impl<
+ boost::asio::ip::tcp
+ > tcp_client_endpoint_base_impl;
+
+class tcp_client_endpoint_impl: public tcp_client_endpoint_base_impl {
+public:
+ tcp_client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~tcp_client_endpoint_impl();
+
+ void start();
+ void restart(bool _force);
+
+ bool get_remote_address(boost::asio::ip::address &_address) const;
+ std::uint16_t get_remote_port() const;
+ bool is_reliable() const;
+ bool is_local() const;
+ void print_status();
+
+ void send_cbk(boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t& _sent_msg);
+private:
+ void send_queued();
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
+ bool is_magic_cookie(const message_buffer_ptr_t& _recv_buffer,
+ size_t _offset) const;
+ void send_magic_cookie(message_buffer_ptr_t &_buffer);
+
+ void receive_cbk(boost::system::error_code const &_error,
+ std::size_t _bytes,
+ const message_buffer_ptr_t& _recv_buffer,
+ std::size_t _recv_buffer_size);
+
+ void connect();
+ void receive();
+ void receive(message_buffer_ptr_t _recv_buffer,
+ std::size_t _recv_buffer_size,
+ std::size_t _missing_capacity);
+ void calculate_shrink_count(const message_buffer_ptr_t& _recv_buffer,
+ std::size_t _recv_buffer_size);
+ const std::string get_address_port_remote() const;
+ const std::string get_address_port_local() const;
+ void handle_recv_buffer_exception(const std::exception &_e,
+ const message_buffer_ptr_t& _recv_buffer,
+ std::size_t _recv_buffer_size);
+ void set_local_port();
+ std::size_t write_completion_condition(
+ const boost::system::error_code& _error,
+ std::size_t _bytes_transferred, std::size_t _bytes_to_send,
+ service_t _service, method_t _method, client_t _client, session_t _session,
+ const std::chrono::steady_clock::time_point _start);
+ std::string get_remote_information() const;
+ std::shared_ptr<struct timing> get_timing(
+ const service_t& _service, const instance_t& _instance) const;
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
+ std::uint32_t get_max_allowed_reconnects() const;
+ void max_allowed_reconnects_reached();
+
+ const std::uint32_t recv_buffer_size_initial_;
+ message_buffer_ptr_t recv_buffer_;
+ std::uint32_t shrink_count_;
+ const std::uint32_t buffer_shrink_threshold_;
+
+ const boost::asio::ip::address remote_address_;
+ const std::uint16_t remote_port_;
+ std::chrono::steady_clock::time_point last_cookie_sent_;
+ const std::chrono::milliseconds send_timeout_;
+ const std::chrono::milliseconds send_timeout_warning_;
+
+ std::uint32_t tcp_restart_aborts_max_;
+ std::uint32_t tcp_connect_time_max_;
+ std::atomic<uint32_t> aborted_restart_count_;
+ std::chrono::steady_clock::time_point connect_timepoint_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_TCP_CLIENT_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
index 5e9b50b..c6481b8 100644
--- a/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/tcp_server_endpoint_impl.hpp
@@ -1,147 +1,153 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_TCP_SERVER_ENDPOINT_IMPL_HPP
-#define VSOMEIP_TCP_SERVER_ENDPOINT_IMPL_HPP
-
-#include <map>
-#include <memory>
-
-#include <boost/asio/ip/tcp.hpp>
-
-#include <vsomeip/defines.hpp>
-#include <vsomeip/export.hpp>
-#include "server_endpoint_impl.hpp"
-
-#include <chrono>
-
-namespace vsomeip {
-
-typedef server_endpoint_impl<
- boost::asio::ip::tcp
- > tcp_server_endpoint_base_impl;
-
-class tcp_server_endpoint_impl: public tcp_server_endpoint_base_impl {
-
-public:
- tcp_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit);
- virtual ~tcp_server_endpoint_impl();
-
- void start();
- void stop();
-
- bool send_to(const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush);
- void send_queued(const queue_iterator_type _queue_iterator);
-
- VSOMEIP_EXPORT bool is_established(std::shared_ptr<endpoint_definition> _endpoint);
-
- bool get_default_target(service_t, endpoint_type &) const;
-
- std::uint16_t get_local_port() const;
- bool is_reliable() const;
- bool is_local() const;
-
- client_t get_client(std::shared_ptr<endpoint_definition> _endpoint);
-
- // dummies to implement endpoint_impl interface
- // TODO: think about a better design!
- void receive();
- void print_status();
-private:
- class connection: public std::enable_shared_from_this<connection> {
-
- public:
- typedef std::shared_ptr<connection> ptr;
-
- static ptr create(std::weak_ptr<tcp_server_endpoint_impl> _server,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- bool _magic_cookies_enabled,
- boost::asio::io_service & _io_service,
- std::chrono::milliseconds _send_timeout);
- socket_type & get_socket();
- std::unique_lock<std::mutex> get_socket_lock();
-
- void start();
- void stop();
- void receive();
-
- void send_queued(const queue_iterator_type _queue_iterator);
-
- void set_remote_info(const endpoint_type &_remote);
- const std::string get_address_port_remote() const;
- std::size_t get_recv_buffer_capacity() const;
-
- private:
- connection(std::weak_ptr<tcp_server_endpoint_impl> _server,
- std::uint32_t _max_message_size,
- std::uint32_t _recv_buffer_size_initial,
- std::uint32_t _buffer_shrink_threshold,
- bool _magic_cookies_enabled,
- boost::asio::io_service & _io_service,
- std::chrono::milliseconds _send_timeout);
- bool send_magic_cookie(message_buffer_ptr_t &_buffer);
- bool is_magic_cookie(size_t _offset) const;
- void receive_cbk(boost::system::error_code const &_error,
- std::size_t _bytes);
- void calculate_shrink_count();
- const std::string get_address_port_local() const;
- void handle_recv_buffer_exception(const std::exception &_e);
- std::size_t write_completion_condition(
- const boost::system::error_code& _error,
- std::size_t _bytes_transferred, std::size_t _bytes_to_send,
- service_t _service, method_t _method, client_t _client, session_t _session,
- std::chrono::steady_clock::time_point _start);
- void stop_and_remove_connection();
-
- std::mutex socket_mutex_;
- tcp_server_endpoint_impl::socket_type socket_;
- std::weak_ptr<tcp_server_endpoint_impl> server_;
-
- const uint32_t max_message_size_;
- const uint32_t recv_buffer_size_initial_;
-
- message_buffer_t recv_buffer_;
- size_t recv_buffer_size_;
- std::uint32_t missing_capacity_;
- std::uint32_t shrink_count_;
- const std::uint32_t buffer_shrink_threshold_;
-
- endpoint_type remote_;
- boost::asio::ip::address remote_address_;
- std::uint16_t remote_port_;
- std::atomic<bool> magic_cookies_enabled_;
- std::chrono::steady_clock::time_point last_cookie_sent_;
- const std::chrono::milliseconds send_timeout_;
- const std::chrono::milliseconds send_timeout_warning_;
- };
-
- std::mutex acceptor_mutex_;
- boost::asio::ip::tcp::acceptor acceptor_;
- std::mutex connections_mutex_;
- typedef std::map<endpoint_type, connection::ptr> connections_t;
- connections_t connections_;
- const std::uint32_t buffer_shrink_threshold_;
- const std::uint16_t local_port_;
- const std::chrono::milliseconds send_timeout_;
-
-private:
- void remove_connection(connection *_connection);
- void accept_cbk(connection::ptr _connection,
- boost::system::error_code const &_error);
- std::string get_remote_information(
- const queue_iterator_type _queue_iterator) const;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_TCP_SERVER_ENDPOINT_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_TCP_SERVER_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_TCP_SERVER_ENDPOINT_IMPL_HPP_
+
+#include <map>
+#include <memory>
+
+#include <boost/asio/ip/tcp.hpp>
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/export.hpp>
+#include "server_endpoint_impl.hpp"
+
+#include <chrono>
+
+namespace vsomeip_v3 {
+
+typedef server_endpoint_impl<
+ boost::asio::ip::tcp
+ > tcp_server_endpoint_base_impl;
+
+class tcp_server_endpoint_impl: public tcp_server_endpoint_base_impl {
+
+public:
+ tcp_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~tcp_server_endpoint_impl();
+
+ void start();
+ void stop();
+
+ bool send_to(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ void send_queued(const queue_iterator_type _queue_iterator);
+ void send_queued_sync(const queue_iterator_type _queue_iterator);
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
+
+ VSOMEIP_EXPORT bool is_established(const std::shared_ptr<endpoint_definition>& _endpoint);
+
+ bool get_default_target(service_t, endpoint_type &) const;
+
+ std::uint16_t get_local_port() const;
+ bool is_reliable() const;
+ bool is_local() const;
+
+ // dummies to implement endpoint_impl interface
+ // TODO: think about a better design!
+ void receive();
+ void print_status();
+private:
+ class connection: public std::enable_shared_from_this<connection> {
+
+ public:
+ typedef std::shared_ptr<connection> ptr;
+
+ static ptr create(const std::weak_ptr<tcp_server_endpoint_impl>& _server,
+ std::uint32_t _max_message_size,
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service & _io_service,
+ std::chrono::milliseconds _send_timeout);
+ socket_type & get_socket();
+ std::unique_lock<std::mutex> get_socket_lock();
+
+ void start();
+ void stop();
+ void receive();
+
+ void send_queued(const queue_iterator_type _queue_iterator);
+ void send_queued_sync(const queue_iterator_type _queue_iterator);
+
+ void set_remote_info(const endpoint_type &_remote);
+ const std::string get_address_port_remote() const;
+ std::size_t get_recv_buffer_capacity() const;
+
+ private:
+ connection(const std::weak_ptr<tcp_server_endpoint_impl>& _server,
+ std::uint32_t _max_message_size,
+ std::uint32_t _recv_buffer_size_initial,
+ std::uint32_t _buffer_shrink_threshold,
+ bool _magic_cookies_enabled,
+ boost::asio::io_service & _io_service,
+ std::chrono::milliseconds _send_timeout);
+ bool send_magic_cookie(message_buffer_ptr_t &_buffer);
+ bool is_magic_cookie(size_t _offset) const;
+ void receive_cbk(boost::system::error_code const &_error,
+ std::size_t _bytes);
+ void calculate_shrink_count();
+ const std::string get_address_port_local() const;
+ void handle_recv_buffer_exception(const std::exception &_e);
+ std::size_t write_completion_condition(
+ const boost::system::error_code& _error,
+ std::size_t _bytes_transferred, std::size_t _bytes_to_send,
+ service_t _service, method_t _method, client_t _client, session_t _session,
+ const std::chrono::steady_clock::time_point _start);
+ void stop_and_remove_connection();
+
+ std::mutex socket_mutex_;
+ tcp_server_endpoint_impl::socket_type socket_;
+ std::weak_ptr<tcp_server_endpoint_impl> server_;
+
+ const uint32_t max_message_size_;
+ const uint32_t recv_buffer_size_initial_;
+
+ message_buffer_t recv_buffer_;
+ size_t recv_buffer_size_;
+ std::uint32_t missing_capacity_;
+ std::uint32_t shrink_count_;
+ const std::uint32_t buffer_shrink_threshold_;
+
+ endpoint_type remote_;
+ boost::asio::ip::address remote_address_;
+ std::uint16_t remote_port_;
+ std::atomic<bool> magic_cookies_enabled_;
+ std::chrono::steady_clock::time_point last_cookie_sent_;
+ const std::chrono::milliseconds send_timeout_;
+ const std::chrono::milliseconds send_timeout_warning_;
+ };
+
+ std::mutex acceptor_mutex_;
+ boost::asio::ip::tcp::acceptor acceptor_;
+ std::mutex connections_mutex_;
+ typedef std::map<endpoint_type, connection::ptr> connections_t;
+ connections_t connections_;
+ const std::uint32_t buffer_shrink_threshold_;
+ const std::uint16_t local_port_;
+ const std::chrono::milliseconds send_timeout_;
+
+private:
+ void remove_connection(connection *_connection);
+ void accept_cbk(const connection::ptr& _connection,
+ boost::system::error_code const &_error);
+ std::string get_remote_information(
+ const queue_iterator_type _queue_iterator) const;
+ std::string get_remote_information(const endpoint_type& _remote) const;
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_TCP_SERVER_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/tp.hpp b/implementation/endpoints/include/tp.hpp
new file mode 100644
index 0000000..f11718d
--- /dev/null
+++ b/implementation/endpoints/include/tp.hpp
@@ -0,0 +1,60 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_TP_HPP_
+#define VSOMEIP_V3_TP_HPP_
+
+#include <cstdint>
+#include <vector>
+#include <utility>
+#include <memory>
+
+#include <vsomeip/enumeration_types.hpp>
+
+#include "buffer.hpp"
+
+namespace vsomeip_v3 {
+namespace tp {
+
+#define VSOMEIP_TP_HEADER_SIZE 4
+#define VSOMEIP_TP_HEADER_POS_MIN 16
+#define VSOMEIP_TP_HEADER_POS_MAX 19
+#define VSOMEIP_TP_PAYLOAD_POS 20
+
+// 28 bit length + 3 bit reserved + 1 bit more segments
+typedef std::uint32_t tp_header_t;
+typedef std::uint8_t tp_message_type_t;
+typedef std::vector<message_buffer_ptr_t> tp_split_messages_t;
+
+const std::uint8_t TP_FLAG = 0x20;
+
+class tp {
+public:
+ static inline length_t get_offset(tp_header_t _tp_header) {
+ return _tp_header & 0xfffffff0;
+ };
+ static inline bool more_segments(tp_header_t _tp_header) {
+ return _tp_header & 0x1;
+ };
+ static inline bool tp_flag_is_set(tp_message_type_t _msg_type) {
+ return _msg_type & TP_FLAG;
+ };
+ static inline tp_message_type_t tp_flag_set(message_type_e _msg_type) {
+ return static_cast<tp_message_type_t>(_msg_type) | TP_FLAG;
+ }
+ static inline message_type_e tp_flag_unset(tp_message_type_t _msg_type) {
+ return static_cast<message_type_e>(_msg_type & ~TP_FLAG);
+ }
+
+ static tp_split_messages_t tp_split_message(
+ const std::uint8_t * const _data, std::uint32_t _size);
+
+ static const std::uint16_t tp_max_segment_length_ = 1392;
+};
+
+} // namespace tp
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_TP_HPP_
diff --git a/implementation/endpoints/include/tp_message.hpp b/implementation/endpoints/include/tp_message.hpp
new file mode 100644
index 0000000..269a1f1
--- /dev/null
+++ b/implementation/endpoints/include/tp_message.hpp
@@ -0,0 +1,62 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_TP_MESSAGE_HPP_
+#define VSOMEIP_V3_TP_MESSAGE_HPP_
+
+#include <set>
+#include <chrono>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/enumeration_types.hpp>
+
+#include "buffer.hpp"
+
+namespace vsomeip_v3 {
+namespace tp {
+
+class tp_message {
+public:
+ tp_message(const byte_t* const _data, std::uint32_t _data_length,
+ std::uint32_t _max_message_size);
+
+ bool add_segment(const byte_t* const _data, std::uint32_t _data_length);
+
+ message_buffer_t get_message();
+
+ std::chrono::steady_clock::time_point get_creation_time() const;
+
+private:
+ std::string get_message_id(const byte_t* const _data, std::uint32_t _data_length);
+ bool check_lengths(const byte_t* const _data, std::uint32_t _data_length,
+ length_t _segment_size, bool _more_fragments);
+private:
+ std::chrono::steady_clock::time_point timepoint_creation_;
+ std::uint32_t max_message_size_;
+ std::uint32_t current_message_size_;
+ bool last_segment_received_;
+
+ struct segment_t {
+ segment_t(std::uint32_t _start, std::uint32_t _end) :
+ start_(_start),
+ end_(_end) {
+ }
+
+ bool operator<(const segment_t& _other) const {
+ return start_ < _other.start_
+ || ((start_ >= _other.start_) && (end_ < _other.end_));
+ };
+
+ std::uint32_t start_;
+ std::uint32_t end_;
+ };
+ std::set<segment_t> segments_;
+ message_buffer_t message_;
+};
+
+} // namespace tp
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_TP_MESSAGE_HPP_
diff --git a/implementation/endpoints/include/tp_reassembler.hpp b/implementation/endpoints/include/tp_reassembler.hpp
new file mode 100644
index 0000000..aaf61c5
--- /dev/null
+++ b/implementation/endpoints/include/tp_reassembler.hpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_TP_REASSEMBLER_HPP_
+#define VSOMEIP_V3_TP_REASSEMBLER_HPP_
+
+#include <cstdint>
+#include <map>
+#include <mutex>
+#include <memory>
+
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/steady_timer.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "tp_message.hpp"
+
+
+namespace vsomeip_v3 {
+namespace tp {
+
+class tp_reassembler : public std::enable_shared_from_this<tp_reassembler> {
+public:
+ tp_reassembler(std::uint32_t _max_message_size, boost::asio::io_service &_io);
+ /**
+ * @return Returns a pair consisting of a bool and a message_buffer_t. The
+ * value of the bool is set to true if the pair contains a finished message
+ */
+ std::pair<bool, message_buffer_t> process_tp_message(
+ const byte_t* const _data, std::uint32_t _data_size,
+ const boost::asio::ip::address& _address, std::uint16_t _port);
+ bool cleanup_unfinished_messages();
+ void stop();
+
+private:
+ void cleanup_timer_start(bool _force);
+ void cleanup_timer_start_unlocked(bool _force);
+ void cleanup_timer_cbk(const boost::system::error_code _error);
+
+private:
+ const std::uint32_t max_message_size_;
+ std::mutex cleanup_timer_mutex_;
+ bool cleanup_timer_running_;
+ boost::asio::steady_timer cleanup_timer_;
+
+ std::mutex mutex_;
+ std::map<boost::asio::ip::address, std::map<std::uint16_t,
+ std::map<std::uint64_t, std::pair<session_t, tp_message>>>> tp_messages_;
+};
+
+} // namespace tp
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_TP_REASSEMBLER_HPP_
diff --git a/implementation/endpoints/include/udp_client_endpoint_impl.hpp b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
index b11da93..05c63c4 100644
--- a/implementation/endpoints/include/udp_client_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_client_endpoint_impl.hpp
@@ -1,65 +1,75 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_INTERNAL_UDP_CLIENT_IMPL_HPP
-#define VSOMEIP_INTERNAL_UDP_CLIENT_IMPL_HPP
-
-#include <memory>
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ip/udp.hpp>
-
-#include <vsomeip/defines.hpp>
-
-#include "client_endpoint_impl.hpp"
-
-namespace vsomeip {
-
-class endpoint_adapter;
-
-typedef client_endpoint_impl<
- boost::asio::ip::udp
- > udp_client_endpoint_base_impl;
-
-class udp_client_endpoint_impl: virtual public udp_client_endpoint_base_impl {
-
-public:
- udp_client_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _udp_receive_buffer_size);
- virtual ~udp_client_endpoint_impl();
-
- void start();
- void restart(bool _force);
-
- void receive_cbk(boost::system::error_code const &_error,
- std::size_t _bytes, message_buffer_ptr_t _recv_buffer);
-
- bool get_remote_address(boost::asio::ip::address &_address) const;
- std::uint16_t get_remote_port() const;
- bool is_local() const;
- void print_status();
-private:
- void send_queued();
- void connect();
- void receive();
- void set_local_port();
- const std::string get_address_port_remote() const;
- const std::string get_address_port_local() const;
- std::string get_remote_information() const;
- std::uint32_t get_max_allowed_reconnects() const;
- void max_allowed_reconnects_reached();
-
- const boost::asio::ip::address remote_address_;
- const std::uint16_t remote_port_;
- const std::uint32_t udp_receive_buffer_size_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_UDP_CLIENT_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_UDP_CLIENT_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_UDP_CLIENT_ENDPOINT_IMPL_HPP_
+
+#include <memory>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/ip/udp.hpp>
+
+#include <vsomeip/defines.hpp>
+
+#include "client_endpoint_impl.hpp"
+#include "tp_reassembler.hpp"
+
+namespace vsomeip_v3 {
+
+class endpoint_adapter;
+
+typedef client_endpoint_impl<
+ boost::asio::ip::udp
+ > udp_client_endpoint_base_impl;
+
+class udp_client_endpoint_impl: virtual public udp_client_endpoint_base_impl {
+
+public:
+ udp_client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~udp_client_endpoint_impl();
+
+ void start();
+ void restart(bool _force);
+
+ void receive_cbk(boost::system::error_code const &_error,
+ std::size_t _bytes, const message_buffer_ptr_t& _recv_buffer);
+
+ bool get_remote_address(boost::asio::ip::address &_address) const;
+ std::uint16_t get_remote_port() const;
+ bool is_local() const;
+ void print_status();
+ bool is_reliable() const;
+private:
+ void send_queued();
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
+ void connect();
+ void receive();
+ void set_local_port();
+ const std::string get_address_port_remote() const;
+ const std::string get_address_port_local() const;
+ std::string get_remote_information() const;
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
+ std::uint32_t get_max_allowed_reconnects() const;
+ void max_allowed_reconnects_reached();
+
+private:
+ const boost::asio::ip::address remote_address_;
+ const std::uint16_t remote_port_;
+ const std::uint32_t udp_receive_buffer_size_;
+ std::shared_ptr<tp::tp_reassembler> tp_reassembler_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_UDP_CLIENT_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/udp_server_endpoint_impl.hpp b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
index f1b6959..1a6cef6 100644
--- a/implementation/endpoints/include/udp_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/udp_server_endpoint_impl.hpp
@@ -1,88 +1,116 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_INTERNAL_UDP_SERVICE_IMPL_HPP
-#define VSOMEIP_INTERNAL_UDP_SERVICE_IMPL_HPP
-
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ip/udp_ext.hpp>
-
-#include <vsomeip/defines.hpp>
-
-#include "server_endpoint_impl.hpp"
-#include <atomic>
-
-namespace vsomeip {
-
-typedef server_endpoint_impl<
- boost::asio::ip::udp_ext
- > udp_server_endpoint_base_impl;
-
-class udp_server_endpoint_impl: public udp_server_endpoint_base_impl {
-
-public:
- udp_server_endpoint_impl(std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _udp_receive_buffer_size);
- virtual ~udp_server_endpoint_impl();
-
- void start();
- void stop();
-
- void receive();
-
- bool send_to(const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush);
- void send_queued(const queue_iterator_type _queue_iterator);
-
- void join(const std::string &_address);
- void leave(const std::string &_address);
-
- void add_default_target(service_t _service,
- const std::string &_address, uint16_t _port);
- void remove_default_target(service_t _service);
- bool get_default_target(service_t _service, endpoint_type &_target) const;
-
- std::uint16_t get_local_port() const;
- bool is_local() const;
-
- client_t get_client(std::shared_ptr<endpoint_definition> _endpoint);
-
- void receive_cbk(boost::system::error_code const &_error,
- std::size_t _size,
- boost::asio::ip::address const &_destination);
-
- void print_status();
-
-private:
- void set_broadcast();
- bool is_joined(const std::string &_address) const;
- bool is_joined(const std::string &_address, bool* _received) const;
- std::string get_remote_information(
- const queue_iterator_type _queue_iterator) const;
-
- const std::string get_address_port_local() const;
-
-private:
- socket_type socket_;
- endpoint_type remote_;
-
- mutable std::mutex default_targets_mutex_;
- std::map<service_t, endpoint_type> default_targets_;
- mutable std::mutex joined_mutex_;
- std::map<std::string, bool> joined_;
- std::atomic<bool> joined_group_;
-
- message_buffer_t recv_buffer_;
- mutable std::mutex socket_mutex_;
-
- const std::uint16_t local_port_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_UDP_SERVICE_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_HPP_
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/udp_ext.hpp>
+
+#include <atomic>
+
+#include <vsomeip/defines.hpp>
+
+#include "server_endpoint_impl.hpp"
+#include "tp_reassembler.hpp"
+
+namespace vsomeip_v3 {
+
+typedef server_endpoint_impl<
+ boost::asio::ip::udp_ext
+ > udp_server_endpoint_base_impl;
+
+class udp_server_endpoint_impl: public udp_server_endpoint_base_impl {
+
+public:
+ udp_server_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration);
+ virtual ~udp_server_endpoint_impl();
+
+ void start();
+ void stop();
+
+ void receive();
+
+ bool send_to(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
+ void send_queued(const queue_iterator_type _queue_iterator);
+ void get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const;
+
+ VSOMEIP_EXPORT void join(const std::string &_address);
+ void leave(const std::string &_address);
+
+ void add_default_target(service_t _service,
+ const std::string &_address, uint16_t _port);
+ void remove_default_target(service_t _service);
+ bool get_default_target(service_t _service, endpoint_type &_target) const;
+
+ std::uint16_t get_local_port() const;
+ bool is_local() const;
+
+ void print_status();
+ bool is_reliable() const;
+
+private:
+ void set_broadcast();
+ void receive_unicast();
+ void receive_multicast();
+ bool is_joined(const std::string &_address) const;
+ bool is_joined(const std::string &_address, bool* _received) const;
+ std::string get_remote_information(
+ const queue_iterator_type _queue_iterator) const;
+ std::string get_remote_information(const endpoint_type& _remote) const;
+
+ const std::string get_address_port_local() const;
+ bool tp_segmentation_enabled(service_t _service, method_t _method) const;
+
+ void on_unicast_received(boost::system::error_code const &_error,
+ std::size_t _bytes,
+ boost::asio::ip::address const &_destination);
+
+ void on_multicast_received(boost::system::error_code const &_error,
+ std::size_t _bytes,
+ boost::asio::ip::address const &_destination);
+
+ void on_message_received(boost::system::error_code const &_error,
+ std::size_t _bytes,
+ boost::asio::ip::address const &_destination,
+ endpoint_type const &_remote,
+ message_buffer_t const &_buffer);
+
+private:
+ socket_type unicast_socket_;
+ endpoint_type unicast_remote_;
+ message_buffer_t unicast_recv_buffer_;
+ mutable std::mutex unicast_socket_mutex_;
+
+ std::unique_ptr<socket_type> multicast_socket_;
+ std::unique_ptr<endpoint_type> multicast_ep_;
+ endpoint_type multicast_remote_;
+ std::unique_ptr<message_buffer_t> multicast_recv_buffer_;
+ mutable std::mutex multicast_socket_mutex_;
+
+ mutable std::mutex default_targets_mutex_;
+ std::map<service_t, endpoint_type> default_targets_;
+ mutable std::mutex joined_mutex_;
+ std::map<std::string, bool> joined_;
+ std::atomic<bool> joined_group_;
+ const std::uint16_t local_port_;
+
+ std::shared_ptr<tp::tp_reassembler> tp_reassembler_;
+ boost::asio::steady_timer tp_cleanup_timer_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_UDP_SERVER_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
index afe56e2..38db284 100644
--- a/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
+++ b/implementation/endpoints/include/virtual_server_endpoint_impl.hpp
@@ -3,42 +3,47 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP
-#define VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP
+#ifndef VSOMEIP_V3_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP_
+#define VSOMEIP_V3_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP_
+
+#include <boost/asio/io_service.hpp>
#include <vsomeip/primitive_types.hpp>
#include "../include/endpoint.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
-class virtual_server_endpoint_impl : public endpoint {
+class virtual_server_endpoint_impl : public endpoint, public std::enable_shared_from_this<virtual_server_endpoint_impl> {
public:
virtual_server_endpoint_impl(
const std::string &_address,
uint16_t _port,
- bool _reliable);
+ bool _reliable,
+ boost::asio::io_service& _service);
virtual ~virtual_server_endpoint_impl();
void start();
+ void prepare_stop(endpoint::prepare_stop_handler_t _handler,
+ service_t _service);
void stop();
bool is_established() const;
+ bool is_established_or_connected() const;
void set_established(bool _established);
void set_connected(bool _connected);
- bool send(const byte_t *_data, uint32_t _size, bool _flush);
+ bool send(const byte_t *_data, uint32_t _size);
bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush);
+ uint32_t _size);
bool send_to(const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush);
+ const byte_t *_data, uint32_t _size);
+ bool send_error(const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size);
void enable_magic_cookies();
void receive();
- void join(const std::string &_address);
- void leave(const std::string &_address);
-
void add_default_target(service_t _service,
const std::string &_address, uint16_t _port);
void remove_default_target(service_t _service);
@@ -58,14 +63,17 @@ public:
void register_error_handler(error_handler_t _handler);
void print_status();
+ size_t get_queue_size() const;
+
private:
std::string address_;
uint16_t port_;
bool reliable_;
uint32_t use_count_;
+ boost::asio::io_service& service_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP
+#endif // VSOMEIP_V3_VIRTUAL_SERVER_ENDPOINT_IMPL_HPP_
diff --git a/implementation/endpoints/src/client_endpoint_impl.cpp b/implementation/endpoints/src/client_endpoint_impl.cpp
index 2f521ea..434ed14 100644
--- a/implementation/endpoints/src/client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/client_endpoint_impl.cpp
@@ -1,507 +1,686 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <chrono>
-#include <iomanip>
-#include <sstream>
-#include <thread>
-#include <limits>
-
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/ip/tcp.hpp>
-#include <boost/asio/ip/udp.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-
-#include <vsomeip/defines.hpp>
-
-#include "../include/client_endpoint_impl.hpp"
-#include "../include/endpoint_host.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/utility.hpp"
-#include "../../utility/include/byteorder.hpp"
-
-namespace vsomeip {
-
-template<typename Protocol>
-client_endpoint_impl<Protocol>::client_endpoint_impl(
- std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit)
- : endpoint_impl<Protocol>(_host, _local, _io, _max_message_size, _queue_limit),
- socket_(new socket_type(_io)), remote_(_remote),
- flush_timer_(_io), connect_timer_(_io),
- connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable
- state_(cei_state_e::CLOSED),
- reconnect_counter_(0),
- packetizer_(std::make_shared<message_buffer_t>()),
- queue_size_(0),
- was_not_connected_(false),
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <chrono>
+#include <iomanip>
+#include <sstream>
+#include <thread>
+#include <limits>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/client_endpoint_impl.hpp"
+#include "../include/endpoint_host.hpp"
+#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+namespace vsomeip_v3 {
+
+template<typename Protocol>
+client_endpoint_impl<Protocol>::client_endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration)
+ : endpoint_impl<Protocol>(_endpoint_host, _routing_host, _local, _io,
+ _max_message_size, _queue_limit, _configuration),
+ socket_(new socket_type(_io)), remote_(_remote),
+ flush_timer_(_io), connect_timer_(_io),
+ connect_timeout_(VSOMEIP_DEFAULT_CONNECT_TIMEOUT), // TODO: use config variable
+ state_(cei_state_e::CLOSED),
+ reconnect_counter_(0),
+ train_(_io),
+ queue_size_(0),
+ was_not_connected_(false),
local_port_(0),
strand_(_io) {
-}
-
-template<typename Protocol>
-client_endpoint_impl<Protocol>::~client_endpoint_impl() {
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::is_client() const {
- return true;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::is_established() const {
- return state_ == cei_state_e::ESTABLISHED;
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::set_established(bool _established) {
- if (_established) {
- if (state_ != cei_state_e::CONNECTING) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (socket_->is_open()) {
- state_ = cei_state_e::ESTABLISHED;
- } else {
- state_ = cei_state_e::CLOSED;
- }
- }
- } else {
- state_ = cei_state_e::CLOSED;
- } }
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::set_connected(bool _connected) {
- if (_connected) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (socket_->is_open()) {
- state_ = cei_state_e::CONNECTED;
- } else {
- state_ = cei_state_e::CLOSED;
- }
- } else {
- state_ = cei_state_e::CLOSED;
- }
-}
-
-template<typename Protocol> void client_endpoint_impl<Protocol>::stop() {
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- endpoint_impl<Protocol>::sending_blocked_ = true;
- // delete unsent messages
- queue_.clear();
- queue_size_ = 0;
- }
- {
- std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
- boost::system::error_code ec;
- connect_timer_.cancel(ec);
- }
- connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;
- shutdown_and_close_socket(false);
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::send_to(
- const std::shared_ptr<endpoint_definition> _target, const byte_t *_data,
- uint32_t _size, bool _flush) {
- (void)_target;
- (void)_data;
- (void)_size;
- (void)_flush;
-
- VSOMEIP_ERROR << "Clients endpoints must not be used to "
- << "send to explicitely specified targets";
- return false;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::send(const uint8_t *_data,
- uint32_t _size, bool _flush) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- bool ret(true);
- const bool queue_size_zero_on_entry(queue_.empty());
- if (endpoint_impl<Protocol>::sending_blocked_ ||
- !check_message_size(_size) ||
- !check_packetizer_space(_size) ||
- !check_queue_limit(_data, _size)) {
- ret = false;
- } else {
-#if 0
- std::stringstream msg;
- msg << "cei::send: ";
- for (uint32_t i = 0; i < _size; i++)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)_data[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- packetizer_->insert(packetizer_->end(), _data, _data + _size);
- send_or_start_flush_timer(_flush, queue_size_zero_on_entry);
- }
- return ret;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::send(const std::vector<byte_t>& _cmd_header,
- const byte_t *_data, uint32_t _size,
- bool _flush) {
- (void) _cmd_header;
- (void) _data;
- (void) _size;
- (void) _flush;
- return false;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::flush() {
- bool is_successful(true);
- std::lock_guard<std::mutex> its_lock(mutex_);
- if (!packetizer_->empty()) {
- queue_.push_back(packetizer_);
- queue_size_ += packetizer_->size();
- packetizer_ = std::make_shared<message_buffer_t>();
- if (queue_.size() == 1) { // no writing in progress
- send_queued();
- }
- } else {
- is_successful = false;
- }
-
- return is_successful;
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::connect_cbk(
- boost::system::error_code const &_error) {
- if (_error == boost::asio::error::operation_aborted
- || endpoint_impl<Protocol>::sending_blocked_) {
- // endpoint was stopped
- shutdown_and_close_socket(false);
- return;
- }
- std::shared_ptr<endpoint_host> its_host = this->host_.lock();
- if (its_host) {
- if (_error && _error != boost::asio::error::already_connected) {
- shutdown_and_close_socket(true);
-
- if (state_ != cei_state_e::ESTABLISHED) {
- state_ = cei_state_e::CLOSED;
- its_host->on_disconnect(this->shared_from_this());
- }
- if (get_max_allowed_reconnects() == MAX_RECONNECTS_UNLIMITED ||
- get_max_allowed_reconnects() >= ++reconnect_counter_) {
- start_connect_timer();
- } else {
- max_allowed_reconnects_reached();
- }
- // Double the timeout as long as the maximum allowed is larger
- if (connect_timeout_ < VSOMEIP_MAX_CONNECT_TIMEOUT)
- connect_timeout_ = (connect_timeout_ << 1);
- } else {
- {
- std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
- connect_timer_.cancel();
- }
- connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT; // TODO: use config variable
- reconnect_counter_ = 0;
- set_local_port();
- if (was_not_connected_) {
- was_not_connected_ = false;
- std::lock_guard<std::mutex> its_lock(mutex_);
- if (queue_.size() > 0) {
- send_queued();
- VSOMEIP_WARNING << __func__ << ": resume sending to: "
- << get_remote_information();
- }
- }
- if (state_ != cei_state_e::ESTABLISHED) {
- its_host->on_connect(this->shared_from_this());
- }
- receive();
- }
- }
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::wait_connect_cbk(
- boost::system::error_code const &_error) {
- if (!_error && !client_endpoint_impl<Protocol>::sending_blocked_) {
- connect();
- }
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::send_cbk(
- boost::system::error_code const &_error, std::size_t _bytes,
- message_buffer_ptr_t _sent_msg) {
- (void)_bytes;
- if (!_error) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- if (queue_.size() > 0) {
- queue_size_ -= queue_.front()->size();
- queue_.pop_front();
- send_queued();
- }
- } else if (_error == boost::asio::error::broken_pipe) {
- state_ = cei_state_e::CLOSED;
- bool stopping(false);
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- stopping = endpoint_impl<Protocol>::sending_blocked_;
- if (stopping) {
- queue_.clear();
- queue_size_ = 0;
- } else {
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
- its_service = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
- (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
- (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
- }
- VSOMEIP_WARNING << "cei::send_cbk received error: "
- << _error.message() << " (" << std::dec
- << _error.value() << ") " << get_remote_information()
- << " " << std::dec << queue_.size()
- << " " << std::dec << queue_size_ << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
- }
- }
- if (!stopping) {
- print_status();
- }
- was_not_connected_ = true;
- shutdown_and_close_socket(true);
- connect();
- } else if (_error == boost::asio::error::not_connected
- || _error == boost::asio::error::bad_descriptor
- || _error == boost::asio::error::no_permission) {
- state_ = cei_state_e::CLOSED;
- if (_error == boost::asio::error::no_permission) {
- VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
- << " (" << std::dec << _error.value() << ") "
- << get_remote_information();
- std::lock_guard<std::mutex> its_lock(mutex_);
- queue_.clear();
- queue_size_ = 0;
- }
- was_not_connected_ = true;
- shutdown_and_close_socket(true);
- connect();
- } else if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- shutdown_and_close_socket(false);
- } else if (_error == boost::system::errc::destination_address_required) {
- VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
- << " (" << std::dec << _error.value() << ") "
- << get_remote_information();
- was_not_connected_ = true;
- } else {
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
- its_service = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
- (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
- (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
- }
- VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
- << " (" << std::dec << _error.value() << ") "
- << get_remote_information() << " "
- << " " << std::dec << queue_.size()
- << " " << std::dec << queue_size_ << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
- print_status();
- }
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::flush_cbk(
- boost::system::error_code const &_error) {
- if (!_error) {
- (void) flush();
- }
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::shutdown_and_close_socket(bool _recreate_socket) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- shutdown_and_close_socket_unlocked(_recreate_socket);
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::shutdown_and_close_socket_unlocked(bool _recreate_socket) {
- local_port_ = 0;
- if (socket_->is_open()) {
+}
+
+template<typename Protocol>
+client_endpoint_impl<Protocol>::~client_endpoint_impl() {
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::is_client() const {
+ return true;
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::is_established() const {
+ return state_ == cei_state_e::ESTABLISHED;
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::is_established_or_connected() const {
+ return (state_ == cei_state_e::ESTABLISHED
+ || state_ == cei_state_e::CONNECTED);
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::set_established(bool _established) {
+ if (_established) {
+ if (state_ != cei_state_e::CONNECTING) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (socket_->is_open()) {
+ state_ = cei_state_e::ESTABLISHED;
+ } else {
+ state_ = cei_state_e::CLOSED;
+ }
+ }
+ } else {
+ state_ = cei_state_e::CLOSED;
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::set_connected(bool _connected) {
+ if (_connected) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (socket_->is_open()) {
+ state_ = cei_state_e::CONNECTED;
+ } else {
+ state_ = cei_state_e::CLOSED;
+ }
+ } else {
+ state_ = cei_state_e::CLOSED;
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::prepare_stop(
+ endpoint::prepare_stop_handler_t _handler, service_t _service) {
+ (void) _handler;
+ (void) _service;
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::stop() {
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ endpoint_impl<Protocol>::sending_blocked_ = true;
+ // delete unsent messages
+ queue_.clear();
+ queue_size_ = 0;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ boost::system::error_code ec;
+ connect_timer_.cancel(ec);
+ }
+ connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;
+ shutdown_and_close_socket(false);
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::send_to(
+ const std::shared_ptr<endpoint_definition> _target, const byte_t *_data,
+ uint32_t _size) {
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ VSOMEIP_ERROR << "Clients endpoints must not be used to "
+ << "send to explicitely specified targets";
+ return false;
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::send_error(
+ const std::shared_ptr<endpoint_definition> _target, const byte_t *_data,
+ uint32_t _size) {
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ VSOMEIP_ERROR << "Clients endpoints must not be used to "
+ << "send errors to explicitly specified targets";
+ return false;
+}
+
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::send(const uint8_t *_data, uint32_t _size) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ bool must_depart(false);
+ const bool queue_size_zero_on_entry(queue_.empty());
+#if 0
+ std::stringstream msg;
+ msg << "cei::send: ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+ VSOMEIP_DEBUG << msg.str();
+#endif
+
+ if (endpoint_impl<Protocol>::sending_blocked_ ||
+ !check_queue_limit(_data, _size)) {
+ return false;
+ }
+ switch (check_message_size(_data, _size)) {
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_WAS_SPLIT:
+ return true;
+ break;
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_TOO_BIG:
+ return false;
+ break;
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_OK:
+ default:
+ break;
+ }
+
+ // STEP 1: Determine elapsed time and update the departure time and cancel the departure timer
+ train_.update_departure_time_and_stop_departure();
+
+ // STEP 3: Get configured timings
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
+ std::chrono::nanoseconds its_debouncing(0), its_retention(0);
+ get_configured_times_from_endpoint(its_service, its_method,
+ &its_debouncing, &its_retention);
+
+ // STEP 4: Check if the passenger enters an empty train
+ const std::pair<service_t, method_t> its_identifier = std::make_pair(
+ its_service, its_method);
+ if (train_.passengers_.empty()) {
+ train_.departure_ = its_retention;
+ } else {
+ // STEP 4.1: Check whether the current train already contains the message
+ if (train_.passengers_.end() != train_.passengers_.find(its_identifier)) {
+ must_depart = true;
+ } else {
+ // STEP 5: Check whether the current message fits into the current train
+ if (train_.buffer_->size() + _size > endpoint_impl<Protocol>::max_message_size_) {
+ must_depart = true;
+ } else {
+ // STEP 6: Check debouncing time
+ if (its_debouncing > train_.minimal_max_retention_time_) {
+ // train's latest departure would already undershot new
+ // passenger's debounce time
+ must_depart = true;
+ } else {
+ if (its_debouncing > train_.departure_) {
+ // train departs earlier as the new passenger's debounce
+ // time allows
+ must_depart = true;
+ } else {
+ // STEP 7: Check maximum retention time
+ if (its_retention < train_.minimal_debounce_time_) {
+ // train's earliest departure would already exceed
+ // the new passenger's retention time.
+ must_depart = true;
+ } else {
+ if (its_retention < train_.departure_) {
+ train_.departure_ = its_retention;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // STEP 8: if necessary, send current buffer and create a new one
+ if (must_depart) {
+ // STEP 8.1: check if debounce time would be undershot here if the train
+ // departs. Block sending until train is allowed to depart.
+ wait_until_debounce_time_reached();
+ train_.passengers_.clear();
+ queue_train(queue_size_zero_on_entry);
+ train_.last_departure_ = std::chrono::steady_clock::now();
+ train_.departure_ = its_retention;
+ train_.minimal_debounce_time_ = std::chrono::nanoseconds::max();
+ train_.minimal_max_retention_time_ = std::chrono::nanoseconds::max();
+ }
+
+ // STEP 9: insert current message buffer
+ train_.buffer_->insert(train_.buffer_->end(), _data, _data + _size);
+ train_.passengers_.insert(its_identifier);
+ // STEP 9.1: update the trains minimal debounce time if necessary
+ if (its_debouncing < train_.minimal_debounce_time_) {
+ train_.minimal_debounce_time_ = its_debouncing;
+ }
+ // STEP 9.2: update the trains minimal maximum retention time if necessary
+ if (its_retention < train_.minimal_max_retention_time_) {
+ train_.minimal_max_retention_time_ = its_retention;
+ }
+
+ // STEP 10: restart timer with current departure time
+#ifndef _WIN32
+ train_.departure_timer_->expires_from_now(train_.departure_);
+#else
+ train_.departure_timer_->expires_from_now(
+ std::chrono::duration_cast<
+ std::chrono::steady_clock::duration>(train_.departure_));
+#endif
+ train_.departure_timer_->async_wait(
+ std::bind(&client_endpoint_impl<Protocol>::flush_cbk,
+ this->shared_from_this(), std::placeholders::_1));
+
+ return true;
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::send_segments(
+ const tp::tp_split_messages_t &_segments) {
+ if (_segments.size() == 0) {
+ return;
+ }
+ const bool queue_size_zero_on_entry(queue_.empty());
+
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*(_segments[0]))[VSOMEIP_SERVICE_POS_MIN],
+ (*(_segments[0]))[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*(_segments[0]))[VSOMEIP_METHOD_POS_MIN],
+ (*(_segments[0]))[VSOMEIP_METHOD_POS_MAX]);
+ std::chrono::nanoseconds its_debouncing(0), its_retention(0);
+ get_configured_times_from_endpoint(its_service, its_method,
+ &its_debouncing, &its_retention);
+ // update the trains minimal debounce time if necessary
+ if (its_debouncing < train_.minimal_debounce_time_) {
+ train_.minimal_debounce_time_ = its_debouncing;
+ }
+ // update the trains minimal maximum retention time if necessary
+ if (its_retention < train_.minimal_max_retention_time_) {
+ train_.minimal_max_retention_time_ = its_retention;
+ }
+
+ // We only need to respect the debouncing. There is no need to wait for further
+ // messages as we will send several now anyway.
+ if (!train_.passengers_.empty()) {
+ wait_until_debounce_time_reached();
+ train_.passengers_.clear();
+ queue_train(queue_size_zero_on_entry);
+ train_.last_departure_ = std::chrono::steady_clock::now();
+ train_.departure_ = its_retention;
+ train_.minimal_debounce_time_ = std::chrono::nanoseconds::max();
+ train_.minimal_max_retention_time_ = std::chrono::nanoseconds::max();
+ }
+ const bool queue_size_still_zero(queue_.empty());
+ for (const auto& s : _segments) {
+ queue_.emplace_back(s);
+ queue_size_ += s->size();
+ }
+
+ if (queue_size_still_zero && !queue_.empty()) { // no writing in progress
+ // respect minimal debounce time
+ wait_until_debounce_time_reached();
+ // ignore retention time and send immediately as the train is full anyway
+ send_queued();
+ }
+ train_.last_departure_ = std::chrono::steady_clock::now();
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::wait_until_debounce_time_reached() const {
+ const std::chrono::nanoseconds time_since_last_departure =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now() - train_.last_departure_);
+ if (time_since_last_departure < train_.minimal_debounce_time_) {
+ std::this_thread::sleep_for(
+ train_.minimal_debounce_time_ - time_since_last_departure);
+ }
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::send(const std::vector<byte_t>& _cmd_header,
+ const byte_t *_data, uint32_t _size) {
+ (void) _cmd_header;
+ (void) _data;
+ (void) _size;
+ return false;
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::flush() {
+ bool is_successful(true);
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (!train_.buffer_->empty()) {
+ queue_train(!queue_.size());
+ train_.last_departure_ = std::chrono::steady_clock::now();
+ train_.passengers_.clear();
+ train_.minimal_debounce_time_ = std::chrono::nanoseconds::max();
+ train_.minimal_max_retention_time_ = std::chrono::nanoseconds::max();
+ } else {
+ is_successful = false;
+ }
+
+ return is_successful;
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::connect_cbk(
+ boost::system::error_code const &_error) {
+ if (_error == boost::asio::error::operation_aborted
+ || endpoint_impl<Protocol>::sending_blocked_) {
+ // endpoint was stopped
+ shutdown_and_close_socket(false);
+ return;
+ }
+ std::shared_ptr<endpoint_host> its_host = this->endpoint_host_.lock();
+ if (its_host) {
+ if (_error && _error != boost::asio::error::already_connected) {
+ shutdown_and_close_socket(true);
+
+ if (state_ != cei_state_e::ESTABLISHED) {
+ state_ = cei_state_e::CLOSED;
+ its_host->on_disconnect(this->shared_from_this());
+ }
+ if (get_max_allowed_reconnects() == MAX_RECONNECTS_UNLIMITED ||
+ get_max_allowed_reconnects() >= ++reconnect_counter_) {
+ start_connect_timer();
+ } else {
+ max_allowed_reconnects_reached();
+ }
+ // Double the timeout as long as the maximum allowed is larger
+ if (connect_timeout_ < VSOMEIP_MAX_CONNECT_TIMEOUT)
+ connect_timeout_ = (connect_timeout_ << 1);
+ } else {
+ {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ connect_timer_.cancel();
+ }
+ connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT; // TODO: use config variable
+ reconnect_counter_ = 0;
+ set_local_port();
+ if (was_not_connected_) {
+ was_not_connected_ = false;
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (queue_.size() > 0) {
+ send_queued();
+ VSOMEIP_WARNING << __func__ << ": resume sending to: "
+ << get_remote_information();
+ }
+ }
+ if (state_ != cei_state_e::ESTABLISHED) {
+ its_host->on_connect(this->shared_from_this());
+ }
+ receive();
+ }
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::wait_connect_cbk(
+ boost::system::error_code const &_error) {
+ if (!_error && !client_endpoint_impl<Protocol>::sending_blocked_) {
+ connect();
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::send_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t& _sent_msg) {
+ (void)_bytes;
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (queue_.size() > 0) {
+ queue_size_ -= queue_.front()->size();
+ queue_.pop_front();
+ send_queued();
+ }
+ } else if (_error == boost::asio::error::broken_pipe) {
+ state_ = cei_state_e::CLOSED;
+ bool stopping(false);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ stopping = endpoint_impl<Protocol>::sending_blocked_;
+ if (stopping) {
+ queue_.clear();
+ queue_size_ = 0;
+ } else {
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_WARNING << "cei::send_cbk received error: "
+ << _error.message() << " (" << std::dec
+ << _error.value() << ") " << get_remote_information()
+ << " " << std::dec << queue_.size()
+ << " " << std::dec << queue_size_ << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ }
+ }
+ if (!stopping) {
+ print_status();
+ }
+ was_not_connected_ = true;
+ shutdown_and_close_socket(true);
+ connect();
+ } else if (_error == boost::asio::error::not_connected
+ || _error == boost::asio::error::bad_descriptor
+ || _error == boost::asio::error::no_permission) {
+ state_ = cei_state_e::CLOSED;
+ if (_error == boost::asio::error::no_permission) {
+ VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.clear();
+ queue_size_ = 0;
+ }
+ was_not_connected_ = true;
+ shutdown_and_close_socket(true);
+ connect();
+ } else if (_error == boost::asio::error::operation_aborted) {
+ VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message();
+ // endpoint was stopped
+ endpoint_impl<Protocol>::sending_blocked_ = true;
+ shutdown_and_close_socket(false);
+ } else if (_error == boost::system::errc::destination_address_required) {
+ VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ was_not_connected_ = true;
+ } else {
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_WARNING << "cei::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information() << " "
+ << " " << std::dec << queue_.size()
+ << " " << std::dec << queue_size_ << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ print_status();
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::flush_cbk(
+ boost::system::error_code const &_error) {
+ if (!_error) {
+ (void) flush();
+ }
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::shutdown_and_close_socket(bool _recreate_socket) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ shutdown_and_close_socket_unlocked(_recreate_socket);
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::shutdown_and_close_socket_unlocked(bool _recreate_socket) {
+ local_port_ = 0;
+ if (socket_->is_open()) {
#ifndef _WIN32
if (-1 == fcntl(socket_->native_handle(), F_GETFD)) {
- VSOMEIP_ERROR << "cei::shutdown_and_close_socket_unlocked: socket/handle closed already '" << std::string(std::strerror(errno))
- << "' (" << errno << ") " << get_remote_information();
+ VSOMEIP_ERROR << "cei::shutdown_and_close_socket_unlocked: socket/handle closed already '"
+ << std::string(std::strerror(errno))
+ << "' (" << errno << ") " << get_remote_information();
}
#endif
- boost::system::error_code its_error;
- socket_->shutdown(Protocol::socket::shutdown_both, its_error);
- socket_->close(its_error);
- }
- if (_recreate_socket) {
- socket_.reset(new socket_type(endpoint_impl<Protocol>::service_));
- }
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::get_remote_address(
- boost::asio::ip::address &_address) const {
- (void)_address;
- return false;
-}
-
-template<typename Protocol>
-std::uint16_t client_endpoint_impl<Protocol>::get_remote_port() const {
- return 0;
-}
-
-template<typename Protocol>
-std::uint16_t client_endpoint_impl<Protocol>::get_local_port() const {
- return local_port_;
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::start_connect_timer() {
- std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
- connect_timer_.expires_from_now(
- std::chrono::milliseconds(connect_timeout_));
- connect_timer_.async_wait(
- std::bind(&client_endpoint_impl<Protocol>::wait_connect_cbk,
- this->shared_from_this(), std::placeholders::_1));
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::check_message_size(std::uint32_t _size) const {
- if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
- && _size > endpoint_impl<Protocol>::max_message_size_) {
- VSOMEIP_ERROR << "cei::check_message_size: Dropping to big message ("
- << std::dec << _size << " Bytes). Maximum allowed message size is: "
- << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
- return false;
- }
- return true;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::check_packetizer_space(std::uint32_t _size) {
- if (packetizer_->size() + _size < packetizer_->size()) {
- VSOMEIP_ERROR << "Overflow in packetizer addition ~> abort sending!";
- return false;
- }
- if (packetizer_->size() + _size > endpoint_impl<Protocol>::max_message_size_
- && !packetizer_->empty()) {
- queue_.push_back(packetizer_);
- queue_size_ += packetizer_->size();
- packetizer_ = std::make_shared<message_buffer_t>();
- }
- return true;
-}
-
-template<typename Protocol>
-bool client_endpoint_impl<Protocol>::check_queue_limit(const uint8_t *_data, std::uint32_t _size) const {
- if (endpoint_impl<Protocol>::queue_limit_ != QUEUE_SIZE_UNLIMITED
- && queue_size_ + _size > endpoint_impl<Protocol>::queue_limit_) {
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (_size >= VSOMEIP_SESSION_POS_MAX) {
- // this will yield wrong IDs for local communication as the commands
- // are prepended to the actual payload
- // it will print:
- // (lowbyte service ID + highbyte methoid)
- // [(Command + lowerbyte sender's client ID).
- // highbyte sender's client ID + lowbyte command size.
- // lowbyte methodid + highbyte vsomeipd length]
- its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
- _data[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN],
- _data[VSOMEIP_SESSION_POS_MAX]);
- }
- VSOMEIP_ERROR << "cei::check_queue_limit: queue size limit (" << std::dec
- << endpoint_impl<Protocol>::queue_limit_
- << ") reached. Dropping message ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "] "
- << "queue_size: " << std::dec << queue_size_
- << " data size: " << std::dec << _size;
- return false;
- }
- return true;
-}
-
-template<typename Protocol>
-void client_endpoint_impl<Protocol>::send_or_start_flush_timer(
- bool _flush, bool _queue_size_zero_on_entry) {
- if (_flush) {
- flush_timer_.cancel();
- queue_.push_back(packetizer_);
- queue_size_ += packetizer_->size();
- packetizer_ = std::make_shared<message_buffer_t>();
-
- if (_queue_size_zero_on_entry && !queue_.empty()) { // no writing in progress
- send_queued();
- }
- } else {
- flush_timer_.expires_from_now(
- std::chrono::milliseconds(VSOMEIP_DEFAULT_FLUSH_TIMEOUT)); // TODO: use config variable
- flush_timer_.async_wait(
- std::bind(
- &client_endpoint_impl<Protocol>::flush_cbk,
- this->shared_from_this(),
- std::placeholders::_1
- )
- );
- }
-}
-
-// Instantiate template
-#ifndef _WIN32
-template class client_endpoint_impl<boost::asio::local::stream_protocol>;
-#endif
-template class client_endpoint_impl<boost::asio::ip::tcp>;
-template class client_endpoint_impl<boost::asio::ip::udp>;
-} // namespace vsomeip
-
+ boost::system::error_code its_error;
+ socket_->shutdown(Protocol::socket::shutdown_both, its_error);
+ socket_->close(its_error);
+ }
+ if (_recreate_socket) {
+ socket_.reset(new socket_type(endpoint_impl<Protocol>::service_));
+ }
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ (void)_address;
+ return false;
+}
+
+template<typename Protocol>
+std::uint16_t client_endpoint_impl<Protocol>::get_remote_port() const {
+ return 0;
+}
+
+template<typename Protocol>
+std::uint16_t client_endpoint_impl<Protocol>::get_local_port() const {
+ return local_port_;
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::start_connect_timer() {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ connect_timer_.expires_from_now(
+ std::chrono::milliseconds(connect_timeout_));
+ connect_timer_.async_wait(
+ std::bind(&client_endpoint_impl<Protocol>::wait_connect_cbk,
+ this->shared_from_this(), std::placeholders::_1));
+}
+
+template<typename Protocol>
+typename endpoint_impl<Protocol>::cms_ret_e client_endpoint_impl<Protocol>::check_message_size(
+ const std::uint8_t * const _data, std::uint32_t _size) {
+ typename endpoint_impl<Protocol>::cms_ret_e ret(endpoint_impl<Protocol>::cms_ret_e::MSG_OK);
+ if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ && _size > endpoint_impl<Protocol>::max_message_size_) {
+ if (endpoint_impl<Protocol>::is_supporting_someip_tp_ && _data != nullptr) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ if (tp_segmentation_enabled(its_service, its_method)) {
+ send_segments(tp::tp::tp_split_message(_data, _size));
+ return endpoint_impl<Protocol>::cms_ret_e::MSG_WAS_SPLIT;
+ }
+ }
+ VSOMEIP_ERROR << "cei::check_message_size: Dropping to big message ("
+ << std::dec << _size << " Bytes). Maximum allowed message size is: "
+ << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
+ ret = endpoint_impl<Protocol>::cms_ret_e::MSG_TOO_BIG;
+ }
+ return ret;
+}
+
+template<typename Protocol>
+bool client_endpoint_impl<Protocol>::check_queue_limit(const uint8_t *_data, std::uint32_t _size) const {
+ if (endpoint_impl<Protocol>::queue_limit_ != QUEUE_SIZE_UNLIMITED
+ && queue_size_ + _size > endpoint_impl<Protocol>::queue_limit_) {
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_size >= VSOMEIP_SESSION_POS_MAX) {
+ // this will yield wrong IDs for local communication as the commands
+ // are prepended to the actual payload
+ // it will print:
+ // (lowbyte service ID + highbyte methoid)
+ // [(Command + lowerbyte sender's client ID).
+ // highbyte sender's client ID + lowbyte command size.
+ // lowbyte methodid + highbyte vsomeip length]
+ its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN],
+ _data[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_ERROR << "cei::check_queue_limit: queue size limit (" << std::dec
+ << endpoint_impl<Protocol>::queue_limit_
+ << ") reached. Dropping message ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "] "
+ << "queue_size: " << std::dec << queue_size_
+ << " data size: " << std::dec << _size;
+ return false;
+ }
+ return true;
+}
+
+template<typename Protocol>
+void client_endpoint_impl<Protocol>::queue_train(bool _queue_size_zero_on_entry) {
+ queue_.push_back(train_.buffer_);
+ queue_size_ += train_.buffer_->size();
+ train_.buffer_ = std::make_shared<message_buffer_t>();
+ if (_queue_size_zero_on_entry && !queue_.empty()) { // no writing in progress
+ send_queued();
+ }
+}
+
+template<typename Protocol>
+size_t client_endpoint_impl<Protocol>::get_queue_size() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ return queue_size_;
+}
+
+// Instantiate template
+#ifndef _WIN32
+template class client_endpoint_impl<boost::asio::local::stream_protocol>;
+#endif
+template class client_endpoint_impl<boost::asio::ip::tcp>;
+template class client_endpoint_impl<boost::asio::ip::udp>;
+
+} // namespace vsomeip_v3
+
diff --git a/implementation/endpoints/src/credentials.cpp b/implementation/endpoints/src/credentials.cpp
index 411fd3f..3b9762c 100644
--- a/implementation/endpoints/src/credentials.cpp
+++ b/implementation/endpoints/src/credentials.cpp
@@ -9,10 +9,14 @@
#include "../include/credentials.hpp"
+#include <vsomeip/internal/logger.hpp>
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
+#endif
-namespace vsomeip {
+namespace vsomeip_v3 {
void credentials::activate_credentials(const int _fd) {
int optval = 1;
@@ -105,7 +109,7 @@ void credentials::send_credentials(const int _fd, client_t _client) {
}
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif
+#endif // #ifndef _WIN32
diff --git a/implementation/endpoints/src/endpoint_definition.cpp b/implementation/endpoints/src/endpoint_definition.cpp
index 9ab7218..9547836 100644
--- a/implementation/endpoints/src/endpoint_definition.cpp
+++ b/implementation/endpoints/src/endpoint_definition.cpp
@@ -7,7 +7,7 @@
#include "../include/endpoint_definition.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
std::map<std::tuple<service_t, instance_t, boost::asio::ip::address, uint16_t, bool>,
std::shared_ptr<endpoint_definition> > endpoint_definition::definitions_;
@@ -63,4 +63,4 @@ void endpoint_definition::set_remote_port(uint16_t _port) {
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/endpoint_impl.cpp b/implementation/endpoints/src/endpoint_impl.cpp
index 9cde3e9..4bb2fc0 100644
--- a/implementation/endpoints/src/endpoint_impl.cpp
+++ b/implementation/endpoints/src/endpoint_impl.cpp
@@ -1,153 +1,142 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <boost/asio/ip/tcp.hpp>
-#include <boost/asio/ip/udp.hpp>
-#include <boost/asio/ip/udp_ext.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-
-#include <vsomeip/constants.hpp>
-#include <vsomeip/defines.hpp>
-
-#include "../include/endpoint_host.hpp"
-#include "../include/endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
-
-namespace vsomeip {
-
-template<typename Protocol>
-endpoint_impl<Protocol>::endpoint_impl(
- std::shared_ptr<endpoint_host> _host,
- endpoint_type _local,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit)
- : service_(_io),
- host_(_host),
- is_supporting_magic_cookies_(false),
- has_enabled_magic_cookies_(false),
- max_message_size_(_max_message_size),
- use_count_(0),
- sending_blocked_(false),
- local_(_local),
- queue_limit_(_queue_limit) {
-}
-
-template<typename Protocol>
-endpoint_impl<Protocol>::~endpoint_impl() {
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::enable_magic_cookies() {
- has_enabled_magic_cookies_ = is_supporting_magic_cookies_;
-}
-
-template<typename Protocol>
-uint32_t endpoint_impl<Protocol>::find_magic_cookie(
- byte_t *_buffer, size_t _size) {
- bool is_found(false);
- uint32_t its_offset = 0xFFFFFFFF;
-
- uint8_t its_cookie_identifier, its_cookie_type;
-
- if (is_client()) {
- its_cookie_identifier =
- static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE);
- its_cookie_type =
- static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE_TYPE);
- } else {
- its_cookie_identifier =
- static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE);
- its_cookie_type =
- static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE_TYPE);
- }
-
- do {
- its_offset++; // --> first loop has "its_offset = 0"
- if (_size > its_offset + 16) {
- is_found = (_buffer[its_offset] == 0xFF
- && _buffer[its_offset + 1] == 0xFF
- && _buffer[its_offset + 2] == its_cookie_identifier
- && _buffer[its_offset + 3] == 0x00
- && _buffer[its_offset + 4] == 0x00
- && _buffer[its_offset + 5] == 0x00
- && _buffer[its_offset + 6] == 0x00
- && _buffer[its_offset + 7] == 0x08
- && _buffer[its_offset + 8] == 0xDE
- && _buffer[its_offset + 9] == 0xAD
- && _buffer[its_offset + 10] == 0xBE
- && _buffer[its_offset + 11] == 0xEF
- && _buffer[its_offset + 12] == 0x01
- && _buffer[its_offset + 13] == 0x01
- && _buffer[its_offset + 14] == its_cookie_type
- && _buffer[its_offset + 15] == 0x00);
- } else {
- break;
- }
-
- } while (!is_found);
-
- return (is_found ? its_offset : 0xFFFFFFFF);
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::join(const std::string &) {
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::leave(const std::string &) {
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::add_default_target(
- service_t, const std::string &, uint16_t) {
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::remove_default_target(service_t) {
-}
-
-template<typename Protocol>
-std::uint16_t endpoint_impl<Protocol>::get_local_port() const {
- return 0;
-}
-
-template<typename Protocol>
-bool endpoint_impl<Protocol>::is_reliable() const {
- return false;
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::increment_use_count() {
- use_count_++;
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::decrement_use_count() {
- if (use_count_ > 0)
- use_count_--;
-}
-
-template<typename Protocol>
-uint32_t endpoint_impl<Protocol>::get_use_count() {
- return use_count_;
-}
-
-template<typename Protocol>
-void endpoint_impl<Protocol>::register_error_handler(error_handler_t _error_handler) {
- std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
- this->error_handler_ = _error_handler;
-}
-
-
-// Instantiate template
-#ifndef _WIN32
-template class endpoint_impl<boost::asio::local::stream_protocol>;
-#endif
-template class endpoint_impl<boost::asio::ip::tcp>;
-template class endpoint_impl<boost::asio::ip::udp>;
-template class endpoint_impl<boost::asio::ip::udp_ext>;
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/ip/udp_ext.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include <boost/asio/local/stream_protocol_ext.hpp>
+
+#include <vsomeip/constants.hpp>
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/endpoint_host.hpp"
+#include "../../routing/include/routing_host.hpp"
+#include "../include/endpoint_impl.hpp"
+
+namespace vsomeip_v3 {
+
+template<typename Protocol>
+endpoint_impl<Protocol>::endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ boost::asio::io_service &_io,
+ std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration)
+ : service_(_io),
+ endpoint_host_(_endpoint_host),
+ routing_host_(_routing_host),
+ is_supporting_magic_cookies_(false),
+ has_enabled_magic_cookies_(false),
+ max_message_size_(_max_message_size),
+ use_count_(0),
+ sending_blocked_(false),
+ local_(_local),
+ queue_limit_(_queue_limit),
+ configuration_(_configuration),
+ is_supporting_someip_tp_(false) {
+}
+
+template<typename Protocol>
+endpoint_impl<Protocol>::~endpoint_impl() {
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::enable_magic_cookies() {
+ has_enabled_magic_cookies_ = is_supporting_magic_cookies_;
+}
+
+template<typename Protocol>
+uint32_t endpoint_impl<Protocol>::find_magic_cookie(
+ byte_t *_buffer, size_t _size) {
+ bool is_found(false);
+ uint32_t its_offset = 0xFFFFFFFF;
+
+ uint8_t its_cookie_identifier, its_cookie_type;
+
+ if (is_client()) {
+ its_cookie_identifier =
+ static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE);
+ its_cookie_type =
+ static_cast<uint8_t>(MAGIC_COOKIE_SERVICE_MESSAGE_TYPE);
+ } else {
+ its_cookie_identifier =
+ static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE);
+ its_cookie_type =
+ static_cast<uint8_t>(MAGIC_COOKIE_CLIENT_MESSAGE_TYPE);
+ }
+
+ do {
+ its_offset++; // --> first loop has "its_offset = 0"
+ if (_size > its_offset + 16) {
+ is_found = (_buffer[its_offset] == 0xFF
+ && _buffer[its_offset + 1] == 0xFF
+ && _buffer[its_offset + 2] == its_cookie_identifier
+ && _buffer[its_offset + 3] == 0x00
+ && _buffer[its_offset + 4] == 0x00
+ && _buffer[its_offset + 5] == 0x00
+ && _buffer[its_offset + 6] == 0x00
+ && _buffer[its_offset + 7] == 0x08
+ && _buffer[its_offset + 8] == 0xDE
+ && _buffer[its_offset + 9] == 0xAD
+ && _buffer[its_offset + 10] == 0xBE
+ && _buffer[its_offset + 11] == 0xEF
+ && _buffer[its_offset + 12] == 0x01
+ && _buffer[its_offset + 13] == 0x01
+ && _buffer[its_offset + 14] == its_cookie_type
+ && _buffer[its_offset + 15] == 0x00);
+ } else {
+ break;
+ }
+
+ } while (!is_found);
+
+ return (is_found ? its_offset : 0xFFFFFFFF);
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::add_default_target(
+ service_t, const std::string &, uint16_t) {
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::remove_default_target(service_t) {
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::increment_use_count() {
+ use_count_++;
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::decrement_use_count() {
+ if (use_count_ > 0)
+ use_count_--;
+}
+
+template<typename Protocol>
+uint32_t endpoint_impl<Protocol>::get_use_count() {
+ return use_count_;
+}
+
+template<typename Protocol>
+void endpoint_impl<Protocol>::register_error_handler(error_handler_t _error_handler) {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ this->error_handler_ = _error_handler;
+}
+
+// Instantiate template
+#ifndef _WIN32
+template class endpoint_impl<boost::asio::local::stream_protocol>;
+template class endpoint_impl<boost::asio::local::stream_protocol_ext>;
+#endif
+template class endpoint_impl<boost::asio::ip::tcp>;
+template class endpoint_impl<boost::asio::ip::udp>;
+template class endpoint_impl<boost::asio::ip::udp_ext>;
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/endpoint_manager_base.cpp b/implementation/endpoints/src/endpoint_manager_base.cpp
new file mode 100644
index 0000000..6c63e4f
--- /dev/null
+++ b/implementation/endpoints/src/endpoint_manager_base.cpp
@@ -0,0 +1,233 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/endpoint_manager_base.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+#include "../../utility/include/utility.hpp"
+#include "../../routing/include/routing_manager_base.hpp"
+#include "../../configuration/include/configuration.hpp"
+#include "../include/local_client_endpoint_impl.hpp"
+#include "../include/local_server_endpoint_impl.hpp"
+
+#include <iomanip>
+
+namespace vsomeip_v3 {
+
+endpoint_manager_base::endpoint_manager_base(routing_manager_base* const _rm,
+ boost::asio::io_service& _io,
+ const std::shared_ptr<configuration>& _configuration) :
+ rm_(_rm),
+ io_(_io),
+ configuration_(_configuration){
+
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::create_local(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ return create_local_unlocked(_client);
+}
+
+void endpoint_manager_base::remove_local(client_t _client) {
+ std::shared_ptr<endpoint> its_endpoint(find_local(_client));
+ if (its_endpoint) {
+ its_endpoint->register_error_handler(nullptr);
+ its_endpoint->stop();
+ VSOMEIP_INFO << "Client [" << std::hex << rm_->get_client() << "] is closing connection to ["
+ << std::hex << _client << "]";
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ local_endpoints_.erase(_client);
+ }
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::find_or_create_local(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ std::shared_ptr<endpoint> its_endpoint(find_local_unlocked(_client));
+ if (!its_endpoint) {
+ its_endpoint = create_local_unlocked(_client);
+ its_endpoint->start();
+ }
+ return (its_endpoint);
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::find_local(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ return find_local_unlocked(_client);
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::find_local(service_t _service,
+ instance_t _instance) {
+ return find_local(rm_->find_local_client(_service, _instance));
+}
+
+
+std::unordered_set<client_t> endpoint_manager_base::get_connected_clients() const {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ std::unordered_set<client_t> clients;
+ for (const auto& its_client : local_endpoints_) {
+ clients.insert(its_client.first);
+ }
+ return clients;
+}
+
+std::shared_ptr<local_server_endpoint_impl> endpoint_manager_base::create_local_server(
+ const std::shared_ptr<routing_host>& _routing_host) {
+ std::shared_ptr<local_server_endpoint_impl> its_server_endpoint;
+ std::stringstream its_path;
+ its_path << utility::get_base_path(configuration_) << std::hex << rm_->get_client();
+ const client_t its_client = rm_->get_client();
+#ifdef _WIN32
+ ::_unlink(its_path.str().c_str());
+ int port = VSOMEIP_INTERNAL_BASE_PORT + its_client;
+#else
+ if (-1 == ::unlink(its_path.str().c_str()) && errno != ENOENT) {
+ VSOMEIP_ERROR << "endpoint_manager_base::init_receiver unlink failed ("
+ << its_path.str() << "): "<< std::strerror(errno);
+ }
+#endif
+ try {
+ its_server_endpoint = std::make_shared<local_server_endpoint_impl>(
+ shared_from_this(), _routing_host,
+#ifdef _WIN32
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
+#else
+ boost::asio::local::stream_protocol_ext::endpoint(its_path.str()),
+#endif
+ io_,
+ configuration_, false);
+#ifdef _WIN32
+ VSOMEIP_INFO << "Listening at " << port;
+#else
+ VSOMEIP_INFO << "Listening at " << its_path.str();
+#endif
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "Local server endpoint creation failed. Client ID: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_client
+#ifdef _WIN32
+ << " Port: " << std::dec << port
+#else
+ << " Path: " << its_path.str()
+#endif
+ << " Reason: " << e.what();
+ }
+ return its_server_endpoint;
+}
+
+void endpoint_manager_base::on_connect(std::shared_ptr<endpoint> _endpoint) {
+ rm_->on_connect(_endpoint);
+}
+
+void endpoint_manager_base::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
+ rm_->on_disconnect(_endpoint);
+}
+
+void endpoint_manager_base::on_error(
+ const byte_t *_data, length_t _length, endpoint* const _receiver,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port) {
+ (void)_data;
+ (void)_length;
+ (void)_receiver;
+ (void)_remote_address;
+ (void)_remote_port;
+ // intentionally left blank
+}
+
+void endpoint_manager_base::release_port(uint16_t _port, bool _reliable) {
+ (void)_port;
+ (void)_reliable;
+ // intentionally left blank
+}
+
+client_t endpoint_manager_base::get_client() const {
+ return rm_->get_client();
+}
+
+std::map<client_t, std::shared_ptr<endpoint>>
+endpoint_manager_base::get_local_endpoints() const {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ return local_endpoints_;
+}
+
+void
+endpoint_manager_base::log_client_states() const {
+ std::vector<std::pair<client_t, size_t> > its_client_queue_sizes;
+ std::stringstream its_log;
+
+ {
+ std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
+ for (const auto e : local_endpoints_) {
+ size_t its_queue_size = e.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE) {
+ its_client_queue_sizes.push_back(
+ std::make_pair(e.first, its_queue_size));
+ }
+ }
+ }
+
+ std::sort(its_client_queue_sizes.begin(), its_client_queue_sizes.end(),
+ [](const std::pair<client_t, size_t> &_a,
+ const std::pair<client_t, size_t> &_b) {
+ return (_a.second > _b.second);
+ });
+
+ size_t its_max(std::min(size_t(10), its_client_queue_sizes.size()));
+ for (size_t i = 0; i < its_max; i++) {
+ its_log << std::hex << std::setw(4) << std::setfill('0')
+ << its_client_queue_sizes[i].first << ":"
+ << std::dec << its_client_queue_sizes[i].second;
+ if (i < its_max-1)
+ its_log << ", ";
+ }
+
+ if (its_log.str().length() > 0)
+ VSOMEIP_WARNING << "ICQ: [" << its_log.str() << "]";
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::create_local_unlocked(client_t _client) {
+ std::stringstream its_path;
+ its_path << utility::get_base_path(configuration_) << std::hex << _client;
+ std::shared_ptr<local_client_endpoint_impl> its_endpoint;
+
+#ifdef _WIN32
+ boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1");
+ int port = VSOMEIP_INTERNAL_BASE_PORT + _client;
+ VSOMEIP_INFO << "Connecting to ["
+ << std::hex << _client << "] at " << port;
+#else
+ VSOMEIP_INFO << "Client [" << std::hex << rm_->get_client() << "] is connecting to ["
+ << std::hex << _client << "] at " << its_path.str();
+#endif
+ its_endpoint = std::make_shared<local_client_endpoint_impl>(
+ shared_from_this(), rm_->shared_from_this(),
+#ifdef _WIN32
+ boost::asio::ip::tcp::endpoint(address, port)
+#else
+ boost::asio::local::stream_protocol::endpoint(its_path.str())
+#endif
+ , io_, configuration_);
+
+ // Messages sent to the VSOMEIP_ROUTING_CLIENT are meant to be routed to
+ // external devices. Therefore, its local endpoint must not be found by
+ // a call to find_local. Thus it must not be inserted to the list of local
+ // clients.
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ local_endpoints_[_client] = its_endpoint;
+ }
+ rm_->register_client_error_handler(_client, its_endpoint);
+
+ return its_endpoint;
+}
+
+std::shared_ptr<endpoint> endpoint_manager_base::find_local_unlocked(client_t _client) {
+ std::shared_ptr<endpoint> its_endpoint;
+ auto found_endpoint = local_endpoints_.find(_client);
+ if (found_endpoint != local_endpoints_.end()) {
+ its_endpoint = found_endpoint->second;
+ }
+ return (its_endpoint);
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/endpoint_manager_impl.cpp b/implementation/endpoints/src/endpoint_manager_impl.cpp
new file mode 100644
index 0000000..6d37509
--- /dev/null
+++ b/implementation/endpoints/src/endpoint_manager_impl.cpp
@@ -0,0 +1,1034 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/endpoint_manager_impl.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/udp_client_endpoint_impl.hpp"
+#include "../include/udp_server_endpoint_impl.hpp"
+#include "../include/tcp_client_endpoint_impl.hpp"
+#include "../include/tcp_server_endpoint_impl.hpp"
+#include "../include/local_server_endpoint_impl.hpp"
+#include "../include/virtual_server_endpoint_impl.hpp"
+#include "../include/endpoint_definition.hpp"
+#include "../../routing/include/routing_manager_base.hpp"
+#include "../../routing/include/routing_manager_impl.hpp"
+#include "../../routing/include/routing_host.hpp"
+#include "../../security/include/security.hpp"
+#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+
+#include <forward_list>
+#include <iomanip>
+
+#ifndef WITHOUT_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+#define SD_LISTEN_FDS_START 3
+
+namespace vsomeip_v3 {
+
+endpoint_manager_impl::endpoint_manager_impl(
+ routing_manager_base* const _rm, boost::asio::io_service& _io,
+ const std::shared_ptr<configuration>& _configuration) :
+ endpoint_manager_base(_rm, _io, _configuration) {
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::find_or_create_remote_client(
+ service_t _service, instance_t _instance, bool _reliable, client_t _client) {
+ std::shared_ptr<endpoint> its_endpoint;
+ bool start_endpoint(false);
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ its_endpoint = find_remote_client(_service, _instance, _reliable, _client);
+ if (!its_endpoint) {
+ its_endpoint = create_remote_client(_service, _instance, _reliable, _client);
+ start_endpoint = true;
+ }
+ }
+ if (start_endpoint && its_endpoint
+ && configuration_->is_someip(_service, _instance)) {
+ its_endpoint->start();
+ }
+ return its_endpoint;
+}
+
+void endpoint_manager_impl::find_or_create_remote_client(
+ service_t _service, instance_t _instance,
+ client_t _client) {
+ std::shared_ptr<endpoint> its_reliable_endpoint;
+ std::shared_ptr<endpoint> its_unreliable_endpoint;
+ bool start_reliable_endpoint(false);
+ bool start_unreliable_endpoint(false);
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ its_reliable_endpoint = find_remote_client(_service, _instance, true, _client);
+ if (!its_reliable_endpoint) {
+ its_reliable_endpoint = create_remote_client(_service, _instance, true, _client);
+ start_reliable_endpoint = true;
+ }
+ its_unreliable_endpoint = find_remote_client(_service, _instance, false, _client);
+ if (!its_unreliable_endpoint) {
+ its_unreliable_endpoint = create_remote_client(_service, _instance, false, _client);
+ start_unreliable_endpoint = true;
+ }
+ }
+ const bool is_someip = configuration_->is_someip(_service, _instance);
+ if (start_reliable_endpoint && its_reliable_endpoint && is_someip) {
+ its_reliable_endpoint->start();
+ }
+ if (start_unreliable_endpoint && its_unreliable_endpoint && is_someip) {
+ its_unreliable_endpoint->start();
+ }
+}
+
+void endpoint_manager_impl::is_remote_service_known(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor,
+ const boost::asio::ip::address &_reliable_address,
+ uint16_t _reliable_port, bool* _reliable_known,
+ const boost::asio::ip::address &_unreliable_address,
+ uint16_t _unreliable_port, bool* _unreliable_known) const {
+
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ auto found_service = remote_service_info_.find(_service);
+ if (found_service != remote_service_info_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ std::shared_ptr<endpoint_definition> its_definition;
+ if (_reliable_port != ILLEGAL_PORT) {
+ auto found_reliable = found_instance->second.find(true);
+ if (found_reliable != found_instance->second.end()) {
+ its_definition = found_reliable->second;
+ if (its_definition->get_address() == _reliable_address
+ && its_definition->get_port() == _reliable_port) {
+ *_reliable_known = true;
+ } else {
+ VSOMEIP_WARNING << "Reliable service endpoint has changed: ["
+ << std::hex << std::setfill('0') << std::setw(4) << _service << "."
+ << std::hex << std::setfill('0') << std::setw(4) << _instance << "."
+ << std::dec << static_cast<std::uint32_t>(_major) << "."
+ << std::dec << _minor << "] old: "
+ << its_definition->get_address().to_string() << ":"
+ << its_definition->get_port() << " new: "
+ << _reliable_address.to_string() << ":"
+ << _reliable_port;
+ }
+ }
+ }
+ if (_unreliable_port != ILLEGAL_PORT) {
+ auto found_unreliable = found_instance->second.find(false);
+ if (found_unreliable != found_instance->second.end()) {
+ its_definition = found_unreliable->second;
+ if (its_definition->get_address() == _unreliable_address
+ && its_definition->get_port() == _unreliable_port) {
+ *_unreliable_known = true;
+ } else {
+ VSOMEIP_WARNING << "Unreliable service endpoint has changed: ["
+ << std::hex << std::setfill('0') << std::setw(4) << _service << "."
+ << std::hex << std::setfill('0') << std::setw(4) << _instance << "."
+ << std::dec << static_cast<std::uint32_t>(_major) << "."
+ << std::dec << _minor << "] old: "
+ << its_definition->get_address().to_string() << ":"
+ << its_definition->get_port() << " new: "
+ << _unreliable_address.to_string() << ":"
+ << _unreliable_port;
+ }
+ }
+ }
+ }
+ }
+}
+
+void endpoint_manager_impl::add_remote_service_info(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<endpoint_definition>& _ep_definition) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ remote_service_info_[_service][_instance][_ep_definition->is_reliable()] =
+ _ep_definition;
+}
+
+void endpoint_manager_impl::add_remote_service_info(
+ service_t _service, instance_t _instance,
+ const std::shared_ptr<endpoint_definition>& _ep_definition_reliable,
+ const std::shared_ptr<endpoint_definition>& _ep_definition_unreliable) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ remote_service_info_[_service][_instance][true] = _ep_definition_reliable;
+ remote_service_info_[_service][_instance][false] = _ep_definition_unreliable;
+}
+
+void endpoint_manager_impl::clear_remote_service_info(service_t _service,
+ instance_t _instance,
+ bool _reliable) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ const auto found_service = remote_service_info_.find(_service);
+ if (found_service != remote_service_info_.end()) {
+ const auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ if (found_instance->second.erase(_reliable)) {
+ if (!found_instance->second.size()) {
+ found_service->second.erase(found_instance);
+ if (!found_service->second.size()) {
+ remote_service_info_.erase(found_service);
+ }
+ }
+ }
+ }
+ }
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::create_server_endpoint(
+ uint16_t _port, bool _reliable, bool _start) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ std::shared_ptr<endpoint> its_endpoint;
+ try {
+ boost::asio::ip::address its_unicast = configuration_->get_unicast_address();
+ const std::string its_unicast_str = its_unicast.to_string();
+ if (_start) {
+ if (_reliable) {
+ its_endpoint = std::make_shared<tcp_server_endpoint_impl>(
+ shared_from_this(),
+ rm_->shared_from_this(),
+ boost::asio::ip::tcp::endpoint(its_unicast, _port),
+ io_,
+ configuration_);
+ if (configuration_->has_enabled_magic_cookies(
+ its_unicast_str, _port) ||
+ configuration_->has_enabled_magic_cookies(
+ "local", _port)) {
+ its_endpoint->enable_magic_cookies();
+ }
+ } else {
+ its_endpoint = std::make_shared<udp_server_endpoint_impl>(
+ shared_from_this(),
+ rm_->shared_from_this(),
+ boost::asio::ip::udp::endpoint(its_unicast, _port),
+ io_,
+ configuration_);
+ }
+
+ } else {
+ its_endpoint = std::make_shared<virtual_server_endpoint_impl>(
+ its_unicast_str, _port, _reliable, io_);
+ }
+
+ if (its_endpoint) {
+ server_endpoints_[_port][_reliable] = its_endpoint;
+ its_endpoint->start();
+ }
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__
+ << " Server endpoint creation failed."
+ << " Reason: "<< e.what()
+ << " Port: " << _port
+ << " (" << _reliable << ")";
+ }
+
+ return (its_endpoint);
+}
+
+
+std::shared_ptr<endpoint> endpoint_manager_impl::find_server_endpoint(
+ uint16_t _port, bool _reliable) const {
+ std::shared_ptr<endpoint> its_endpoint;
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ auto found_port = server_endpoints_.find(_port);
+ if (found_port != server_endpoints_.end()) {
+ auto found_endpoint = found_port->second.find(_reliable);
+ if (found_endpoint != found_port->second.end()) {
+ its_endpoint = found_endpoint->second;
+ }
+ }
+ return (its_endpoint);
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::find_or_create_server_endpoint(
+ uint16_t _port, bool _reliable, bool _start, service_t _service,
+ instance_t _instance) {
+ std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port,
+ _reliable);
+ if (!its_endpoint) {
+ its_endpoint = create_server_endpoint(_port, _reliable, _start);
+ }
+ if (its_endpoint) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ service_instances_[_service][its_endpoint.get()] = _instance;
+ its_endpoint->increment_use_count();
+ }
+ return (its_endpoint);
+}
+
+bool endpoint_manager_impl::remove_server_endpoint(uint16_t _port, bool _reliable) {
+ bool ret = false;
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ auto found_port = server_endpoints_.find(_port);
+ if (found_port != server_endpoints_.end()) {
+ auto found_reliable = found_port->second.find(_reliable);
+ if (found_reliable != found_port->second.end()) {
+ if (found_reliable->second->get_use_count() == 0 &&
+ found_port->second.erase(_reliable)) {
+ ret = true;
+ if (found_port->second.empty()) {
+ server_endpoints_.erase(found_port);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+void endpoint_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance,
+ bool _reliable) {
+ std::shared_ptr<endpoint> endpoint_to_delete;
+ bool other_services_reachable_through_endpoint(false);
+ std::vector<std::shared_ptr<endpoint>> its_specific_endpoints;
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ // Clear client endpoints for remote services (generic and specific ones)
+ if (remote_services_.find(_service) != remote_services_.end()) {
+ if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
+ auto endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable];
+ if (endpoint) {
+ service_instances_[_service].erase(endpoint.get());
+ endpoint_to_delete = endpoint;
+ }
+ remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].erase(_reliable);
+ auto found_endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].find(
+ !_reliable);
+ if (found_endpoint == remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].end()) {
+ remote_services_[_service][_instance].erase(VSOMEIP_ROUTING_CLIENT);
+ }
+ }
+ }
+ if (remote_services_.find(_service) != remote_services_.end()) {
+ if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
+ if (!remote_services_[_service][_instance].size()) {
+ remote_services_[_service].erase(_instance);
+ if (0 >= remote_services_[_service].size()) {
+ remote_services_.erase(_service);
+ }
+ }
+ }
+ }
+
+ if (!service_instances_[_service].size()) {
+ service_instances_.erase(_service);
+ }
+
+ // Only stop and delete the endpoint if none of the services
+ // reachable through it is online anymore.
+ if (endpoint_to_delete) {
+ for (const auto& service : remote_services_) {
+ for (const auto& instance : service.second) {
+ const auto& client = instance.second.find(VSOMEIP_ROUTING_CLIENT);
+ if (client != instance.second.end()) {
+ for (const auto& reliable : client->second) {
+ if (reliable.second == endpoint_to_delete) {
+ other_services_reachable_through_endpoint = true;
+ break;
+ }
+ }
+ }
+ if (other_services_reachable_through_endpoint) { break; }
+ }
+ if (other_services_reachable_through_endpoint) { break; }
+ }
+
+ if (!other_services_reachable_through_endpoint) {
+ std::uint16_t its_port(0);
+ boost::asio::ip::address its_address;
+ if (_reliable) {
+ std::shared_ptr<tcp_client_endpoint_impl> ep =
+ std::dynamic_pointer_cast<tcp_client_endpoint_impl>(endpoint_to_delete);
+ if (ep) {
+ its_port = ep->get_remote_port();
+ ep->get_remote_address(its_address);
+ }
+ } else {
+ std::shared_ptr<udp_client_endpoint_impl> ep =
+ std::dynamic_pointer_cast<udp_client_endpoint_impl>(endpoint_to_delete);
+ if (ep) {
+ its_port = ep->get_remote_port();
+ ep->get_remote_address(its_address);
+ }
+ }
+ const auto found_ip = client_endpoints_by_ip_.find(its_address);
+ if (found_ip != client_endpoints_by_ip_.end()) {
+ const auto found_port = found_ip->second.find(its_port);
+ if (found_port != found_ip->second.end()) {
+ const auto found_reliable = found_port->second.find(_reliable);
+ if (found_reliable != found_port->second.end()) {
+ if (found_reliable->second == endpoint_to_delete) {
+ found_port->second.erase(_reliable);
+ // delete if necessary
+ if (!found_port->second.size()) {
+ found_ip->second.erase(found_port);
+ if (!found_ip->second.size()) {
+ client_endpoints_by_ip_.erase(found_ip);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!other_services_reachable_through_endpoint && endpoint_to_delete) {
+ endpoint_to_delete->stop();
+ }
+ for (const auto &specific_endpoint : its_specific_endpoints) {
+ specific_endpoint->stop();
+ }
+}
+
+void endpoint_manager_impl::find_or_create_multicast_endpoint(
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_address, uint16_t _port) {
+ bool multicast_known(false);
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ const auto found_service = multicast_info.find(_service);
+ if (found_service != multicast_info.end()) {
+ const auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ const auto& endpoint_def = found_instance->second;
+ if (endpoint_def->get_address() == _address &&
+ endpoint_def->get_port() == _port) {
+ // Multicast info and endpoint already created before
+ // This can happen when more than one client subscribe on the same instance!
+ multicast_known = true;
+ }
+ }
+ }
+ if (!multicast_known) {
+ // Save multicast info to be able to delete the endpoint
+ // as soon as the instance stops offering its service
+ std::shared_ptr<endpoint_definition> endpoint_def =
+ endpoint_definition::get(_address, _port, false, _service, _instance);
+ multicast_info[_service][_instance] = endpoint_def;
+ }
+ }
+ const bool is_someip = configuration_->is_someip(_service, _instance);
+
+ // Create multicast endpoint & join multicase group
+ std::shared_ptr<endpoint> its_endpoint = find_or_create_server_endpoint(
+ _port, false, is_someip, _service, _instance);
+ if (its_endpoint) {
+ if (!multicast_known) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ service_instances_[_service][its_endpoint.get()] = _instance;
+ }
+ dynamic_cast<udp_server_endpoint_impl*>(its_endpoint.get())->join(
+ _address.to_string());
+ } else {
+ VSOMEIP_ERROR <<"Could not find/create multicast endpoint!";
+ }
+}
+
+void endpoint_manager_impl::clear_multicast_endpoints(service_t _service, instance_t _instance) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ // Clear multicast info and endpoint and multicast instance (remote service)
+ if (multicast_info.find(_service) != multicast_info.end()) {
+ if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) {
+ std::string address = multicast_info[_service][_instance]->get_address().to_string();
+ uint16_t port = multicast_info[_service][_instance]->get_port();
+ std::shared_ptr<endpoint> multicast_endpoint;
+ auto found_port = server_endpoints_.find(port);
+ if (found_port != server_endpoints_.end()) {
+ auto found_unreliable = found_port->second.find(false);
+ if (found_unreliable != found_port->second.end()) {
+ multicast_endpoint = found_unreliable->second;
+ dynamic_cast<udp_server_endpoint_impl*>(
+ multicast_endpoint.get())->leave(address);
+ multicast_endpoint->stop();
+ server_endpoints_[port].erase(false);
+ }
+ if (found_port->second.find(true) == found_port->second.end()) {
+ server_endpoints_.erase(port);
+ }
+ }
+ multicast_info[_service].erase(_instance);
+ if (0 >= multicast_info[_service].size()) {
+ multicast_info.erase(_service);
+ }
+ // Clear service_instances_ for multicast endpoint
+ remove_instance(_service, multicast_endpoint.get());
+ }
+ }
+}
+
+bool endpoint_manager_impl::supports_selective(service_t _service,
+ instance_t _instance) const {
+ bool supports_selective(false);
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ const auto its_service = remote_service_info_.find(_service);
+ if (its_service != remote_service_info_.end()) {
+ const auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ for (const auto& its_reliable : its_instance->second) {
+ supports_selective |= configuration_->
+ supports_selective_broadcasts(
+ its_reliable.second->get_address());
+ }
+ }
+ }
+ return supports_selective;
+}
+
+void endpoint_manager_impl::print_status() const {
+ // local client endpoints
+ {
+ std::map<client_t, std::shared_ptr<endpoint>> lces = get_local_endpoints();
+ VSOMEIP_INFO << "status local client endpoints: " << std::dec << lces.size();
+ for (const auto& lce : lces) {
+ lce.second->print_status();
+ }
+ }
+
+ // udp and tcp client endpoints
+ {
+ client_endpoints_by_ip_t client_endpoints_by_ip;
+ remote_services_t remote_services;
+ server_endpoints_t server_endpoints;
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ client_endpoints_by_ip = client_endpoints_by_ip_;
+ remote_services = remote_services_;
+ server_endpoints = server_endpoints_;
+ }
+ VSOMEIP_INFO << "status start remote client endpoints:";
+ std::uint32_t num_remote_client_endpoints(0);
+ // normal endpoints
+ for (const auto &a : client_endpoints_by_ip) {
+ for (const auto& p : a.second) {
+ for (const auto& ru : p.second) {
+ ru.second->print_status();
+ num_remote_client_endpoints++;
+ }
+ }
+ }
+ VSOMEIP_INFO << "status end remote client endpoints: " << std::dec
+ << num_remote_client_endpoints;
+
+ // selective client endpoints
+ VSOMEIP_INFO << "status start selective remote client endpoints:";
+ std::uint32_t num_remote_selectiv_client_endpoints(0);
+ for (const auto& s : remote_services) {
+ for (const auto& i : s.second) {
+ for (const auto& c : i.second) {
+ if (c.first != VSOMEIP_ROUTING_CLIENT) {
+ for (const auto& ur : c.second) {
+ ur.second->print_status();
+ num_remote_selectiv_client_endpoints++;
+ }
+ }
+ }
+ }
+ }
+ VSOMEIP_INFO << "status end selective remote client endpoints: "
+ << std::dec << num_remote_selectiv_client_endpoints;
+
+ VSOMEIP_INFO << "status start server endpoints:";
+ std::uint32_t num_server_endpoints(1);
+ // local server endpoints
+ static_cast<routing_manager_impl*>(rm_)->print_stub_status();
+
+ // server endpoints
+ for (const auto& p : server_endpoints) {
+ for (const auto& ru : p.second ) {
+ ru.second->print_status();
+ num_server_endpoints++;
+ }
+ }
+ VSOMEIP_INFO << "status end server endpoints:"
+ << std::dec << num_server_endpoints;
+ }
+}
+
+std::shared_ptr<local_server_endpoint_impl>
+endpoint_manager_impl::create_local_server(
+ bool* _is_socket_activated,
+ const std::shared_ptr<routing_host>& _routing_host) {
+ std::shared_ptr<local_server_endpoint_impl> its_endpoint;
+ std::stringstream its_endpoint_path_ss;
+ its_endpoint_path_ss << utility::get_base_path(configuration_) << VSOMEIP_ROUTING_CLIENT;
+ const std::string its_endpoint_path = its_endpoint_path_ss.str();
+ client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
+ if (security::get()->is_enabled() && get_client() != routing_host_id) {
+ VSOMEIP_ERROR << "endpoint_manager_impl::create_local_server: "
+ << std::hex << "Client " << get_client() << " isn't allowed"
+ << " to create the routing endpoint as its not configured as the routing master!";
+ return its_endpoint;
+ }
+ uint32_t native_socket_fd = 0;
+ int32_t num_fd = 0;
+#ifndef WITHOUT_SYSTEMD
+ num_fd = sd_listen_fds(0);
+#endif
+ if (num_fd > 1) {
+ VSOMEIP_ERROR << "Too many file descriptors received by systemd socket activation! num_fd: " << num_fd;
+ } else if (num_fd == 1) {
+ native_socket_fd = SD_LISTEN_FDS_START + 0;
+ VSOMEIP_INFO << "Using native socket created by systemd socket activation! fd: " << native_socket_fd;
+ #ifndef _WIN32
+ try {
+ its_endpoint =
+ std::make_shared <local_server_endpoint_impl>(
+ shared_from_this(), _routing_host,
+ boost::asio::local::stream_protocol_ext::endpoint(its_endpoint_path),
+ io_,
+ native_socket_fd,
+ configuration_, true);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "Server endpoint creation failed. Client ID: "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ #endif
+ *_is_socket_activated = true;
+ } else {
+ #if _WIN32
+ ::_unlink(its_endpoint_path.c_str());
+ int port = VSOMEIP_INTERNAL_BASE_PORT;
+ VSOMEIP_INFO << "Routing endpoint at " << port;
+ #else
+ if (-1 == ::unlink(its_endpoint_path.c_str()) && errno != ENOENT) {
+ VSOMEIP_ERROR << "endpoint_manager_impl::create_local_server unlink failed ("
+ << its_endpoint_path << "): "<< std::strerror(errno);
+ }
+ VSOMEIP_INFO << __func__ << " Routing endpoint at " << its_endpoint_path;
+ #endif
+
+ try {
+ its_endpoint =
+ std::make_shared <local_server_endpoint_impl>(
+ shared_from_this(), _routing_host,
+ #ifdef _WIN32
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
+ #else
+ boost::asio::local::stream_protocol_ext::endpoint(its_endpoint_path),
+ #endif
+ io_,
+ configuration_, true);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "Server endpoint creation failed. Client ID: "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
+ }
+ *_is_socket_activated = false;
+ }
+ return its_endpoint;
+}
+
+instance_t endpoint_manager_impl::find_instance(
+ service_t _service, endpoint* const _endpoint) const {
+ instance_t its_instance(0xFFFF);
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ auto found_service = service_instances_.find(_service);
+ if (found_service != service_instances_.end()) {
+ auto found_endpoint = found_service->second.find(_endpoint);
+ if (found_endpoint != found_service->second.end()) {
+ its_instance = found_endpoint->second;
+ }
+ }
+ return its_instance;
+}
+
+bool endpoint_manager_impl::remove_instance(service_t _service,
+ endpoint* const _endpoint) {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ auto found_service = service_instances_.find(_service);
+ if (found_service != service_instances_.end()) {
+ if (found_service->second.erase(_endpoint)) {
+ if (!found_service->second.size()) {
+ service_instances_.erase(found_service);
+ }
+ }
+ }
+ _endpoint->decrement_use_count();
+ return (_endpoint->get_use_count() == 0);
+}
+
+void endpoint_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
+ // Is called when endpoint->connect succeeded!
+ struct service_info {
+ service_t service_id_;
+ instance_t instance_id_;
+ major_version_t major_;
+ minor_version_t minor_;
+ std::shared_ptr<endpoint> endpoint_;
+ bool service_is_unreliable_only_;
+ };
+
+ // Set to state CONNECTED as connection is not yet fully established in remote side POV
+ // but endpoint is ready to send / receive. Set to ESTABLISHED after timer expires
+ // to prevent inserting subscriptions twice or send out subscription before remote side
+ // is finished with TCP 3 way handshake
+ _endpoint->set_connected(true);
+
+ std::forward_list<struct service_info> services_to_report_;
+ {
+ const bool endpoint_is_reliable = _endpoint->is_reliable();
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ for (auto &its_service : remote_services_) {
+ for (auto &its_instance : its_service.second) {
+ for (auto &its_client : its_instance.second) {
+ if (its_client.first == VSOMEIP_ROUTING_CLIENT ||
+ its_client.first == get_client()) {
+ auto found_endpoint = its_client.second.find(endpoint_is_reliable);
+ if (found_endpoint != its_client.second.end()) {
+ if (found_endpoint->second == _endpoint) {
+ std::shared_ptr<serviceinfo> its_info(
+ rm_->find_service(its_service.first,
+ its_instance.first));
+ if (!its_info) {
+ _endpoint->set_established(true);
+ return;
+ }
+ // only report services offered via TCP+UDP when both
+ // endpoints are connected
+ const auto its_other_endpoint = its_info->get_endpoint(
+ !endpoint_is_reliable);
+
+ if (!its_other_endpoint || (its_other_endpoint
+ && its_other_endpoint->is_established_or_connected())) {
+ services_to_report_.push_front(
+ { its_service.first,
+ its_instance.first,
+ its_info->get_major(),
+ its_info->get_minor(),
+ _endpoint,
+ (!endpoint_is_reliable &&
+ !its_other_endpoint)});
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ for (const auto &s : services_to_report_) {
+ static_cast<routing_manager_impl*>(rm_)->service_endpoint_connected(
+ s.service_id_, s.instance_id_, s.major_, s.minor_, s.endpoint_,
+ s.service_is_unreliable_only_);
+ }
+ if (services_to_report_.empty()) {
+ _endpoint->set_established(true);
+ }
+}
+
+void endpoint_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
+ // Is called when endpoint->connect fails!
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ for (auto &its_service : remote_services_) {
+ for (auto &its_instance : its_service.second) {
+ for (auto &its_client : its_instance.second) {
+ if (its_client.first == VSOMEIP_ROUTING_CLIENT ||
+ its_client.first == get_client()) {
+ const bool is_reliable = _endpoint->is_reliable();
+ auto found_endpoint = its_client.second.find(is_reliable);
+ if (found_endpoint != its_client.second.end()) {
+ if (found_endpoint->second == _endpoint) {
+ std::shared_ptr<serviceinfo> its_info(
+ rm_->find_service(its_service.first,
+ its_instance.first));
+ if(!its_info){
+ return;
+ }
+ if (!is_reliable) {
+ static_cast<routing_manager_impl*>(rm_)->on_availability(
+ its_service.first, its_instance.first,
+ false, its_info->get_major(),
+ its_info->get_minor());
+ }
+ static_cast<routing_manager_impl*>(rm_)->service_endpoint_disconnected(
+ its_service.first, its_instance.first,
+ its_info->get_major(),
+ its_info->get_minor(), _endpoint);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void endpoint_manager_impl::on_error(
+ const byte_t *_data, length_t _length, endpoint* const _receiver,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port) {
+ instance_t its_instance = 0;
+ if (_length >= VSOMEIP_SERVICE_POS_MAX) {
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ its_instance = find_instance(its_service, _receiver);
+ }
+ static_cast<routing_manager_impl*>(rm_)->send_error(
+ return_code_e::E_MALFORMED_MESSAGE, _data, _length, its_instance,
+ _receiver->is_reliable(), _receiver, _remote_address, _remote_port);
+}
+
+void endpoint_manager_impl::release_port(uint16_t _port, bool _reliable) {
+ std::lock_guard<std::mutex> its_lock(used_client_ports_mutex_);
+ used_client_ports_[_reliable].erase(_port);
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::find_remote_client(
+ service_t _service, instance_t _instance, bool _reliable, client_t _client) {
+ std::shared_ptr<endpoint> its_endpoint;
+ auto found_service = remote_services_.find(_service);
+ if (found_service != remote_services_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_client = found_instance->second.find(_client);
+ if (found_client != found_instance->second.end()) {
+ auto found_reliability = found_client->second.find(_reliable);
+ if (found_reliability != found_client->second.end()) {
+ its_endpoint = found_reliability->second;
+ }
+ }
+ }
+ }
+ if (its_endpoint || _client != VSOMEIP_ROUTING_CLIENT) {
+ return its_endpoint;
+ }
+
+ // If another service is hosted on the same server_endpoint
+ // reuse the existing client_endpoint.
+ auto found_service_info = remote_service_info_.find(_service);
+ if(found_service_info != remote_service_info_.end()) {
+ auto found_instance = found_service_info->second.find(_instance);
+ if(found_instance != found_service_info->second.end()) {
+ auto found_reliable = found_instance->second.find(_reliable);
+ if(found_reliable != found_instance->second.end()) {
+ std::shared_ptr<endpoint_definition> its_ep_def =
+ found_reliable->second;
+ auto found_address = client_endpoints_by_ip_.find(
+ its_ep_def->get_address());
+ if(found_address != client_endpoints_by_ip_.end()) {
+ auto found_port = found_address->second.find(
+ its_ep_def->get_remote_port());
+ if(found_port != found_address->second.end()) {
+ auto found_reliable2 = found_port->second.find(
+ _reliable);
+ if(found_reliable2 != found_port->second.end()) {
+ its_endpoint = found_reliable2->second;
+ // store the endpoint under this service/instance id
+ // as well - needed for later cleanup
+ remote_services_[_service][_instance][_client][_reliable] =
+ its_endpoint;
+ service_instances_[_service][its_endpoint.get()] = _instance;
+ // add endpoint to serviceinfo object
+ auto found_service_info = rm_->find_service(_service,_instance);
+ if (found_service_info) {
+ found_service_info->set_endpoint(its_endpoint, _reliable);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return its_endpoint;
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::create_remote_client(
+ service_t _service, instance_t _instance, bool _reliable, client_t _client) {
+ std::shared_ptr<endpoint> its_endpoint;
+ std::shared_ptr<endpoint_definition> its_endpoint_def;
+ uint16_t its_local_port;
+ uint16_t its_remote_port = ILLEGAL_PORT;
+
+ auto found_service = remote_service_info_.find(_service);
+ if (found_service != remote_service_info_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ auto found_reliability = found_instance->second.find(_reliable);
+ if (found_reliability != found_instance->second.end()) {
+ its_endpoint_def = found_reliability->second;
+ its_remote_port = its_endpoint_def->get_port();
+ }
+ }
+ }
+
+ if( its_remote_port != ILLEGAL_PORT) {
+ // if client port range for remote service port range is configured
+ // and remote port is in range, determine unused client port
+ std::unique_lock<std::mutex> its_lock(used_client_ports_mutex_);
+ if (configuration_->get_client_port(_service, _instance, its_remote_port, _reliable,
+ used_client_ports_, its_local_port)) {
+ if(its_endpoint_def) {
+ its_endpoint = create_client_endpoint(
+ its_endpoint_def->get_address(),
+ its_local_port,
+ its_endpoint_def->get_port(),
+ _reliable, _client
+ );
+ }
+
+ if (its_endpoint) {
+ used_client_ports_[_reliable].insert(its_local_port);
+ its_lock.unlock();
+ service_instances_[_service][its_endpoint.get()] = _instance;
+ remote_services_[_service][_instance][_client][_reliable] = its_endpoint;
+ if (_client == VSOMEIP_ROUTING_CLIENT) {
+ client_endpoints_by_ip_[its_endpoint_def->get_address()]
+ [its_endpoint_def->get_port()]
+ [_reliable] = its_endpoint;
+ // Set the basic route to the service in the service info
+ auto found_service_info = rm_->find_service(_service, _instance);
+ if (found_service_info) {
+ found_service_info->set_endpoint(its_endpoint, _reliable);
+ }
+ }
+ }
+ }
+ }
+ return its_endpoint;
+}
+
+std::shared_ptr<endpoint> endpoint_manager_impl::create_client_endpoint(
+ const boost::asio::ip::address &_address,
+ uint16_t _local_port, uint16_t _remote_port,
+ bool _reliable, client_t _client) {
+ (void)_client;
+
+ std::shared_ptr<endpoint> its_endpoint;
+ boost::asio::ip::address its_unicast = configuration_->get_unicast_address();
+
+ try {
+ if (_reliable) {
+ its_endpoint = std::make_shared<tcp_client_endpoint_impl>(
+ shared_from_this(),
+ rm_->shared_from_this(),
+ boost::asio::ip::tcp::endpoint(its_unicast, _local_port),
+ boost::asio::ip::tcp::endpoint(_address, _remote_port),
+ io_,
+ configuration_);
+
+ if (configuration_->has_enabled_magic_cookies(_address.to_string(),
+ _remote_port)) {
+ its_endpoint->enable_magic_cookies();
+ }
+ } else {
+ its_endpoint = std::make_shared<udp_client_endpoint_impl>(
+ shared_from_this(),
+ rm_->shared_from_this(),
+ boost::asio::ip::udp::endpoint(its_unicast, _local_port),
+ boost::asio::ip::udp::endpoint(_address, _remote_port),
+ io_,
+ configuration_);
+ }
+ } catch (...) {
+ VSOMEIP_ERROR << __func__ << " Client endpoint creation failed";
+ }
+
+ return (its_endpoint);
+}
+
+void
+endpoint_manager_impl::log_client_states() const {
+ std::stringstream its_log;
+ std::vector<
+ std::pair<
+ std::tuple<boost::asio::ip::address, uint16_t, bool>,
+ size_t
+ >
+ > its_client_queue_sizes;
+
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ for (const auto its_address : client_endpoints_by_ip_) {
+ for (const auto its_port : its_address.second) {
+ for (const auto its_reliability : its_port.second) {
+ size_t its_queue_size = its_reliability.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
+ its_client_queue_sizes.push_back(
+ std::make_pair(
+ std::make_tuple(
+ its_address.first,
+ its_port.first,
+ its_reliability.first),
+ its_queue_size));
+ }
+ }
+ }
+ }
+
+ std::sort(its_client_queue_sizes.begin(), its_client_queue_sizes.end(),
+ [](const std::pair<
+ std::tuple<boost::asio::ip::address, uint16_t, bool>,
+ size_t> &_a,
+ const std::pair<
+ std::tuple<boost::asio::ip::address, uint16_t, bool>,
+ size_t> &_b) {
+ return (_a.second > _b.second);
+ });
+
+ size_t its_max(std::min(size_t(5), its_client_queue_sizes.size()));
+ for (size_t i = 0; i < its_max; i++) {
+ its_log << std::hex << std::setw(4) << std::setfill('0')
+ << std::get<0>(its_client_queue_sizes[i].first).to_string()
+ << ":" << std::dec << std::get<1>(its_client_queue_sizes[i].first)
+ << "(" << (std::get<2>(its_client_queue_sizes[i].first) ? "tcp" : "udp") << "):"
+ << std::dec << its_client_queue_sizes[i].second;
+ if (i < its_max-1)
+ its_log << ", ";
+ }
+
+ if (its_log.str().length() > 0)
+ VSOMEIP_INFO << "ECQ: [" << its_log.str() << "]";
+}
+
+void
+endpoint_manager_impl::log_server_states() const {
+ std::stringstream its_log;
+ std::vector<
+ std::pair<
+ std::pair<uint16_t, bool>,
+ size_t
+ >
+ > its_client_queue_sizes;
+
+ {
+ std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
+ for (const auto its_port : server_endpoints_) {
+ for (const auto its_reliability : its_port.second) {
+ size_t its_queue_size = its_reliability.second->get_queue_size();
+ if (its_queue_size > VSOMEIP_DEFAULT_QUEUE_WARN_SIZE)
+ its_client_queue_sizes.push_back(
+ std::make_pair(
+ std::make_pair(
+ its_port.first,
+ its_reliability.first),
+ its_queue_size));
+ }
+ }
+ }
+
+ std::sort(its_client_queue_sizes.begin(), its_client_queue_sizes.end(),
+ [](const std::pair<std::pair<uint16_t, bool>, size_t> &_a,
+ const std::pair<std::pair<uint16_t, bool>, size_t> &_b) {
+ return (_a.second > _b.second);
+ });
+
+ size_t its_max(std::min(size_t(5), its_client_queue_sizes.size()));
+ for (size_t i = 0; i < its_max; i++) {
+ its_log << std::dec << its_client_queue_sizes[i].first.first
+ << "(" << (its_client_queue_sizes[i].first.second ? "tcp" : "udp") << "):"
+ << std::dec << its_client_queue_sizes[i].second;
+ if (i < its_max-1)
+ its_log << ", ";
+ }
+
+ if (its_log.str().length() > 0)
+ VSOMEIP_INFO << "ESQ: [" << its_log.str() << "]";
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/local_client_endpoint_impl.cpp b/implementation/endpoints/src/local_client_endpoint_impl.cpp
index a57c831..7e58e67 100644
--- a/implementation/endpoints/src/local_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_client_endpoint_impl.cpp
@@ -1,166 +1,168 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-#include <sstream>
-
-#include <boost/asio/write.hpp>
-
-#include <vsomeip/defines.hpp>
-
-#include "../include/endpoint_host.hpp"
-#include "../include/local_client_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../include/local_server_endpoint_impl.hpp"
-#include "../../configuration/include/configuration.hpp"
-
-// Credentials
-#ifndef _WIN32
-#include "../include/credentials.hpp"
-#endif
-
-namespace vsomeip {
-
-local_client_endpoint_impl::local_client_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit)
- : local_client_endpoint_base_impl(_host, _remote, _remote, _io,
- _max_message_size, _queue_limit),
- // Using _remote for the local(!) endpoint is ok,
- // because we have no bind for local endpoints!
- recv_buffer_(1,0) {
- is_supporting_magic_cookies_ = false;
-}
-
-local_client_endpoint_impl::~local_client_endpoint_impl() {
-
-}
-
-bool local_client_endpoint_impl::is_local() const {
- return true;
-}
-
-void local_client_endpoint_impl::restart(bool _force) {
- if (!_force && state_ == cei_state_e::CONNECTING) {
- return;
- }
- state_ = cei_state_e::CONNECTING;
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- sending_blocked_ = false;
- queue_.clear();
- queue_size_ = 0;
- }
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- shutdown_and_close_socket_unlocked(true);
- }
- was_not_connected_ = true;
- reconnect_counter_ = 0;
- start_connect_timer();
-}
-
-void local_client_endpoint_impl::start() {
- connect();
-}
-
-void local_client_endpoint_impl::stop() {
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- sending_blocked_ = true;
- }
- {
- std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
- boost::system::error_code ec;
- connect_timer_.cancel(ec);
- }
- connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;
-
- bool is_open(false);
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- is_open = socket_->is_open();
- }
- if (is_open) {
- bool send_queue_empty(false);
- std::uint32_t times_slept(0);
-
- while (times_slept <= 50) {
- mutex_.lock();
- send_queue_empty = (queue_.size() == 0);
- mutex_.unlock();
- if (send_queue_empty) {
- break;
- } else {
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- times_slept++;
- }
- }
- }
- shutdown_and_close_socket(false);
-}
-
-void local_client_endpoint_impl::connect() {
- boost::system::error_code its_connect_error;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::system::error_code its_error;
- socket_->open(remote_.protocol(), its_error);
-
- if (!its_error || its_error == boost::asio::error::already_open) {
- socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "local_client_endpoint_impl::connect: "
- << "couldn't enable SO_REUSEADDR: " << its_error.message();
- }
- state_ = cei_state_e::CONNECTING;
- socket_->connect(remote_, its_connect_error);
-
-// Credentials
-#ifndef _WIN32
- if (!its_connect_error) {
- auto its_host = host_.lock();
- if (its_host) {
- if (its_host->get_configuration()->is_security_enabled()) {
- credentials::send_credentials(socket_->native(),
- its_host->get_client());
- }
- }
- } else {
- VSOMEIP_WARNING << "local_client_endpoint::connect: Couldn't "
- << "connect to: " << remote_.path() << " ("
- << its_connect_error.message() << " / " << std::dec
- << its_connect_error.value() << ")";
- }
-#endif
-
- } else {
- VSOMEIP_WARNING << "local_client_endpoint::connect: Error opening socket: "
- << its_error.message() << " (" << std::dec << its_error.value()
- << ")";
- its_connect_error = its_error;
- }
- }
- // call connect_cbk asynchronously
- try {
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+#include <sstream>
+
+#include <boost/asio/write.hpp>
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/endpoint_host.hpp"
+#include "../include/local_client_endpoint_impl.hpp"
+#include "../include/local_server_endpoint_impl.hpp"
+#include "../../routing/include/routing_host.hpp"
+#include "../../security/include/security.hpp"
+
+// Credentials
+#ifndef _WIN32
+#include "../include/credentials.hpp"
+#endif
+
+namespace vsomeip_v3 {
+
+local_client_endpoint_impl::local_client_endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration)
+ : local_client_endpoint_base_impl(_endpoint_host, _routing_host, _remote,
+ _remote, _io,
+ _configuration->get_max_message_size_local(),
+ _configuration->get_endpoint_queue_limit_local(),
+ _configuration),
+ // Using _remote for the local(!) endpoint is ok,
+ // because we have no bind for local endpoints!
+ recv_buffer_(VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE + 8,0) {
+ is_supporting_magic_cookies_ = false;
+}
+
+local_client_endpoint_impl::~local_client_endpoint_impl() {
+
+}
+
+bool local_client_endpoint_impl::is_local() const {
+ return true;
+}
+
+void local_client_endpoint_impl::restart(bool _force) {
+ if (!_force && state_ == cei_state_e::CONNECTING) {
+ return;
+ }
+ state_ = cei_state_e::CONNECTING;
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ sending_blocked_ = false;
+ queue_.clear();
+ queue_size_ = 0;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ shutdown_and_close_socket_unlocked(true);
+ }
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
+ start_connect_timer();
+}
+
+void local_client_endpoint_impl::start() {
+ connect();
+}
+
+void local_client_endpoint_impl::stop() {
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ sending_blocked_ = true;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ boost::system::error_code ec;
+ connect_timer_.cancel(ec);
+ }
+ connect_timeout_ = VSOMEIP_DEFAULT_CONNECT_TIMEOUT;
+
+ bool is_open(false);
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ is_open = socket_->is_open();
+ }
+ if (is_open) {
+ bool send_queue_empty(false);
+ std::uint32_t times_slept(0);
+
+ while (times_slept <= 50) {
+ mutex_.lock();
+ send_queue_empty = (queue_.size() == 0);
+ mutex_.unlock();
+ if (send_queue_empty) {
+ break;
+ } else {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ times_slept++;
+ }
+ }
+ }
+ shutdown_and_close_socket(false);
+}
+
+void local_client_endpoint_impl::connect() {
+ boost::system::error_code its_connect_error;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::system::error_code its_error;
+ socket_->open(remote_.protocol(), its_error);
+
+ if (!its_error || its_error == boost::asio::error::already_open) {
+ socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "local_client_endpoint_impl::connect: "
+ << "couldn't enable SO_REUSEADDR: " << its_error.message();
+ }
+ state_ = cei_state_e::CONNECTING;
+ socket_->connect(remote_, its_connect_error);
+
+// Credentials
+#ifndef _WIN32
+ if (!its_connect_error) {
+ auto its_host = endpoint_host_.lock();
+ if (its_host) {
+ credentials::send_credentials(socket_->native_handle(),
+ its_host->get_client());
+ }
+ } else {
+ VSOMEIP_WARNING << "local_client_endpoint::connect: Couldn't "
+ << "connect to: " << remote_.path() << " ("
+ << its_connect_error.message() << " / " << std::dec
+ << its_connect_error.value() << ")";
+ }
+#endif
+
+ } else {
+ VSOMEIP_WARNING << "local_client_endpoint::connect: Error opening socket: "
+ << its_error.message() << " (" << std::dec << its_error.value()
+ << ")";
+ its_connect_error = its_error;
+ }
+ }
+ // call connect_cbk asynchronously
+ try {
strand_.post(
- std::bind(&client_endpoint_impl::connect_cbk, shared_from_this(),
- its_connect_error));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << "local_client_endpoint_impl::connect: " << e.what();
- }
-}
-
-void local_client_endpoint_impl::receive() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (socket_->is_open()) {
- socket_->async_receive(
- boost::asio::buffer(recv_buffer_),
+ std::bind(&client_endpoint_impl::connect_cbk, shared_from_this(),
+ its_connect_error));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "local_client_endpoint_impl::connect: " << e.what();
+ }
+}
+
+void local_client_endpoint_impl::receive() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (socket_->is_open()) {
+ socket_->async_receive(
+ boost::asio::buffer(recv_buffer_),
strand_.wrap(
std::bind(
&local_client_endpoint_impl::receive_cbk,
@@ -170,170 +172,249 @@ void local_client_endpoint_impl::receive() {
std::placeholders::_1,
std::placeholders::_2
)
- )
- );
- }
-}
-
-void local_client_endpoint_impl::send_queued() {
- static const byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 };
- static const byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
- std::vector<boost::asio::const_buffer> bufs;
-
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
-
-#if 0
-std::stringstream msg;
-msg << "lce<" << this << ">::sq: ";
-for (std::size_t i = 0; i < its_buffer->size(); i++)
- msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(*its_buffer)[i] << " ";
-VSOMEIP_INFO << msg.str();
-#endif
-
- bufs.push_back(boost::asio::buffer(its_start_tag));
- bufs.push_back(boost::asio::buffer(*its_buffer));
- bufs.push_back(boost::asio::buffer(its_end_tag));
-
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::asio::async_write(
- *socket_,
- bufs,
- std::bind(
- &client_endpoint_impl::send_cbk,
- std::dynamic_pointer_cast<
- local_client_endpoint_impl
- >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer
- )
- );
- }
-}
-
-void local_client_endpoint_impl::send_magic_cookie() {
-}
-
-void local_client_endpoint_impl::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes) {
- (void)_bytes;
- if (_error) {
- if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- return;
- } else if (_error == boost::asio::error::connection_reset
- || _error == boost::asio::error::eof
- || _error == boost::asio::error::bad_descriptor) {
- VSOMEIP_TRACE << "local_client_endpoint:"
- " connection_reseted/EOF/bad_descriptor";
- } else if (_error) {
- VSOMEIP_ERROR << "Local endpoint received message ("
- << _error.message() << ")";
- }
- error_handler_t handler;
- {
- std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
- handler = error_handler_;
- }
- if (handler)
- handler();
- } else {
- receive();
- }
-}
-
-bool local_client_endpoint_impl::get_remote_address(
- boost::asio::ip::address &_address) const {
- (void)_address;
- return false;
-}
-
-std::uint16_t local_client_endpoint_impl::get_remote_port() const {
- return 0;
-}
-
-void local_client_endpoint_impl::set_local_port() {
- // local_port_ is set to zero in ctor of client_endpoint_impl -> do nothing
-}
-
-void local_client_endpoint_impl::print_status() {
-#ifndef _WIN32
- std::string its_path = remote_.path();
-#else
- std::string its_path("");
-#endif
- std::size_t its_data_size(0);
- std::size_t its_queue_size(0);
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- its_queue_size = queue_.size();
- its_data_size = queue_size_;
- }
-
- VSOMEIP_INFO << "status lce: " << its_path << " queue: "
- << its_queue_size << " data: " << its_data_size;
-}
-
-std::string local_client_endpoint_impl::get_remote_information() const {
-#ifdef _WIN32
- boost::system::error_code ec;
- return remote_.address().to_string(ec) + ":"
- + std::to_string(remote_.port());
-#else
- return remote_.path();
-#endif
-}
-
-std::uint32_t local_client_endpoint_impl::get_max_allowed_reconnects() const {
- return 13;
-}
-
-bool local_client_endpoint_impl::send(const std::vector<byte_t>& _cmd_header,
- const byte_t *_data, uint32_t _size,
- bool _flush) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- bool ret(true);
- const bool queue_size_zero_on_entry(queue_.empty());
-
- if (endpoint_impl::sending_blocked_ ||
- !check_message_size(static_cast<std::uint32_t>(_cmd_header.size() + _size)) ||
- !check_packetizer_space(static_cast<std::uint32_t>(_cmd_header.size() + _size))||
- !check_queue_limit(_data, static_cast<std::uint32_t>(_cmd_header.size() + _size))) {
- ret = false;
- } else {
-#if 0
- std::stringstream msg;
- msg << "lce::send: ";
- for (uint32_t i = 0; i < _size; i++)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)_data[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- packetizer_->reserve(_cmd_header.size() + _size);
- packetizer_->insert(packetizer_->end(), _cmd_header.begin(), _cmd_header.end());
- packetizer_->insert(packetizer_->end(), _data, _data + _size);
- send_or_start_flush_timer(_flush, queue_size_zero_on_entry);
- }
- return ret;
-}
-
-void local_client_endpoint_impl::max_allowed_reconnects_reached() {
- VSOMEIP_ERROR << "local_client_endpoint::max_allowed_reconnects_reached: "
- << get_remote_information();
- error_handler_t handler;
- {
- std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
- handler = error_handler_;
- }
- if (handler)
- handler();
-}
-
-} // namespace vsomeip
+ )
+ );
+ }
+}
+
+// this overrides client_endpoint_impl::send to disable the pull method
+// for local communication
+bool local_client_endpoint_impl::send(const uint8_t *_data, uint32_t _size) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ bool ret(true);
+ const bool queue_size_zero_on_entry(queue_.empty());
+ if (endpoint_impl::sending_blocked_ ||
+ check_message_size(nullptr, _size) != cms_ret_e::MSG_OK ||
+ !check_packetizer_space(_size) ||
+ !check_queue_limit(_data, _size)) {
+ ret = false;
+ } else {
+#if 0
+ std::stringstream msg;
+ msg << "lce::send: ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ train_.buffer_->insert(train_.buffer_->end(), _data, _data + _size);
+ queue_train(queue_size_zero_on_entry);
+ }
+ return ret;
+}
+
+void local_client_endpoint_impl::send_queued() {
+ static const byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 };
+ static const byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
+ std::vector<boost::asio::const_buffer> bufs;
+
+ message_buffer_ptr_t its_buffer;
+ if(queue_.size()) {
+ its_buffer = queue_.front();
+ } else {
+ return;
+ }
+
+ bufs.push_back(boost::asio::buffer(its_start_tag));
+ bufs.push_back(boost::asio::buffer(*its_buffer));
+ bufs.push_back(boost::asio::buffer(its_end_tag));
+
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::asio::async_write(
+ *socket_,
+ bufs,
+ std::bind(
+ &client_endpoint_impl::send_cbk,
+ std::dynamic_pointer_cast<
+ local_client_endpoint_impl
+ >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer
+ )
+ );
+ }
+}
+
+void local_client_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ (void)_service;
+ (void)_method;
+ (void)_debouncing;
+ (void)_maximum_retention;
+ VSOMEIP_ERROR << "local_client_endpoint_impl::get_configured_times_from_endpoint called.";
+}
+
+void local_client_endpoint_impl::send_magic_cookie() {
+}
+
+void local_client_endpoint_impl::receive_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes) {
+ if (_error) {
+ if (_error == boost::asio::error::operation_aborted) {
+ // endpoint was stopped
+ return;
+ } else if (_error == boost::asio::error::connection_reset
+ || _error == boost::asio::error::eof
+ || _error == boost::asio::error::bad_descriptor) {
+ VSOMEIP_TRACE << "local_client_endpoint:"
+ " connection_reseted/EOF/bad_descriptor";
+ } else if (_error) {
+ VSOMEIP_ERROR << "Local endpoint received message ("
+ << _error.message() << ")";
+ }
+ error_handler_t handler;
+ {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ handler = error_handler_;
+ }
+ if (handler)
+ handler();
+ } else {
+
+#if 0
+ std::stringstream msg;
+ msg << "lce<" << this << ">::recv: ";
+ for (std::size_t i = 0; i < recv_buffer_.size(); i++)
+ msg << std::setw(2) << std::setfill('0') << std::hex
+ << (int)recv_buffer_[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+
+ // We only handle a single message here. Check whether the message
+ // format matches what we do expect.
+ if (_bytes == VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE + 8
+ && recv_buffer_[0] == 0x67 && recv_buffer_[1] == 0x37
+ && recv_buffer_[2] == 0x6d && recv_buffer_[3] == 0x07
+ && recv_buffer_[4] == VSOMEIP_ASSIGN_CLIENT_ACK
+ && recv_buffer_[13] == 0x07 && recv_buffer_[14] == 0x6d
+ && recv_buffer_[15] == 0x37 && recv_buffer_[16] == 0x67) {
+
+ auto its_routing_host = routing_host_.lock();
+ if (its_routing_host)
+ its_routing_host->on_message(&recv_buffer_[4],
+ static_cast<length_t>(recv_buffer_.size() - 8), this);
+ }
+
+ receive();
+ }
+}
+
+bool local_client_endpoint_impl::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ (void)_address;
+ return false;
+}
+
+std::uint16_t local_client_endpoint_impl::get_remote_port() const {
+ return 0;
+}
+
+void local_client_endpoint_impl::set_local_port() {
+ // local_port_ is set to zero in ctor of client_endpoint_impl -> do nothing
+}
+
+void local_client_endpoint_impl::print_status() {
+#ifndef _WIN32
+ std::string its_path = remote_.path();
+#else
+ std::string its_path("");
+#endif
+ std::size_t its_data_size(0);
+ std::size_t its_queue_size(0);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ its_queue_size = queue_.size();
+ its_data_size = queue_size_;
+ }
+
+ VSOMEIP_INFO << "status lce: " << its_path << " queue: "
+ << its_queue_size << " data: " << its_data_size;
+}
+
+std::string local_client_endpoint_impl::get_remote_information() const {
+#ifdef _WIN32
+ boost::system::error_code ec;
+ return remote_.address().to_string(ec) + ":"
+ + std::to_string(remote_.port());
+#else
+ return remote_.path();
+#endif
+}
+
+
+bool local_client_endpoint_impl::check_packetizer_space(std::uint32_t _size) {
+ if (train_.buffer_->size() + _size < train_.buffer_->size()) {
+ VSOMEIP_ERROR << "Overflow in packetizer addition ~> abort sending!";
+ return false;
+ }
+ if (train_.buffer_->size() + _size > max_message_size_
+ && !train_.buffer_->empty()) {
+ queue_.push_back(train_.buffer_);
+ queue_size_ += train_.buffer_->size();
+ train_.buffer_ = std::make_shared<message_buffer_t>();
+ }
+ return true;
+}
+
+bool local_client_endpoint_impl::is_reliable() const {
+ return false;
+}
+
+std::uint32_t local_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return 13;
+}
+
+bool local_client_endpoint_impl::send(const std::vector<byte_t>& _cmd_header,
+ const byte_t *_data, uint32_t _size) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ bool ret(true);
+ const bool queue_size_zero_on_entry(queue_.empty());
+
+ const std::uint32_t its_complete_size = static_cast<std::uint32_t>(
+ _cmd_header.size() + _size);
+ if (endpoint_impl::sending_blocked_ ||
+ check_message_size(nullptr, its_complete_size) != cms_ret_e::MSG_OK ||
+ !check_packetizer_space(its_complete_size)||
+ !check_queue_limit(_data, its_complete_size)) {
+ ret = false;
+ } else {
+#if 0
+ std::stringstream msg;
+ msg << "lce::send: ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ train_.buffer_->reserve(its_complete_size);
+ train_.buffer_->insert(train_.buffer_->end(), _cmd_header.begin(), _cmd_header.end());
+ train_.buffer_->insert(train_.buffer_->end(), _data, _data + _size);
+ queue_train(queue_size_zero_on_entry);
+ }
+ return ret;
+}
+
+bool local_client_endpoint_impl::tp_segmentation_enabled(
+ service_t _service, method_t _method) const {
+ (void)_service;
+ (void)_method;
+ return false;
+}
+
+void local_client_endpoint_impl::max_allowed_reconnects_reached() {
+ VSOMEIP_ERROR << "local_client_endpoint::max_allowed_reconnects_reached: "
+ << get_remote_information();
+ error_handler_t handler;
+ {
+ std::lock_guard<std::mutex> its_lock(error_handler_mutex_);
+ handler = error_handler_;
+ }
+ if (handler)
+ handler();
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/local_server_endpoint_impl.cpp b/implementation/endpoints/src/local_server_endpoint_impl.cpp
index cfd5c0b..ecfbd88 100644
--- a/implementation/endpoints/src/local_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/local_server_endpoint_impl.cpp
@@ -10,31 +10,37 @@
#include <sys/types.h>
#include <boost/asio/write.hpp>
+#include <vsomeip/internal/logger.hpp>
+
#include "../include/endpoint_host.hpp"
+#include "../../routing/include/routing_host.hpp"
#include "../include/local_server_endpoint_impl.hpp"
-
-#include "../../logging/include/logger.hpp"
+#include "../../security/include/security.hpp"
#include "../../utility/include/byteorder.hpp"
-#include "../../configuration/include/internal.hpp"
#include "../../configuration/include/configuration.hpp"
+#include "../../utility/include/utility.hpp"
// Credentials
#ifndef _WIN32
#include "../include/credentials.hpp"
#endif
-namespace vsomeip {
+namespace vsomeip_v3 {
local_server_endpoint_impl::local_server_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local, boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit, std::uint32_t _mode)
- : local_server_endpoint_base_impl(_host, _local, _io,
- _max_message_size, _queue_limit),
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local, boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration,
+ bool _is_routing_endpoint)
+ : local_server_endpoint_base_impl(_endpoint_host, _routing_host, _local,
+ _io,
+ _configuration->get_max_message_size_local(),
+ _configuration->get_endpoint_queue_limit_local(),
+ _configuration),
acceptor_(_io),
- buffer_shrink_threshold_(_buffer_shrink_threshold) {
+ buffer_shrink_threshold_(_configuration->get_buffer_shrink_threshold()),
+ is_routing_endpoint_(_is_routing_endpoint) {
is_supporting_magic_cookies_ = false;
boost::system::error_code ec;
@@ -48,26 +54,28 @@ local_server_endpoint_impl::local_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor listen");
#ifndef _WIN32
- if (chmod(_local.path().c_str(), static_cast<mode_t>(_mode)) == -1) {
+ if (chmod(_local.path().c_str(),
+ static_cast<mode_t>(_configuration->get_permissions_uds())) == -1) {
VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
}
- if (_host->get_configuration()->is_security_enabled()) {
- credentials::activate_credentials(acceptor_.native_handle());
- }
+ credentials::activate_credentials(acceptor_.native_handle());
#endif
}
local_server_endpoint_impl::local_server_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local, boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local, boost::asio::io_service &_io,
int native_socket,
- std::uint32_t _buffer_shrink_threshold,
- configuration::endpoint_queue_limit_t _queue_limit, std::uint32_t _mode)
- : local_server_endpoint_base_impl(_host, _local, _io,
- _max_message_size, _queue_limit),
+ const std::shared_ptr<configuration>& _configuration,
+ bool _is_routing_endpoint)
+ : local_server_endpoint_base_impl(_endpoint_host, _routing_host, _local, _io,
+ _configuration->get_max_message_size_local(),
+ _configuration->get_endpoint_queue_limit_local(),
+ _configuration),
acceptor_(_io),
- buffer_shrink_threshold_(_buffer_shrink_threshold) {
+ buffer_shrink_threshold_(configuration_->get_buffer_shrink_threshold()),
+ is_routing_endpoint_(_is_routing_endpoint) {
is_supporting_magic_cookies_ = false;
boost::system::error_code ec;
@@ -75,12 +83,11 @@ local_server_endpoint_impl::local_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor assign native socket");
#ifndef _WIN32
- if (chmod(_local.path().c_str(), static_cast<mode_t>(_mode)) == -1) {
+ if (chmod(_local.path().c_str(),
+ static_cast<mode_t>(_configuration->get_permissions_uds())) == -1) {
VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
}
- if (_host->get_configuration()->is_security_enabled()) {
- credentials::activate_credentials(acceptor_.native_handle());
- }
+ credentials::activate_credentials(acceptor_.native_handle());
#endif
}
@@ -133,49 +140,63 @@ void local_server_endpoint_impl::stop() {
}
connections_.clear();
}
-#ifndef _WIN32
+}
+
+bool local_server_endpoint_impl::send(const uint8_t *_data, uint32_t _size) {
+#if 0
+ std::stringstream msg;
+ msg << "lse::send ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::setw(2) << std::setfill('0') << std::hex << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (endpoint_impl::sending_blocked_) {
+ return false;
+ }
+
+ client_t its_client;
+ std::memcpy(&its_client, &_data[7], sizeof(its_client));
+
+ connection::ptr its_connection;
{
- std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
- client_connections_.clear();
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ const auto its_iterator = connections_.find(its_client);
+ if (its_iterator == connections_.end()) {
+ return false;
+ } else {
+ its_connection = its_iterator->second;
+ }
}
-#endif
+
+ auto its_buffer = std::make_shared<message_buffer_t>();
+ its_buffer->insert(its_buffer->end(), _data, _data + _size);
+ its_connection->send_queued(its_buffer);
+
+ return true;
}
bool local_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush) {
+ const byte_t *_data, uint32_t _size) {
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ return false;
+}
+
+bool local_server_endpoint_impl::send_error(
+ const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) {
(void)_target;
(void)_data;
(void)_size;
- (void)_flush;
return false;
}
void local_server_endpoint_impl::send_queued(
const queue_iterator_type _queue_iterator) {
- connection::ptr its_connection;
- {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- auto connection_iterator = connections_.find(_queue_iterator->first);
- if (connection_iterator != connections_.end()) {
- connection_iterator->second->send_queued(_queue_iterator);
- its_connection = connection_iterator->second;
- } else {
- VSOMEIP_INFO << "Didn't find connection: "
-#ifdef _WIN32
- << _queue_iterator->first.address().to_string() << ":" << std::dec
- << static_cast<std::uint16_t>(_queue_iterator->first.port())
-#else
- << _queue_iterator->first.path()
-#endif
- << " dropping outstanding messages (" << std::dec
- << _queue_iterator->second.second.size() << ").";
- queues_.erase(_queue_iterator->first);
- }
- }
- if (its_connection) {
- its_connection->send_queued(_queue_iterator);
- }
+ (void)_queue_iterator;
}
void local_server_endpoint_impl::receive() {
@@ -188,38 +209,29 @@ bool local_server_endpoint_impl::get_default_target(
return false;
}
-void local_server_endpoint_impl::remove_connection(
- local_server_endpoint_impl::connection *_connection) {
- {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- for (auto it = connections_.begin(); it != connections_.end();) {
- if (it->second.get() == _connection) {
- it = connections_.erase(it);
- break;
- } else {
- ++it;
- }
- }
+bool local_server_endpoint_impl::add_connection(const client_t &_client,
+ const std::shared_ptr<connection> &_connection) {
+ bool ret = false;
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ auto find_connection = connections_.find(_client);
+ if (find_connection == connections_.end()) {
+ connections_[_client] = _connection;
+ ret = true;
+ } else {
+ VSOMEIP_WARNING << "Attempt to add already existing "
+ "connection to client " << std::hex << _client;
}
+ return ret;
+}
-#ifndef _WIN32
- {
- std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
- for (auto it = client_connections_.begin(); it != client_connections_.end();) {
- if (it->second.get() == _connection) {
- it = client_connections_.erase(it);
- break;
- } else {
- ++it;
- }
- }
- }
-#endif
+void local_server_endpoint_impl::remove_connection(
+ const client_t &_client) {
+ std::lock_guard<std::mutex> its_lock(connections_mutex_);
+ connections_.erase(_client);
}
void local_server_endpoint_impl::accept_cbk(
- connection::ptr _connection, boost::system::error_code const &_error) {
-
+ const connection::ptr& _connection, boost::system::error_code const &_error) {
if (_error != boost::asio::error::bad_descriptor
&& _error != boost::asio::error::operation_aborted
&& _error != boost::asio::error::no_descriptors) {
@@ -243,40 +255,46 @@ void local_server_endpoint_impl::accept_cbk(
if (!_error) {
#ifndef _WIN32
- auto its_host = host_.lock();
+ auto its_host = endpoint_host_.lock();
client_t client = 0;
- if (its_host) {
- if (its_host->get_configuration()->is_security_enabled()) {
- std::unique_lock<std::mutex> its_socket_lock(_connection->get_socket_lock());
- socket_type &new_connection_socket = _connection->get_socket();
- uid_t uid(0xffffffff);
- gid_t gid(0xffffffff);
- client = credentials::receive_credentials(
- new_connection_socket.native(), uid, gid);
-
- std::lock_guard<std::mutex> its_client_connection_lock(client_connections_mutex_);
- auto found_client = client_connections_.find(client);
- if (found_client != client_connections_.end()) {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Rejecting new connection with client ID 0x" << client
- << " uid/gid= " << std::dec << uid << "/" << gid
- << " because of already existing connection using same client ID";
- boost::system::error_code er;
- new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
- new_connection_socket.close(er);
- return;
- }
- if (!its_host->get_configuration()->check_routing_credentials(client, uid, gid)) {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Rejecting new connection with routing manager client ID 0x" << client
- << " uid/gid= " << std::dec << uid << "/" << gid
- << " because passed credentials do not match with routing manager credentials!";
- boost::system::error_code er;
- new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
- new_connection_socket.close(er);
- return;
- }
+ socket_type &new_connection_socket = _connection->get_socket();
+ uid_t uid(ANY_UID);
+ gid_t gid(ANY_GID);
+ client = credentials::receive_credentials(
+ new_connection_socket.native_handle(), uid, gid);
+
+ if (its_host && security::get()->is_enabled()) {
+ if (!configuration_->check_routing_credentials(client, uid, gid)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Rejecting new connection with routing manager client ID 0x" << std::hex << client
+ << " uid/gid= " << std::dec << uid << "/" << gid
+ << " because passed credentials do not match with routing manager credentials!";
+ boost::system::error_code er;
+ new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
+ new_connection_socket.close(er);
+ return;
+ }
- if (!its_host->check_credentials(client, uid, gid)) {
+ if (is_routing_endpoint_) {
+ // rm_impl receives VSOMEIP_CLIENT_UNSET initially -> check later
+ _connection->set_bound_uid_gid(uid, gid);
+ } else {
+ {
+ std::lock_guard<std::mutex> its_connection_lock(connections_mutex_);
+ // rm_impl receives VSOMEIP_CLIENT_UNSET initially -> check later
+ const auto found_client = connections_.find(client);
+ if (found_client != connections_.end()) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
+ << its_host->get_client() << " is rejecting new connection with client ID 0x"
+ << client << " uid/gid= " << std::dec << uid << "/" << gid
+ << " because of already existing connection using same client ID";
+ boost::system::error_code er;
+ new_connection_socket.shutdown(new_connection_socket.shutdown_both, er);
+ new_connection_socket.close(er);
+ return;
+ }
+ }
+ if (!security::get()->check_credentials(client, uid, gid)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
<< its_host->get_client() << " received client credentials from client 0x"
<< client << " which violates the security policy : uid/gid="
@@ -286,34 +304,16 @@ void local_server_endpoint_impl::accept_cbk(
new_connection_socket.close(er);
return;
}
+ // rm_impl receives VSOMEIP_CLIENT_UNSET initially -> set later
_connection->set_bound_client(client);
- credentials::deactivate_credentials(new_connection_socket.native());
+ add_connection(client, _connection);
}
+ } else {
+ security::get()->store_client_to_uid_gid_mapping(client, uid, gid);
+ security::get()->store_uid_gid_to_client_mapping(uid, gid, client);
}
#endif
-
- boost::system::error_code its_error;
- endpoint_type remote;
- {
- std::unique_lock<std::mutex> its_socket_lock(_connection->get_socket_lock());
- socket_type &new_connection_socket = _connection->get_socket();
- remote = new_connection_socket.remote_endpoint(its_error);
- }
- if (!its_error) {
- {
- {
- std::lock_guard<std::mutex> its_lock(connections_mutex_);
- connections_[remote] = _connection;
- }
-#ifndef _WIN32
- {
- std::lock_guard<std::mutex> its_lock(client_connections_mutex_);
- client_connections_[client] = _connection;
- }
-#endif
- }
- _connection->start();
- }
+ _connection->start();
}
}
@@ -322,7 +322,7 @@ void local_server_endpoint_impl::accept_cbk(
///////////////////////////////////////////////////////////////////////////////
local_server_endpoint_impl::connection::connection(
- std::weak_ptr<local_server_endpoint_impl> _server,
+ const std::shared_ptr<local_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
std::uint32_t _initial_recv_buffer_size,
std::uint32_t _buffer_shrink_threshold,
@@ -336,12 +336,21 @@ local_server_endpoint_impl::connection::connection(
missing_capacity_(0),
shrink_count_(0),
buffer_shrink_threshold_(_buffer_shrink_threshold),
- bound_client_(VSOMEIP_ROUTING_CLIENT) {
+ bound_client_(VSOMEIP_CLIENT_UNSET),
+#ifndef _WIN32
+ bound_uid_(ANY_UID),
+ bound_gid_(ANY_GID),
+#endif
+ assigned_client_(false) {
+ if (_server->is_routing_endpoint_ &&
+ !security::get()->is_enabled()) {
+ assigned_client_ = true;
+ }
}
local_server_endpoint_impl::connection::ptr
local_server_endpoint_impl::connection::create(
- std::weak_ptr<local_server_endpoint_impl> _server,
+ const std::shared_ptr<local_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
boost::asio::io_service &_io_service) {
@@ -393,6 +402,19 @@ void local_server_endpoint_impl::connection::start() {
// don't start receiving again
return;
}
+#ifndef _WIN32
+ socket_.async_receive(
+ boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
+ std::bind(
+ &local_server_endpoint_impl::connection::receive_cbk,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3,
+ std::placeholders::_4
+ )
+ );
+#else
socket_.async_receive(
boost::asio::buffer(&recv_buffer_[recv_buffer_size_], buffer_size),
std::bind(
@@ -402,6 +424,7 @@ void local_server_endpoint_impl::connection::start() {
std::placeholders::_2
)
);
+#endif
}
}
@@ -421,11 +444,7 @@ void local_server_endpoint_impl::connection::stop() {
}
void local_server_endpoint_impl::connection::send_queued(
- const queue_iterator_type _queue_iterator) {
-
- // TODO: We currently do _not_ use the send method of the local server
- // endpoints. If we ever need it, we need to add the "start tag", "data",
- // "end tag" sequence here.
+ const message_buffer_ptr_t& _buffer) {
std::shared_ptr<local_server_endpoint_impl> its_server(server_.lock());
if (!its_server) {
VSOMEIP_TRACE << "local_server_endpoint_impl::connection::send_queued "
@@ -433,24 +452,32 @@ void local_server_endpoint_impl::connection::send_queued(
return;
}
- message_buffer_ptr_t its_buffer = _queue_iterator->second.second.front();
+ static const byte_t its_start_tag[] = { 0x67, 0x37, 0x6D, 0x07 };
+ static const byte_t its_end_tag[] = { 0x07, 0x6D, 0x37, 0x67 };
+ std::vector<boost::asio::const_buffer> bufs;
+
#if 0
std::stringstream msg;
msg << "lse::sq: ";
- for (std::size_t i = 0; i < its_buffer->size(); i++)
+ for (std::size_t i = 0; i < _buffer->size(); i++)
msg << std::setw(2) << std::setfill('0') << std::hex
- << (int)(*its_buffer)[i] << " ";
+ << (int)(*_buffer)[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
+
+ bufs.push_back(boost::asio::buffer(its_start_tag));
+ bufs.push_back(boost::asio::buffer(*_buffer));
+ bufs.push_back(boost::asio::buffer(its_end_tag));
+
{
std::lock_guard<std::mutex> its_lock(socket_mutex_);
boost::asio::async_write(
socket_,
- boost::asio::buffer(*its_buffer),
+ bufs,
std::bind(
- &local_server_endpoint_base_impl::send_cbk,
- its_server,
- _queue_iterator,
+ &local_server_endpoint_impl::connection::send_cbk,
+ shared_from_this(),
+ _buffer,
std::placeholders::_1,
std::placeholders::_2
)
@@ -458,191 +485,290 @@ void local_server_endpoint_impl::connection::send_queued(
}
}
-void local_server_endpoint_impl::connection::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes) {
+client_t local_server_endpoint_impl::assign_client(
+ const byte_t *_data, uint32_t _size) {
+ client_t its_client(VSOMEIP_CLIENT_UNSET);
+ std::string its_name;
+ uint32_t its_name_length;
- if (_error == boost::asio::error::operation_aborted) {
- // connection was stopped
- return;
+ if (_size >= VSOMEIP_COMMAND_PAYLOAD_POS) {
+ std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS], sizeof(its_client));
+ std::memcpy(&its_name_length, &_data[VSOMEIP_COMMAND_SIZE_POS_MIN],
+ sizeof(its_name_length));
+
+ if (its_name_length > 0)
+ its_name.assign(reinterpret_cast<const char *>(
+ &_data[VSOMEIP_COMMAND_PAYLOAD_POS]), its_name_length);
}
+
+ its_client = utility::request_client_id(configuration_, its_name, its_client);
+
+ return its_client;
+}
+
+void local_server_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service,
+ method_t _method, std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ (void)_service;
+ (void)_method;
+ (void)_debouncing;
+ (void)_maximum_retention;
+ VSOMEIP_ERROR << "local_server_endpoint_impl::get_configured_times_from_endpoint.";
+}
+
+void local_server_endpoint_impl::connection::send_cbk(const message_buffer_ptr_t _buffer,
+ boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_buffer;
+ (void)_bytes;
+ if (_error)
+ VSOMEIP_WARNING << "sei::send_cbk received error: " << _error.message();
+}
+
+void local_server_endpoint_impl::connection::receive_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes
+#ifndef _WIN32
+ , std::uint32_t const &_uid, std::uint32_t const &_gid
+#endif
+ )
+{
std::shared_ptr<local_server_endpoint_impl> its_server(server_.lock());
if (!its_server) {
VSOMEIP_TRACE << "local_server_endpoint_impl::connection::receive_cbk "
" couldn't lock server_";
return;
}
- std::shared_ptr<endpoint_host> its_host = its_server->host_.lock();
- if (its_host) {
- std::size_t its_start = 0;
- std::size_t its_end = 0;
- std::size_t its_iteration_gap = 0;
- std::uint32_t its_command_size = 0;
-
- if (!_error && 0 < _bytes) {
- #if 0
- std::stringstream msg;
- msg << "lse::c<" << this << ">rcb: ";
- for (std::size_t i = 0; i < _bytes + recv_buffer_size_; i++)
- msg << std::setw(2) << std::setfill('0') << std::hex
- << (int) (recv_buffer_[i]) << " ";
- VSOMEIP_INFO << msg.str();
- #endif
-
- if (recv_buffer_size_ + _bytes < recv_buffer_size_) {
- VSOMEIP_ERROR << "receive buffer overflow in local server endpoint ~> abort!";
+
+ std::shared_ptr<routing_host> its_host = its_server->routing_host_.lock();
+ if (!its_host)
+ return;
+
+ if (_error == boost::asio::error::operation_aborted) {
+ if (its_server->is_routing_endpoint_ &&
+ bound_client_ != VSOMEIP_CLIENT_UNSET) {
+ utility::release_client_id(bound_client_);
+ set_bound_client(VSOMEIP_CLIENT_UNSET);
+ }
+
+ // connection was stopped
+ return;
+ }
+
+ std::size_t its_start = 0;
+ std::size_t its_end = 0;
+ std::size_t its_iteration_gap = 0;
+ std::uint32_t its_command_size = 0;
+
+ if (!_error && 0 < _bytes) {
+#if 0
+ std::stringstream msg;
+ msg << "lse::c<" << this << ">rcb: ";
+ for (std::size_t i = 0; i < _bytes + recv_buffer_size_; i++)
+ msg << std::setw(2) << std::setfill('0') << std::hex
+ << (int) (recv_buffer_[i]) << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+
+ if (recv_buffer_size_ + _bytes < recv_buffer_size_) {
+ VSOMEIP_ERROR << "receive buffer overflow in local server endpoint ~> abort!";
+ return;
+ }
+ recv_buffer_size_ += _bytes;
+
+ bool message_is_empty(false);
+ bool found_message(false);
+
+ do {
+ found_message = false;
+ message_is_empty = false;
+
+ its_start = 0 + its_iteration_gap;
+ if (its_start + 3 < its_start) {
+ VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!";
return;
}
- recv_buffer_size_ += _bytes;
+ while (its_start + 3 < recv_buffer_size_ + its_iteration_gap &&
+ (recv_buffer_[its_start] != 0x67 ||
+ recv_buffer_[its_start+1] != 0x37 ||
+ recv_buffer_[its_start+2] != 0x6d ||
+ recv_buffer_[its_start+3] != 0x07)) {
+ its_start++;
+ }
- bool message_is_empty(false);
- bool found_message(false);
+ if (its_start + 3 == recv_buffer_size_ + its_iteration_gap) {
+ message_is_empty = true;
+ } else {
+ its_start += 4;
+ }
- do {
- found_message = false;
- message_is_empty = false;
+ if (!message_is_empty) {
+ if (its_start + 6 < recv_buffer_size_ + its_iteration_gap) {
+ its_command_size = VSOMEIP_BYTES_TO_LONG(
+ recv_buffer_[its_start + 6],
+ recv_buffer_[its_start + 5],
+ recv_buffer_[its_start + 4],
+ recv_buffer_[its_start + 3]);
- its_start = 0 + its_iteration_gap;
- if (its_start + 3 < its_start) {
+ its_end = its_start + 6 + its_command_size;
+ } else {
+ its_end = its_start;
+ }
+ if (its_command_size && max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ && its_command_size > max_message_size_) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ VSOMEIP_ERROR << "Received a local message which exceeds "
+ << "maximum message size (" << std::dec << its_command_size
+ << ") aborting! local: " << get_path_local() << " remote: "
+ << get_path_remote();
+ recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
+ recv_buffer_.shrink_to_fit();
+ return;
+ }
+ if (its_end + 3 < its_end) {
VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!";
return;
}
- while (its_start + 3 < recv_buffer_size_ + its_iteration_gap &&
- (recv_buffer_[its_start] != 0x67 ||
- recv_buffer_[its_start+1] != 0x37 ||
- recv_buffer_[its_start+2] != 0x6d ||
- recv_buffer_[its_start+3] != 0x07)) {
- its_start++;
+ while (its_end + 3 < recv_buffer_size_ + its_iteration_gap &&
+ (recv_buffer_[its_end] != 0x07 ||
+ recv_buffer_[its_end+1] != 0x6d ||
+ recv_buffer_[its_end+2] != 0x37 ||
+ recv_buffer_[its_end+3] != 0x67)) {
+ its_end ++;
}
-
- if (its_start + 3 == recv_buffer_size_ + its_iteration_gap) {
- message_is_empty = true;
- } else {
- its_start += 4;
+ if (its_end + 4 < its_end) {
+ VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!";
+ return;
}
-
- if (!message_is_empty) {
- if (its_start + 6 < recv_buffer_size_ + its_iteration_gap) {
- its_command_size = VSOMEIP_BYTES_TO_LONG(
- recv_buffer_[its_start + 6],
- recv_buffer_[its_start + 5],
- recv_buffer_[its_start + 4],
- recv_buffer_[its_start + 3]);
-
- its_end = its_start + 6 + its_command_size;
+ // check if we received a full message
+ if (recv_buffer_size_ + its_iteration_gap < its_end + 4
+ || recv_buffer_[its_end] != 0x07
+ || recv_buffer_[its_end+1] != 0x6d
+ || recv_buffer_[its_end+2] != 0x37
+ || recv_buffer_[its_end+3] != 0x67) {
+ // command (1 Byte) + client id (2 Byte)
+ // + command size (4 Byte) + data itself + stop tag (4 byte)
+ // = 11 Bytes not covered in command size.
+ if (its_start - its_iteration_gap + its_command_size + 11 > recv_buffer_size_) {
+ missing_capacity_ =
+ std::uint32_t(its_start) - std::uint32_t(its_iteration_gap)
+ + its_command_size + 11 - std::uint32_t(recv_buffer_size_);
+ } else if (recv_buffer_size_ < 11) {
+ // to little data to read out the command size
+ // minimal amount of data needed to read out command size = 11
+ missing_capacity_ = 11 - static_cast<std::uint32_t>(recv_buffer_size_);
} else {
- its_end = its_start;
- }
- if (its_command_size && max_message_size_ != MESSAGE_SIZE_UNLIMITED
- && its_command_size > max_message_size_) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- VSOMEIP_ERROR << "Received a local message which exceeds "
- << "maximum message size (" << std::dec << its_command_size
- << ") aborting! local: " << get_path_local() << " remote: "
- << get_path_remote();
- recv_buffer_.resize(recv_buffer_size_initial_, 0x0);
- recv_buffer_.shrink_to_fit();
- return;
- }
- if (its_end + 3 < its_end) {
- VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!";
- return;
- }
- while (its_end + 3 < recv_buffer_size_ + its_iteration_gap &&
- (recv_buffer_[its_end] != 0x07 ||
- recv_buffer_[its_end+1] != 0x6d ||
- recv_buffer_[its_end+2] != 0x37 ||
- recv_buffer_[its_end+3] != 0x67)) {
- its_end ++;
- }
- if (its_end + 4 < its_end) {
- VSOMEIP_ERROR << "buffer overflow in local server endpoint ~> abort!";
- return;
- }
- // check if we received a full message
- if (recv_buffer_size_ + its_iteration_gap < its_end + 4
- || recv_buffer_[its_end] != 0x07
- || recv_buffer_[its_end+1] != 0x6d
- || recv_buffer_[its_end+2] != 0x37
- || recv_buffer_[its_end+3] != 0x67) {
- // start tag (4 Byte) + command (1 Byte) + client id (2 Byte)
- // + command size (4 Byte) + data itself + stop tag (4 byte)
- // = 15 Bytes not covered in command size.
- if (its_command_size + 15 > recv_buffer_size_) {
- missing_capacity_ = its_command_size + 15 - std::uint32_t(recv_buffer_size_);
- } else if (recv_buffer_size_ < 11) {
- // to little data to read out the command size
- // minimal amount of data needed to read out command size = 11
- missing_capacity_ = 11 - static_cast<std::uint32_t>(recv_buffer_size_);
- } else {
- std::stringstream local_msg;
- for (std::size_t i = its_iteration_gap;
- i < recv_buffer_size_ + its_iteration_gap &&
- i - its_iteration_gap < 32; i++) {
- local_msg << std::setw(2) << std::setfill('0')
- << std::hex << (int) recv_buffer_[i] << " ";
- }
- VSOMEIP_ERROR << "lse::c<" << this
- << ">rcb: recv_buffer_size is: " << std::dec
- << recv_buffer_size_ << " but couldn't read "
- "out command size. recv_buffer_capacity: "
- << std::dec << recv_buffer_.capacity()
- << " its_iteration_gap: " << std::dec
- << its_iteration_gap << " bound client: 0x"
- << std::hex << bound_client_ << " buffer: "
- << local_msg.str();
- recv_buffer_size_ = 0;
- missing_capacity_ = 0;
- its_iteration_gap = 0;
- message_is_empty = true;
+ std::stringstream local_msg;
+ for (std::size_t i = its_iteration_gap;
+ i < recv_buffer_size_ + its_iteration_gap &&
+ i - its_iteration_gap < 32; i++) {
+ local_msg << std::setw(2) << std::setfill('0')
+ << std::hex << (int) recv_buffer_[i] << " ";
}
+ VSOMEIP_ERROR << "lse::c<" << this
+ << ">rcb: recv_buffer_size is: " << std::dec
+ << recv_buffer_size_ << " but couldn't read "
+ "out command size. recv_buffer_capacity: "
+ << std::dec << recv_buffer_.capacity()
+ << " its_iteration_gap: " << std::dec
+ << its_iteration_gap << " bound client: 0x"
+ << std::hex << bound_client_ << " buffer: "
+ << local_msg.str();
+ recv_buffer_size_ = 0;
+ missing_capacity_ = 0;
+ its_iteration_gap = 0;
+ message_is_empty = true;
}
}
+ }
+
+ if (!message_is_empty &&
+ its_end + 3 < recv_buffer_size_ + its_iteration_gap) {
- if (!message_is_empty &&
- its_end + 3 < recv_buffer_size_ + its_iteration_gap) {
+ if (its_server->is_routing_endpoint_
+ && recv_buffer_[its_start] == VSOMEIP_ASSIGN_CLIENT) {
+ client_t its_client = its_server->assign_client(
+ &recv_buffer_[its_start], uint32_t(its_end - its_start));
+#ifndef _WIN32
+ if (security::get()->is_enabled()) {
+ if (!its_server->add_connection(its_client, shared_from_this())) {
+ VSOMEIP_WARNING << std::hex << "Client 0x" << its_host->get_client()
+ << " is rejecting new connection with client ID 0x" << its_client
+ << " uid/gid= " << std::dec << bound_uid_ << "/" << bound_gid_
+ << " because of already existing connection using same client ID";
+ stop();
+ return;
+ } else if (!security::get()->check_credentials(
+ its_client, bound_uid_, bound_gid_)) {
+ VSOMEIP_WARNING << std::hex << "Client 0x" << its_host->get_client()
+ << " received client credentials from client 0x" << its_client
+ << " which violates the security policy : uid/gid="
+ << std::dec << bound_uid_ << "/" << bound_gid_;
+ its_server->remove_connection(its_client);
+ utility::release_client_id(its_client);
+ stop();
+ return;
+ } else {
+ set_bound_client(its_client);
+ }
+ } else
+#endif
+ {
+ set_bound_client(its_client);
+ its_server->add_connection(its_client, shared_from_this());
+ }
+ its_server->send_client_identifier(its_client);
+ assigned_client_ = true;
+ } else if (!its_server->is_routing_endpoint_ || assigned_client_) {
+#ifndef _WIN32
+ credentials_t its_credentials = std::make_pair(_uid, _gid);
+#else
+ credentials_t its_credentials = std::make_pair(ANY_UID, ANY_GID);
+#endif
its_host->on_message(&recv_buffer_[its_start],
uint32_t(its_end - its_start), its_server.get(),
- boost::asio::ip::address(), bound_client_);
-
- #if 0
- std::stringstream local_msg;
- local_msg << "lse::c<" << this << ">rcb::thunk: ";
- for (std::size_t i = its_start; i < its_end; i++)
- local_msg << std::setw(2) << std::setfill('0') << std::hex
- << (int) recv_buffer_[i] << " ";
- VSOMEIP_INFO << local_msg.str();
- #endif
- calculate_shrink_count();
- recv_buffer_size_ -= (its_end + 4 - its_iteration_gap);
- missing_capacity_ = 0;
- its_command_size = 0;
- found_message = true;
- its_iteration_gap = its_end + 4;
+ boost::asio::ip::address(), bound_client_, its_credentials);
} else {
- if (its_iteration_gap) {
- // Message not complete and not in front of the buffer!
- // Copy last part to front for consume in future receive_cbk call!
- for (size_t i = 0; i < recv_buffer_size_; ++i) {
- recv_buffer_[i] = recv_buffer_[i + its_iteration_gap];
- }
- // Still more capacity needed after shifting everything to front?
- if (missing_capacity_ &&
- missing_capacity_ <= recv_buffer_.capacity() - recv_buffer_size_) {
- missing_capacity_ = 0;
- }
+ VSOMEIP_WARNING << std::hex << "Client 0x" << its_host->get_client()
+ << " didn't receive VSOMEIP_ASSIGN_CLIENT as first message";
+ }
+ #if 0
+ std::stringstream local_msg;
+ local_msg << "lse::c<" << this << ">rcb::thunk: ";
+ for (std::size_t i = its_start; i < its_end; i++)
+ local_msg << std::setw(2) << std::setfill('0') << std::hex
+ << (int) recv_buffer_[i] << " ";
+ VSOMEIP_INFO << local_msg.str();
+ #endif
+ calculate_shrink_count();
+ recv_buffer_size_ -= (its_end + 4 - its_iteration_gap);
+ missing_capacity_ = 0;
+ its_command_size = 0;
+ found_message = true;
+ its_iteration_gap = its_end + 4;
+ } else {
+ if (its_iteration_gap) {
+ // Message not complete and not in front of the buffer!
+ // Copy last part to front for consume in future receive_cbk call!
+ for (size_t i = 0; i < recv_buffer_size_; ++i) {
+ recv_buffer_[i] = recv_buffer_[i + its_iteration_gap];
+ }
+ // Still more capacity needed after shifting everything to front?
+ if (missing_capacity_ &&
+ missing_capacity_ <= recv_buffer_.capacity() - recv_buffer_size_) {
+ missing_capacity_ = 0;
}
}
- } while (recv_buffer_size_ > 0 && found_message);
- }
+ }
+ } while (recv_buffer_size_ > 0 && found_message);
+ }
- if (_error == boost::asio::error::eof
- || _error == boost::asio::error::connection_reset) {
- stop();
- its_server->remove_connection(this);
- its_host->get_configuration()->remove_client_to_uid_gid_mapping(bound_client_);
- } else if (_error != boost::asio::error::bad_descriptor) {
- start();
- }
+ if (_error == boost::asio::error::eof
+ || _error == boost::asio::error::connection_reset) {
+ stop();
+ its_server->remove_connection(bound_client_);
+ security::get()->remove_client_to_uid_gid_mapping(bound_client_);
+ } else if (_error != boost::asio::error::bad_descriptor) {
+ start();
}
}
@@ -654,6 +780,12 @@ client_t local_server_endpoint_impl::connection::get_bound_client() const {
return bound_client_;
}
+#ifndef _WIN32
+void local_server_endpoint_impl::connection::set_bound_uid_gid(uid_t _uid, gid_t _gid) {
+ bound_uid_ = _uid;
+ bound_gid_ = _gid;
+}
+#endif
void local_server_endpoint_impl::connection::calculate_shrink_count() {
if (buffer_shrink_threshold_) {
@@ -717,9 +849,9 @@ void local_server_endpoint_impl::connection::handle_recv_buffer_exception(
}
its_message << " Last 16 Bytes captured: ";
- for (int i = 15; recv_buffer_size_ > 15 && i >= 0; i--) {
+ for (int i = 15; recv_buffer_size_ > 15u && i >= 0; i--) {
its_message << std::setw(2) << std::setfill('0') << std::hex
- << (int) (recv_buffer_[i]) << " ";
+ << (int) (recv_buffer_[static_cast<size_t>(i)]) << " ";
}
VSOMEIP_ERROR << its_message.str();
recv_buffer_.clear();
@@ -736,7 +868,7 @@ void local_server_endpoint_impl::connection::handle_recv_buffer_exception(
}
std::shared_ptr<local_server_endpoint_impl> its_server = server_.lock();
if (its_server) {
- its_server->remove_connection(this);
+ its_server->remove_connection(bound_client_);
}
}
@@ -762,25 +894,18 @@ void local_server_endpoint_impl::print_status() {
<< std::dec << queues_.size();
for (const auto &c : its_connections) {
#ifndef _WIN32
- std::string its_remote_path(c.first.path());
+ std::string its_remote_path; // TODO: construct the path
#else
std::string its_remote_path("");
#endif
- std::size_t its_data_size(0);
- std::size_t its_queue_size(0);
+
std::size_t its_recv_size(0);
{
std::unique_lock<std::mutex> c_s_lock(c.second->get_socket_lock());
its_recv_size = c.second->get_recv_buffer_capacity();
}
- auto found_queue = queues_.find(c.first);
- if (found_queue != queues_.end()) {
- its_queue_size = found_queue->second.second.size();
- its_data_size = found_queue->second.first;
- }
+
VSOMEIP_INFO << "status lse: client: " << its_remote_path
- << " queue: " << std::dec << its_queue_size
- << " data: " << std::dec << its_data_size
<< " recv_buffer: " << std::dec << its_recv_size;
}
}
@@ -791,8 +916,69 @@ std::string local_server_endpoint_impl::get_remote_information(
return _queue_iterator->first.address().to_string(ec) + ":"
+ std::to_string(_queue_iterator->first.port());
#else
- return _queue_iterator->first.path();
+ (void)_queue_iterator;
+ return "local";
+#endif
+}
+
+std::string local_server_endpoint_impl::get_remote_information(
+ const endpoint_type& _remote) const {
+#ifdef _WIN32
+ boost::system::error_code ec;
+ return _remote.address().to_string(ec) + ":"
+ + std::to_string(_remote.port());
+#else
+ (void)_remote;
+ return "local";
#endif
}
-} // namespace vsomeip
+bool local_server_endpoint_impl::is_reliable() const {
+ return false;
+}
+
+std::uint16_t local_server_endpoint_impl::get_local_port() const {
+ return 0;
+}
+
+bool local_server_endpoint_impl::check_packetizer_space(
+ queue_iterator_type _queue_iterator, message_buffer_ptr_t* _packetizer,
+ std::uint32_t _size) {
+ if ((*_packetizer)->size() + _size < (*_packetizer)->size()) {
+ VSOMEIP_ERROR << "Overflow in packetizer addition ~> abort sending!";
+ return false;
+ }
+ if ((*_packetizer)->size() + _size > max_message_size_
+ && !(*_packetizer)->empty()) {
+ _queue_iterator->second.second.push_back(*_packetizer);
+ _queue_iterator->second.first += (*_packetizer)->size();
+ *_packetizer = std::make_shared<message_buffer_t>();
+ }
+ return true;
+}
+
+void
+local_server_endpoint_impl::send_client_identifier(
+ const client_t &_client) {
+ byte_t its_command[] = {
+ VSOMEIP_ASSIGN_CLIENT_ACK,
+ 0x0, 0x0, // client
+ 0x2, 0x0, 0x0, 0x0, // size
+ 0x0, 0x0 // assigned client
+ };
+
+ std::memcpy(its_command+7, &_client, sizeof(_client));
+
+ send(its_command, sizeof(its_command));
+}
+
+
+bool local_server_endpoint_impl::tp_segmentation_enabled(
+ service_t _service, method_t _method) const {
+ (void)_service;
+ (void)_method;
+ return false;
+}
+
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/netlink_connector.cpp b/implementation/endpoints/src/netlink_connector.cpp
index 2f9e2e5..ce82e9f 100644
--- a/implementation/endpoints/src/netlink_connector.cpp
+++ b/implementation/endpoints/src/netlink_connector.cpp
@@ -11,12 +11,13 @@
#include <boost/asio/read.hpp>
#include<sstream>
+#include <vsomeip/internal/logger.hpp>
+
#include "../include/netlink_connector.hpp"
-#include "../../logging/include/logger.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
-void netlink_connector::register_net_if_changes_handler(net_if_changed_handler_t _handler) {
+void netlink_connector::register_net_if_changes_handler(const net_if_changed_handler_t& _handler) {
handler_ = _handler;
}
@@ -65,7 +66,9 @@ void netlink_connector::start() {
handler_(true, "n/a", true);
handler_(false, "n/a", true);
}
+#ifndef VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
return;
+#endif // VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
}
send_ifa_request();
@@ -109,8 +112,8 @@ void netlink_connector::receive_cbk(boost::system::error_code const &_error,
// New Address information
struct ifaddrmsg *ifa = (ifaddrmsg *)NLMSG_DATA(nlh);
if (has_address(ifa, IFA_PAYLOAD(nlh), address)) {
- net_if_index_for_address_ = ifa->ifa_index;
- auto its_if = net_if_flags_.find(ifa->ifa_index);
+ net_if_index_for_address_ = static_cast<int>(ifa->ifa_index);
+ auto its_if = net_if_flags_.find(static_cast<int>(ifa->ifa_index));
if (its_if != net_if_flags_.end()) {
if ((its_if->second & IFF_UP) &&
(its_if->second & IFF_RUNNING)) {
@@ -141,13 +144,13 @@ void netlink_connector::receive_cbk(boost::system::error_code const &_error,
if ((ifi->ifi_flags & IFF_UP) &&
(ifi->ifi_flags & IFF_RUNNING)) {
if (handler_) {
- if_indextoname(ifi->ifi_index,ifname);
+ if_indextoname(static_cast<unsigned int>(ifi->ifi_index),ifname);
handler_(true, ifname, true);
send_rt_request();
}
} else {
if (handler_) {
- if_indextoname(ifi->ifi_index,ifname);
+ if_indextoname(static_cast<unsigned int>(ifi->ifi_index),ifname);
handler_(true, ifname, false);
}
}
@@ -368,7 +371,7 @@ bool netlink_connector::check_sd_multicast_route_match(struct rtmsg* _routemsg,
inet_ntop(AF_INET, RTA_DATA(retrta), address, sizeof(address));
std::uint32_t netmask(0);
for (int i = 31; i > 31 - _routemsg->rtm_dst_len; i--) {
- netmask |= (1 << i);
+ netmask |= static_cast<std::uint32_t>(1 << i);
}
const std::uint32_t dst_addr = ntohl(*((std::uint32_t *)RTA_DATA(retrta)));
const std::uint32_t dst_net = (dst_addr & netmask);
@@ -380,18 +383,22 @@ bool netlink_connector::check_sd_multicast_route_match(struct rtmsg* _routemsg,
std::uint32_t netmask2[4] = {0,0,0,0};
for (int i = 127; i > 127 - _routemsg->rtm_dst_len; i--) {
if (i > 95) {
- netmask2[0] |= (1 << (i-96));
+ netmask2[0] |= static_cast<std::uint32_t>(1 << (i-96));
} else if (i > 63) {
- netmask2[1] |= (1 << (i-63));
+ netmask2[1] |= static_cast<std::uint32_t>(1 << (i-63));
} else if (i > 31) {
- netmask2[2] |= (1 << (i-32));
+ netmask2[2] |= static_cast<std::uint32_t>(1 << (i-32));
} else {
- netmask2[3] |= (1 << i);
+ netmask2[3] |= static_cast<std::uint32_t>(1 << i);
}
}
for (int i = 0; i < 4; i++) {
+#ifndef ANDROID
const std::uint32_t dst = ntohl((*(struct in6_addr*)RTA_DATA(retrta)).__in6_u.__u6_addr32[i]);
+#else
+ const std::uint32_t dst = ntohl((*(struct in6_addr*)RTA_DATA(retrta)).in6_u.u6_addr32[i]);
+#endif
const std::uint32_t sd = ntohl(reinterpret_cast<std::uint32_t*>(multicast_address_.to_v6().to_bytes().data())[i]);
const std::uint32_t dst_net = dst & netmask2[i];
const std::uint32_t sd_net = sd & netmask2[i];
@@ -403,7 +410,7 @@ bool netlink_connector::check_sd_multicast_route_match(struct rtmsg* _routemsg,
}
} else if (retrta->rta_type == RTA_OIF) {
if_index = *(int *)(RTA_DATA(retrta));
- if_indextoname(if_index,if_name);
+ if_indextoname(static_cast<unsigned int>(if_index),if_name);
} else if (retrta->rta_type == RTA_GATEWAY) {
size_t rtattr_length = RTA_PAYLOAD(retrta);
if (rtattr_length == 4) {
@@ -432,7 +439,7 @@ bool netlink_connector::check_sd_multicast_route_match(struct rtmsg* _routemsg,
return false;
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif
+#endif // #ifndef _WIN32
diff --git a/implementation/endpoints/src/server_endpoint_impl.cpp b/implementation/endpoints/src/server_endpoint_impl.cpp
index 915bfc9..06b61f4 100644
--- a/implementation/endpoints/src/server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/server_endpoint_impl.cpp
@@ -1,338 +1,764 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-#include <sstream>
-#include <limits>
-
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/ip/tcp.hpp>
-#include <boost/asio/ip/udp_ext.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-
-#include <vsomeip/defines.hpp>
-
-#include "../include/server_endpoint_impl.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/byteorder.hpp"
-#include "../../utility/include/utility.hpp"
-#include "../../service_discovery/include/defines.hpp"
-
-namespace vsomeip {
-
-template<typename Protocol>
-server_endpoint_impl<Protocol>::server_endpoint_impl(
- std::shared_ptr<endpoint_host> _host, endpoint_type _local,
- boost::asio::io_service &_io, std::uint32_t _max_message_size,
- configuration::endpoint_queue_limit_t _queue_limit)
- : endpoint_impl<Protocol>(_host, _local, _io, _max_message_size,
- _queue_limit),
- flush_timer_(_io) {
-}
-
-template<typename Protocol>
-server_endpoint_impl<Protocol>::~server_endpoint_impl() {
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::stop() {
- std::lock_guard<std::mutex> its_lock(mutex_);
- endpoint_impl<Protocol>::sending_blocked_ = true;
-}
-
-template<typename Protocol>
-bool server_endpoint_impl<Protocol>::is_client() const {
- return false;
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::restart(bool _force) {
- (void)_force;
- // intentionally left blank
-}
-
-template<typename Protocol>
-bool server_endpoint_impl<Protocol>::is_established() const {
- return true;
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::set_established(bool _established) { (void) _established; }
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::set_connected(bool _connected) {
- (void) _connected;
-}
-template<typename Protocol> bool server_endpoint_impl<Protocol>::send(const uint8_t *_data,
- uint32_t _size, bool _flush) {
-#if 0
- std::stringstream msg;
- msg << "sei::send ";
- for (uint32_t i = 0; i < _size; i++)
- msg << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- endpoint_type its_target;
- bool is_valid_target(false);
-
- if (VSOMEIP_SESSION_POS_MAX < _size) {
- std::lock_guard<std::mutex> its_lock(mutex_);
-
- if(endpoint_impl<Protocol>::sending_blocked_) {
- return false;
- }
-
- service_t its_service;
- std::memcpy(&its_service, &_data[VSOMEIP_SERVICE_POS_MIN],
- sizeof(service_t));
-
- client_t its_client;
- std::memcpy(&its_client, &_data[VSOMEIP_CLIENT_POS_MIN],
- sizeof(client_t));
- session_t its_session;
- std::memcpy(&its_session, &_data[VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
-
- clients_mutex_.lock();
- auto found_client = clients_.find(its_client);
- if (found_client != clients_.end()) {
- auto found_session = found_client->second.find(its_session);
- if (found_session != found_client->second.end()) {
- its_target = found_session->second;
- is_valid_target = true;
- found_client->second.erase(its_session);
- } else {
- VSOMEIP_WARNING << "server_endpoint::send: session_id 0x"
- << std::hex << its_session
- << " not found for client 0x" << its_client;
- const method_t its_method =
- VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == VSOMEIP_SD_SERVICE
- && its_method == VSOMEIP_SD_METHOD) {
- VSOMEIP_ERROR << "Clearing clients map as a request was "
- "received on SD port";
- clients_.clear();
- is_valid_target = get_default_target(its_service, its_target);
- }
- }
- } else {
- is_valid_target = get_default_target(its_service, its_target);
- }
- clients_mutex_.unlock();
-
- if (is_valid_target) {
- is_valid_target = send_intern(its_target, _data, _size, _flush);
- }
- }
- return is_valid_target;
-}
-
-template<typename Protocol>
-bool server_endpoint_impl<Protocol>::send(
- const std::vector<byte_t>& _cmd_header, const byte_t *_data,
- uint32_t _size, bool _flush) {
- (void) _cmd_header;
- (void) _data;
- (void) _size;
- (void) _flush;
- return false;
-}
-
-template<typename Protocol>
-bool server_endpoint_impl<Protocol>::send_intern(
- endpoint_type _target, const byte_t *_data, uint32_t _size,
- bool _flush) {
-
- message_buffer_ptr_t target_packetizer;
- queue_iterator_type target_queue_iterator;
-
- if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
- && _size > endpoint_impl<Protocol>::max_message_size_) {
- VSOMEIP_ERROR << "sei::send_intern: Dropping to big message (" << _size
- << " Bytes). Maximum allowed message size is: "
- << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
- return false;
- }
-
- auto found_packetizer = packetizer_.find(_target);
- if (found_packetizer != packetizer_.end()) {
- target_packetizer = found_packetizer->second;
- } else {
- target_packetizer = std::make_shared<message_buffer_t>();
- packetizer_.insert(std::make_pair(_target, target_packetizer));
- }
-
- target_queue_iterator = queues_.find(_target);
- if (target_queue_iterator == queues_.end()) {
- target_queue_iterator = queues_.insert(queues_.begin(),
- std::make_pair(
- _target,
- std::make_pair(std::size_t(0),
- std::deque<message_buffer_ptr_t>())
- ));
- }
-
- // TODO compare against value from configuration here
- const bool queue_size_zero_on_entry(target_queue_iterator->second.second.empty());
- if (target_packetizer->size() + _size
- > endpoint_impl<Protocol>::max_message_size_
- && !target_packetizer->empty()) {
- target_queue_iterator->second.second.push_back(target_packetizer);
- target_queue_iterator->second.first += target_packetizer->size();
- target_packetizer = std::make_shared<message_buffer_t>();
- packetizer_[_target] = target_packetizer;
- }
-
- if (endpoint_impl<Protocol>::queue_limit_ != QUEUE_SIZE_UNLIMITED
- && target_queue_iterator->second.first + _size >
- endpoint_impl<Protocol>::queue_limit_) {
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (_size >= VSOMEIP_SESSION_POS_MAX) {
- // this will yield wrong IDs for local communication as the commands
- // are prepended to the actual payload
- // it will print:
- // (lowbyte service ID + highbyte methoid)
- // [(Command + lowerbyte sender's client ID).
- // highbyte sender's client ID + lowbyte command size.
- // lowbyte methodid + highbyte vsomeipd length]
- its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
- _data[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
- _data[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN],
- _data[VSOMEIP_SESSION_POS_MAX]);
- }
- VSOMEIP_ERROR << "sei::send_intern: queue size limit (" << std::dec
- << endpoint_impl<Protocol>::queue_limit_
- << ") reached. Dropping message ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
- << " queue_size: " << std::dec << target_queue_iterator->second.first
- << " data size: " << std::dec << _size;
- return false;
- }
-
-
- target_packetizer->insert(target_packetizer->end(), _data, _data + _size);
-
- if (_flush) {
- flush_timer_.cancel();
- target_queue_iterator->second.second.push_back(target_packetizer);
- target_queue_iterator->second.first += target_packetizer->size();
- packetizer_[_target] = std::make_shared<message_buffer_t>();
- } else {
- std::chrono::milliseconds flush_timeout(VSOMEIP_DEFAULT_FLUSH_TIMEOUT);
- flush_timer_.expires_from_now(flush_timeout); // TODO: use configured value
- flush_timer_.async_wait(
- std::bind(&server_endpoint_impl<Protocol>::flush_cbk,
- this->shared_from_this(),
- _target,
- std::placeholders::_1));
- }
-
- if (queue_size_zero_on_entry && !target_queue_iterator->second.second.empty()) { // no writing in progress
- send_queued(target_queue_iterator);
- }
-
- return true;
-}
-
-template<typename Protocol>
-bool server_endpoint_impl<Protocol>::flush(
- endpoint_type _target) {
- bool is_flushed = false;
- std::lock_guard<std::mutex> its_lock(mutex_);
- auto queue_iterator = queues_.find(_target);
- if (queue_iterator != queues_.end() && !queue_iterator->second.second.empty()) {
- send_queued(queue_iterator);
- is_flushed = true;
- }
-
- return is_flushed;
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::connect_cbk(
- boost::system::error_code const &_error) {
- (void)_error;
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::send_cbk(
- const queue_iterator_type _queue_iterator,
- boost::system::error_code const &_error, std::size_t _bytes) {
- (void)_bytes;
-
- std::lock_guard<std::mutex> its_lock(mutex_);
- if (!_error) {
- _queue_iterator->second.first -=
- _queue_iterator->second.second.front()->size();
- _queue_iterator->second.second.pop_front();
- if (_queue_iterator->second.second.size() > 0) {
- send_queued(_queue_iterator);
- }
- } else {
- message_buffer_ptr_t its_buffer;
- if (_queue_iterator->second.second.size()) {
- its_buffer = _queue_iterator->second.second.front();
- }
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (its_buffer && its_buffer->size() > VSOMEIP_SESSION_POS_MAX) {
- its_service = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
- (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
- (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
- (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
- (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
- }
- // error: sending of outstanding responses isn't started again
- // delete remaining outstanding responses
- VSOMEIP_WARNING << "sei::send_cbk received error: " << _error.message()
- << " (" << std::dec << _error.value() << ") "
- << get_remote_information(_queue_iterator) << " "
- << std::dec << _queue_iterator->second.second.size() << " "
- << std::dec << _queue_iterator->second.first << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
- queues_.erase(_queue_iterator);
- }
-}
-
-template<typename Protocol>
-void server_endpoint_impl<Protocol>::flush_cbk(
- endpoint_type _target, const boost::system::error_code &_error_code) {
- if (!_error_code) {
- (void) flush(_target);
- }
-}
-
-// Instantiate template
-#ifndef _WIN32
-template class server_endpoint_impl<boost::asio::local::stream_protocol>;
-#endif
-template class server_endpoint_impl<boost::asio::ip::tcp>;
-template class server_endpoint_impl<boost::asio::ip::udp_ext>;
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+#include <sstream>
+#include <limits>
+#include <thread>
+#include <algorithm>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp_ext.hpp>
+#include <boost/asio/local/stream_protocol_ext.hpp>
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/server_endpoint_impl.hpp"
+#include "../include/endpoint_definition.hpp"
+
+#include "../../utility/include/byteorder.hpp"
+#include "../../utility/include/utility.hpp"
+#include "../../service_discovery/include/defines.hpp"
+
+namespace vsomeip_v3 {
+
+template<typename Protocol>
+server_endpoint_impl<Protocol>::server_endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host, endpoint_type _local,
+ boost::asio::io_service &_io, std::uint32_t _max_message_size,
+ configuration::endpoint_queue_limit_t _queue_limit,
+ const std::shared_ptr<configuration>& _configuration)
+ : endpoint_impl<Protocol>(_endpoint_host, _routing_host, _local, _io, _max_message_size,
+ _queue_limit, _configuration) {
+}
+
+template<typename Protocol>
+server_endpoint_impl<Protocol>::~server_endpoint_impl() {
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::prepare_stop(
+ endpoint::prepare_stop_handler_t _handler, service_t _service) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ bool queued_train(false);
+ if (_service == ANY_SERVICE) { // endpoint is shutting down completely
+ endpoint_impl<Protocol>::sending_blocked_ = true;
+ boost::system::error_code ec;
+ for (auto const& train_iter : trains_) {
+ train_iter.second->departure_timer_->cancel(ec);
+ if (train_iter.second->buffer_->size() > 0) {
+ auto target_queue_iter = queues_.find(train_iter.first);
+ if (target_queue_iter != queues_.end()) {
+ auto& its_qpair = target_queue_iter->second;
+ const bool queue_size_zero_on_entry(its_qpair.second.empty());
+ queue_train(target_queue_iter, train_iter.second,
+ queue_size_zero_on_entry);
+ queued_train = true;
+ }
+ }
+ }
+ } else {
+ for (auto const& train_iter : trains_) {
+ for (auto const& passenger_iter : train_iter.second->passengers_) {
+ if (passenger_iter.first == _service) {
+ // cancel departure timer
+ boost::system::error_code ec;
+ train_iter.second->departure_timer_->cancel(ec);
+ // queue train
+ auto target_queue_iter = queues_.find(train_iter.first);
+ if (target_queue_iter != queues_.end()) {
+ const auto& its_qpair = target_queue_iter->second;
+ const bool queue_size_zero_on_entry(its_qpair.second.empty());
+ queue_train(target_queue_iter, train_iter.second,
+ queue_size_zero_on_entry);
+ queued_train = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (!queued_train) {
+ if (_service == ANY_SERVICE) {
+ if (std::all_of(queues_.begin(), queues_.end(),
+ [&](const typename queue_type::value_type& q)
+ { return q.second.second.empty(); })) {
+ // nothing was queued and all queues are empty -> ensure cbk is called
+ auto ptr = this->shared_from_this();
+ endpoint_impl<Protocol>::service_.post([ptr, _handler, _service](){
+ _handler(ptr, _service);
+ });
+ } else {
+ prepare_stop_handlers_[_service] = _handler;
+ }
+ } else {
+ // check if any of the queues contains a message of to be stopped service
+ bool found_service_msg(false);
+ for (const auto& q : queues_) {
+ for (const auto& msg : q.second.second ) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*msg)[VSOMEIP_SERVICE_POS_MAX]);
+ if (its_service == _service) {
+ found_service_msg = true;
+ break;
+ }
+ }
+ if (found_service_msg) {
+ break;
+ }
+ }
+ if (found_service_msg) {
+ prepare_stop_handlers_[_service] = _handler;
+ } else { // no messages of the to be stopped service are or have been queued
+ auto ptr = this->shared_from_this();
+ endpoint_impl<Protocol>::service_.post([ptr, _handler, _service](){
+ _handler(ptr, _service);
+ });
+ }
+ }
+ } else {
+ prepare_stop_handlers_[_service] = _handler;
+ }
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::stop() {
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::is_client() const {
+ return false;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::restart(bool _force) {
+ (void)_force;
+ // intentionally left blank
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::is_established() const {
+ return true;
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::is_established_or_connected() const {
+ return true;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::set_established(bool _established) {
+ (void) _established;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::set_connected(bool _connected) {
+ (void) _connected;
+}
+
+template<typename Protocol>bool server_endpoint_impl<Protocol>::send(const uint8_t *_data,
+ uint32_t _size) {
+#if 0
+ std::stringstream msg;
+ msg << "sei::send ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ endpoint_type its_target;
+ bool is_valid_target(false);
+
+ if (VSOMEIP_SESSION_POS_MAX < _size) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ if(endpoint_impl<Protocol>::sending_blocked_) {
+ return false;
+ }
+
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SESSION_POS_MIN], _data[VSOMEIP_SESSION_POS_MAX]);
+
+ clients_mutex_.lock();
+ auto found_client = clients_.find(its_client);
+ if (found_client != clients_.end()) {
+ auto found_session = found_client->second.find(its_session);
+ if (found_session != found_client->second.end()) {
+ its_target = found_session->second;
+ is_valid_target = true;
+ found_client->second.erase(its_session);
+ } else {
+ VSOMEIP_WARNING << "server_endpoint::send: session_id 0x"
+ << std::hex << its_session
+ << " not found for client 0x" << its_client;
+ const method_t its_method =
+ VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == VSOMEIP_SD_SERVICE
+ && its_method == VSOMEIP_SD_METHOD) {
+ VSOMEIP_ERROR << "Clearing clients map as a request was "
+ "received on SD port";
+ clients_.clear();
+ is_valid_target = get_default_target(its_service, its_target);
+ }
+ }
+ } else {
+ is_valid_target = get_default_target(its_service, its_target);
+ }
+ clients_mutex_.unlock();
+
+ if (is_valid_target) {
+ is_valid_target = send_intern(its_target, _data, _size);
+ }
+ }
+ return is_valid_target;
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::send(
+ const std::vector<byte_t>& _cmd_header, const byte_t *_data,
+ uint32_t _size) {
+ (void) _cmd_header;
+ (void) _data;
+ (void) _size;
+ return false;
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::send_intern(
+ endpoint_type _target, const byte_t *_data, uint32_t _size) {
+
+ switch (check_message_size(_data, _size, _target)) {
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_WAS_SPLIT:
+ return true;
+ break;
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_TOO_BIG:
+ return false;
+ break;
+ case endpoint_impl<Protocol>::cms_ret_e::MSG_OK:
+ default:
+ break;
+ }
+ if (!prepare_stop_handlers_.empty()) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ if (prepare_stop_handlers_.find(its_service) != prepare_stop_handlers_.end()) {
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SESSION_POS_MIN], _data[VSOMEIP_SESSION_POS_MAX]);
+ VSOMEIP_WARNING << "server_endpoint::send: Service is stopping, ignoring message: ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ return false;
+ }
+ }
+
+ const queue_iterator_type target_queue_iterator = find_or_create_queue_unlocked(_target);
+
+ bool must_depart(false);
+
+#if 0
+ std::stringstream msg;
+ msg << "sei::send_intern: ";
+ for (uint32_t i = 0; i < _size; i++)
+ msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
+ VSOMEIP_DEBUG << msg.str();
+#endif
+ // STEP 1: determine the correct train
+ std::shared_ptr<train> target_train = find_or_create_train_unlocked(_target);
+
+ const bool queue_size_zero_on_entry(target_queue_iterator->second.second.empty());
+ if (!check_queue_limit(_data, _size, target_queue_iterator->second.first)) {
+ return false;
+ }
+ // STEP 2: Determine elapsed time and update the departure time and cancel the timer
+ target_train->update_departure_time_and_stop_departure();
+
+ // STEP 3: Get configured timings
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+
+ std::chrono::nanoseconds its_debouncing(0), its_retention(0);
+ if (its_service != VSOMEIP_SD_SERVICE && its_method != VSOMEIP_SD_METHOD) {
+ get_configured_times_from_endpoint(its_service, its_method,
+ &its_debouncing, &its_retention);
+ }
+
+ // STEP 4: Check if the passenger enters an empty train
+ const std::pair<service_t, method_t> its_identifier = std::make_pair(
+ its_service, its_method);
+ if (target_train->passengers_.empty()) {
+ target_train->departure_ = its_retention;
+ } else {
+ if (target_train->passengers_.end()
+ != target_train->passengers_.find(its_identifier)) {
+ must_depart = true;
+ } else {
+ // STEP 5: Check whether the current message fits into the current train
+ if (target_train->buffer_->size() + _size > endpoint_impl<Protocol>::max_message_size_) {
+ must_depart = true;
+ } else {
+ // STEP 6: Check debouncing time
+ if (its_debouncing > target_train->minimal_max_retention_time_) {
+ // train's latest departure would already undershot new
+ // passenger's debounce time
+ must_depart = true;
+ } else {
+ if (its_debouncing > target_train->departure_) {
+ // train departs earlier as the new passenger's debounce
+ // time allows
+ must_depart = true;
+ } else {
+ // STEP 7: Check maximum retention time
+ if (its_retention < target_train->minimal_debounce_time_) {
+ // train's earliest departure would already exceed
+ // the new passenger's retention time.
+ must_depart = true;
+ } else {
+ if (its_retention < target_train->departure_) {
+ target_train->departure_ = its_retention;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // STEP 8: if necessary, send current buffer and create a new one
+ if (must_depart) {
+ // STEP 8.1: check if debounce time would be undershot here if the train
+ // departs. Block sending until train is allowed to depart.
+ wait_until_debounce_time_reached(target_train);
+ queue_train(target_queue_iterator, target_train,
+ queue_size_zero_on_entry);
+ target_train->departure_ = its_retention;
+ }
+
+ // STEP 9: insert current message buffer
+ target_train->buffer_->insert(target_train->buffer_->end(), _data, _data + _size);
+ target_train->passengers_.insert(its_identifier);
+ // STEP 9.1: update the trains minimal debounce time if necessary
+ if (its_debouncing < target_train->minimal_debounce_time_) {
+ target_train->minimal_debounce_time_ = its_debouncing;
+ }
+ // STEP 9.2: update the trains minimal maximum retention time if necessary
+ if (its_retention < target_train->minimal_max_retention_time_) {
+ target_train->minimal_max_retention_time_ = its_retention;
+ }
+
+ // STEP 10: restart timer with current departure time
+#ifndef _WIN32
+ target_train->departure_timer_->expires_from_now(target_train->departure_);
+#else
+ target_train->departure_timer_->expires_from_now(
+ std::chrono::duration_cast<
+ std::chrono::steady_clock::duration>(target_train->departure_));
+#endif
+ target_train->departure_timer_->async_wait(
+ std::bind(&server_endpoint_impl<Protocol>::flush_cbk,
+ this->shared_from_this(), _target,
+ target_train, std::placeholders::_1));
+
+ return (true);
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::send_segments(
+ const tp::tp_split_messages_t &_segments, const endpoint_type &_target) {
+
+ if (_segments.size() == 0)
+ return;
+
+ const queue_iterator_type target_queue_iterator = find_or_create_queue_unlocked(_target);
+ const bool queue_size_zero_on_entry(target_queue_iterator->second.second.empty());
+
+ std::shared_ptr<train> target_train = find_or_create_train_unlocked(_target);
+ target_train->update_departure_time_and_stop_departure();
+
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*(_segments[0]))[VSOMEIP_SERVICE_POS_MIN], (*(_segments[0]))[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*(_segments[0]))[VSOMEIP_METHOD_POS_MIN], (*(_segments[0]))[VSOMEIP_METHOD_POS_MAX]);
+
+ std::chrono::nanoseconds its_debouncing(0), its_retention(0);
+ if (its_service != VSOMEIP_SD_SERVICE && its_method != VSOMEIP_SD_METHOD) {
+ get_configured_times_from_endpoint(its_service, its_method,
+ &its_debouncing, &its_retention);
+ }
+ // update the trains minimal debounce time if necessary
+ if (its_debouncing < target_train->minimal_debounce_time_) {
+ target_train->minimal_debounce_time_ = its_debouncing;
+ }
+ // update the trains minimal maximum retention time if necessary
+ if (its_retention < target_train->minimal_max_retention_time_) {
+ target_train->minimal_max_retention_time_ = its_retention;
+ }
+ // We only need to respect the debouncing. There is no need to wait for further
+ // messages as we will send several now anyway.
+ if (!target_train->passengers_.empty()) {
+ wait_until_debounce_time_reached(target_train);
+ queue_train(target_queue_iterator, target_train, queue_size_zero_on_entry);
+ }
+
+ const bool queue_size_still_zero(target_queue_iterator->second.second.empty());
+ for (const auto &s : _segments) {
+ target_queue_iterator->second.second.emplace_back(s);
+ target_queue_iterator->second.first += s->size();
+ }
+ if (queue_size_still_zero && !target_queue_iterator->second.second.empty()) { // no writing in progress
+ // respect minimal debounce time
+ wait_until_debounce_time_reached(target_train);
+ // ignore retention time and send immediately as the train is full anyway
+ send_queued(target_queue_iterator);
+ }
+ target_train->last_departure_ = std::chrono::steady_clock::now();
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::wait_until_debounce_time_reached(
+ const std::shared_ptr<train>& _train) const {
+ const std::chrono::nanoseconds time_since_last_departure =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now() - _train->last_departure_);
+
+ if (time_since_last_departure < _train->minimal_debounce_time_) {
+ std::this_thread::sleep_for(
+ _train->minimal_debounce_time_ - time_since_last_departure);
+ }
+}
+
+
+template<typename Protocol>
+typename endpoint_impl<Protocol>::cms_ret_e server_endpoint_impl<Protocol>::check_message_size(
+ const std::uint8_t * const _data, std::uint32_t _size,
+ const endpoint_type& _target) {
+ typename endpoint_impl<Protocol>::cms_ret_e ret(endpoint_impl<Protocol>::cms_ret_e::MSG_OK);
+ if (endpoint_impl<Protocol>::max_message_size_ != MESSAGE_SIZE_UNLIMITED
+ && _size > endpoint_impl<Protocol>::max_message_size_) {
+ if (endpoint_impl<Protocol>::is_supporting_someip_tp_ && _data != nullptr) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ if (tp_segmentation_enabled(its_service, its_method)) {
+ send_segments(tp::tp::tp_split_message(_data, _size), _target);
+ return endpoint_impl<Protocol>::cms_ret_e::MSG_WAS_SPLIT;
+ }
+ }
+ VSOMEIP_ERROR << "sei::send_intern: Dropping to big message (" << _size
+ << " Bytes). Maximum allowed message size is: "
+ << endpoint_impl<Protocol>::max_message_size_ << " Bytes.";
+ ret = endpoint_impl<Protocol>::cms_ret_e::MSG_TOO_BIG;
+ }
+ return ret;
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::check_queue_limit(const uint8_t *_data, std::uint32_t _size,
+ std::size_t _current_queue_size) const {
+ if (endpoint_impl<Protocol>::queue_limit_ != QUEUE_SIZE_UNLIMITED
+ && _current_queue_size + _size
+ > endpoint_impl<Protocol>::queue_limit_) {
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_size >= VSOMEIP_SESSION_POS_MAX) {
+ // this will yield wrong IDs for local communication as the commands
+ // are prepended to the actual payload
+ // it will print:
+ // (lowbyte service ID + highbyte methoid)
+ // [(Command + lowerbyte sender's client ID).
+ // highbyte sender's client ID + lowbyte command size.
+ // lowbyte methodid + highbyte vsomeip length]
+ its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN],
+ _data[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_ERROR << "sei::send_intern: queue size limit (" << std::dec
+ << endpoint_impl<Protocol>::queue_limit_
+ << ") reached. Dropping message ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
+ << " queue_size: " << std::dec << _current_queue_size
+ << " data size: " << std::dec << _size;
+ return false;
+ }
+ return true;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::queue_train(
+ const queue_iterator_type _queue_iterator,
+ const std::shared_ptr<train>& _train,
+ bool _queue_size_zero_on_entry) {
+ _queue_iterator->second.second.emplace_back(_train->buffer_);
+ _queue_iterator->second.first += _train->buffer_->size();
+ _train->last_departure_ = std::chrono::steady_clock::now();
+ _train->passengers_.clear();
+ _train->buffer_ = std::make_shared<message_buffer_t>();
+ _train->minimal_debounce_time_ = std::chrono::nanoseconds::max();
+ _train->minimal_max_retention_time_ = std::chrono::nanoseconds::max();
+ if (_queue_size_zero_on_entry && !_queue_iterator->second.second.empty()) { // no writing in progress
+ send_queued(_queue_iterator);
+ }
+}
+
+template<typename Protocol>
+typename server_endpoint_impl<Protocol>::queue_iterator_type
+server_endpoint_impl<Protocol>::find_or_create_queue_unlocked(const endpoint_type& _target) {
+ queue_iterator_type target_queue_iterator = queues_.find(_target);
+ if (target_queue_iterator == queues_.end()) {
+ target_queue_iterator = queues_.insert(queues_.begin(),
+ std::make_pair(
+ _target,
+ std::make_pair(std::size_t(0),
+ std::deque<message_buffer_ptr_t>())
+ ));
+ }
+ return target_queue_iterator;
+}
+
+template<typename Protocol>
+std::shared_ptr<train> server_endpoint_impl<Protocol>::find_or_create_train_unlocked(
+ const endpoint_type& _target) {
+ auto train_iter = trains_.find(_target);
+ if (train_iter == trains_.end()) {
+ train_iter = trains_.insert(trains_.begin(),
+ std::make_pair(_target, std::make_shared<train>(this->service_)));
+ }
+ return train_iter->second;
+}
+
+template<typename Protocol>
+bool server_endpoint_impl<Protocol>::flush(
+ endpoint_type _target,
+ const std::shared_ptr<train>& _train) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ bool is_flushed = false;
+ if (!_train->buffer_->empty()) {
+ const queue_iterator_type target_queue_iterator = queues_.find(_target);
+ if (target_queue_iterator != queues_.end()) {
+ const bool queue_size_zero_on_entry(target_queue_iterator->second.second.empty());
+ queue_train(target_queue_iterator, _train, queue_size_zero_on_entry);
+ is_flushed = true;
+ } else {
+ std::stringstream ss;
+ ss << "sei::flush couldn't find target queue, won't queue train to: "
+ << get_remote_information(_target) << " passengers: ";
+ for (const auto& p : _train->passengers_) {
+ ss << "[" << std::hex << std::setw(4) << std::setfill('0')
+ << p.first << ":" << p.second << "] ";
+ }
+ VSOMEIP_WARNING << ss.str();
+ }
+ }
+ return is_flushed;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::connect_cbk(
+ boost::system::error_code const &_error) {
+ (void)_error;
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::send_cbk(
+ const queue_iterator_type _queue_iterator,
+ boost::system::error_code const &_error, std::size_t _bytes) {
+ (void)_bytes;
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ auto check_if_all_msgs_for_stopped_service_are_sent = [&]() {
+ bool found_service_msg(false);
+ service_t its_stopped_service(ANY_SERVICE);
+ for (auto stp_hndlr_iter = prepare_stop_handlers_.begin();
+ stp_hndlr_iter != prepare_stop_handlers_.end();) {
+ its_stopped_service = stp_hndlr_iter->first;
+ if (its_stopped_service == ANY_SERVICE) {
+ ++stp_hndlr_iter;
+ continue;
+ }
+ for (const auto& q : queues_) {
+ for (const auto& msg : q.second.second ) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*msg)[VSOMEIP_SERVICE_POS_MAX]);
+ if (its_service == its_stopped_service) {
+ found_service_msg = true;
+ break;
+ }
+ }
+ if (found_service_msg) {
+ break;
+ }
+ }
+ if (found_service_msg) {
+ ++stp_hndlr_iter;
+ } else { // all messages of the to be stopped service have been sent
+ auto handler = stp_hndlr_iter->second;
+ auto ptr = this->shared_from_this();
+ #ifndef _WIN32
+ endpoint_impl<Protocol>::
+ #endif
+ service_.post([ptr, handler, its_stopped_service](){
+ handler(ptr, its_stopped_service);
+ });
+ stp_hndlr_iter = prepare_stop_handlers_.erase(stp_hndlr_iter);
+ }
+ }
+ };
+
+ auto check_if_all_queues_are_empty = [&](){
+ if (prepare_stop_handlers_.size() > 1) {
+ // before the endpoint was stopped completely other
+ // prepare_stop_handlers have been queued ensure to call them as well
+ check_if_all_msgs_for_stopped_service_are_sent();
+ }
+ if (std::all_of(queues_.begin(), queues_.end(), [&]
+ #ifndef _WIN32
+ (const typename queue_type::value_type& q)
+ #else
+ (const std::pair<endpoint_type,std::pair<size_t, std::deque<message_buffer_ptr_t>>>& q)
+ #endif
+ { return q.second.second.empty(); })) {
+ // all outstanding response have been sent.
+ auto found_cbk = prepare_stop_handlers_.find(ANY_SERVICE);
+ if (found_cbk != prepare_stop_handlers_.end()) {
+ auto handler = found_cbk->second;
+ auto ptr = this->shared_from_this();
+ #ifndef _WIN32
+ endpoint_impl<Protocol>::
+ #endif
+ service_.post([ptr, handler](){
+ handler(ptr, ANY_SERVICE);
+ });
+ prepare_stop_handlers_.erase(found_cbk);
+ }
+ }
+ };
+
+ auto& its_qpair = _queue_iterator->second;
+ if (!_error) {
+ its_qpair.first -= its_qpair.second.front()->size();
+ its_qpair.second.pop_front();
+
+ if (!prepare_stop_handlers_.empty() && !endpoint_impl<Protocol>::sending_blocked_) {
+ // only one service instance is stopped
+ check_if_all_msgs_for_stopped_service_are_sent();
+ }
+
+ if (its_qpair.second.size() > 0) {
+ send_queued(_queue_iterator);
+ } else if (!prepare_stop_handlers_.empty() && endpoint_impl<Protocol>::sending_blocked_) {
+ // endpoint is shutting down completely
+ queues_.erase(_queue_iterator);
+ check_if_all_queues_are_empty();
+ }
+ } else {
+ message_buffer_ptr_t its_buffer;
+ if (_queue_iterator->second.second.size()) {
+ its_buffer = _queue_iterator->second.second.front();
+ }
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (its_buffer && its_buffer->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
+ (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
+ (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ // error: sending of outstanding responses isn't started again
+ // delete remaining outstanding responses
+ VSOMEIP_WARNING << "sei::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information(_queue_iterator) << " "
+ << std::dec << _queue_iterator->second.second.size() << " "
+ << std::dec << _queue_iterator->second.first << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ queues_.erase(_queue_iterator);
+ if (!prepare_stop_handlers_.empty()) {
+ if (endpoint_impl<Protocol>::sending_blocked_) {
+ // endpoint is shutting down completely, ensure to call
+ // prepare_stop_handlers even in error cases
+ check_if_all_queues_are_empty();
+ } else {
+ // only one service instance is stopped
+ check_if_all_msgs_for_stopped_service_are_sent();
+ }
+ }
+
+ }
+}
+
+template<typename Protocol>
+void server_endpoint_impl<Protocol>::flush_cbk(
+ endpoint_type _target,
+ const std::shared_ptr<train>& _train, const boost::system::error_code &_error_code) {
+ if (!_error_code) {
+ (void) flush(_target, _train);
+ }
+}
+
+template<typename Protocol>
+size_t server_endpoint_impl<Protocol>::get_queue_size() const {
+ size_t its_queue_size(0);
+
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (const auto q : queues_) {
+ its_queue_size += q.second.second.size();
+ }
+ }
+
+ return its_queue_size;
+}
+
+// Instantiate template
+#ifndef _WIN32
+template class server_endpoint_impl<boost::asio::local::stream_protocol_ext>;
+#endif
+template class server_endpoint_impl<boost::asio::ip::tcp>;
+template class server_endpoint_impl<boost::asio::ip::udp_ext>;
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
index 41254f6..2c56521 100644
--- a/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_client_endpoint_impl.cpp
@@ -1,253 +1,268 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-
-#include <boost/asio/write.hpp>
-
-#include <vsomeip/constants.hpp>
-#include <vsomeip/defines.hpp>
-
-#include "../include/endpoint_host.hpp"
-#include "../include/tcp_client_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/utility.hpp"
-#include "../../utility/include/byteorder.hpp"
-#include "../../configuration/include/internal.hpp"
-
-
-namespace ip = boost::asio::ip;
-
-namespace vsomeip {
-
-tcp_client_endpoint_impl::tcp_client_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _tcp_restart_aborts_max,
- std::uint32_t _tcp_connect_time_max)
- : tcp_client_endpoint_base_impl(_host, _local, _remote, _io,
- _max_message_size, _queue_limit),
- recv_buffer_size_initial_(VSOMEIP_SOMEIP_HEADER_SIZE),
- recv_buffer_(std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0)),
- shrink_count_(0),
- buffer_shrink_threshold_(_buffer_shrink_threshold),
- remote_address_(_remote.address()),
- remote_port_(_remote.port()),
- last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)),
- send_timeout_(_send_timeout),
- send_timeout_warning_(_send_timeout / 2),
- tcp_restart_aborts_max_(_tcp_restart_aborts_max),
- tcp_connect_time_max_(_tcp_connect_time_max),
- aborted_restart_count_(0) {
- is_supporting_magic_cookies_ = true;
-}
-
-tcp_client_endpoint_impl::~tcp_client_endpoint_impl() {
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- its_host->release_port(local_.port(), true);
- }
-}
-
-bool tcp_client_endpoint_impl::is_local() const {
- return false;
-}
-
-void tcp_client_endpoint_impl::start() {
- connect();
-}
-
-void tcp_client_endpoint_impl::restart(bool _force) {
- if (!_force && state_ == cei_state_e::CONNECTING) {
- std::chrono::steady_clock::time_point its_current
- = std::chrono::steady_clock::now();
- long its_connect_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
- its_current - connect_timepoint_).count();
- if (aborted_restart_count_ < tcp_restart_aborts_max_
- && its_connect_duration < tcp_connect_time_max_) {
- aborted_restart_count_++;
- return;
- } else {
- VSOMEIP_WARNING << "tce::restart: maximum number of aborted restarts ["
- << tcp_restart_aborts_max_ << "] reached! its_connect_duration: "
- << its_connect_duration;
- }
- }
- state_ = cei_state_e::CONNECTING;
- std::string address_port_local;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- address_port_local = get_address_port_local();
- shutdown_and_close_socket_unlocked(true);
- recv_buffer_ = std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0);
- }
- was_not_connected_ = true;
- reconnect_counter_ = 0;
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- for (const auto&m : queue_) {
- const service_t its_service = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_SERVICE_POS_MIN],
- (*m)[VSOMEIP_SERVICE_POS_MAX]);
- const method_t its_method = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_METHOD_POS_MIN],
- (*m)[VSOMEIP_METHOD_POS_MAX]);
- const client_t its_client = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_CLIENT_POS_MIN],
- (*m)[VSOMEIP_CLIENT_POS_MAX]);
- const session_t its_session = VSOMEIP_BYTES_TO_WORD(
- (*m)[VSOMEIP_SESSION_POS_MIN],
- (*m)[VSOMEIP_SESSION_POS_MAX]);
- VSOMEIP_WARNING << "tce::restart: dropping message: "
- << "remote:" << get_address_port_remote() << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
- << " size: " << std::dec << m->size();
- }
- queue_.clear();
- queue_size_ = 0;
- }
- VSOMEIP_WARNING << "tce::restart: local: " << address_port_local
- << " remote: " << get_address_port_remote();
- start_connect_timer();
-}
-
-void tcp_client_endpoint_impl::connect() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::system::error_code its_error;
- socket_->open(remote_.protocol(), its_error);
-
- if (!its_error || its_error == boost::asio::error::already_open) {
- // Nagle algorithm off
- socket_->set_option(ip::tcp::no_delay(true), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't disable "
- << "Nagle algorithm: " << its_error.message()
- << " remote:" << get_address_port_remote();
- }
-
- socket_->set_option(boost::asio::socket_base::keep_alive(true), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
- << "keep_alive: " << its_error.message()
- << " remote:" << get_address_port_remote();
- }
-
- // Enable SO_REUSEADDR to avoid bind problems with services going offline
- // and coming online again and the user has specified only a small number
- // of ports in the clients section for one service instance
- socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
- << "SO_REUSEADDR: " << its_error.message()
- << " remote:" << get_address_port_remote();
- }
- socket_->set_option(boost::asio::socket_base::linger(true, 0), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
- << "SO_LINGER: " << its_error.message()
- << " remote:" << get_address_port_remote();
- }
- // In case a client endpoint port was configured,
- // bind to it before connecting
- if (local_.port() != ILLEGAL_PORT) {
- boost::system::error_code its_bind_error;
- socket_->bind(local_, its_bind_error);
- if(its_bind_error) {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
- "Error binding socket: " << its_bind_error.message()
- << " remote:" << get_address_port_remote();
- try {
- // don't connect on bind error to avoid using a random port
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+
+#include <boost/asio/write.hpp>
+
+#include <vsomeip/constants.hpp>
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/endpoint_host.hpp"
+#include "../../routing/include/routing_host.hpp"
+#include "../include/tcp_client_endpoint_impl.hpp"
+#include "../../utility/include/utility.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+namespace ip = boost::asio::ip;
+
+namespace vsomeip_v3 {
+
+tcp_client_endpoint_impl::tcp_client_endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration)
+ : tcp_client_endpoint_base_impl(_endpoint_host, _routing_host, _local,
+ _remote, _io,
+ _configuration->get_max_message_size_reliable(
+ _remote.address().to_string(),
+ _remote.port()),
+ _configuration->get_endpoint_queue_limit(
+ _remote.address().to_string(),
+ _remote.port()),
+ _configuration),
+ recv_buffer_size_initial_(VSOMEIP_SOMEIP_HEADER_SIZE),
+ recv_buffer_(std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0)),
+ shrink_count_(0),
+ buffer_shrink_threshold_(configuration_->get_buffer_shrink_threshold()),
+ remote_address_(_remote.address()),
+ remote_port_(_remote.port()),
+ last_cookie_sent_(std::chrono::steady_clock::now() - std::chrono::seconds(11)),
+ // send timeout after 2/3 of configured ttl, warning after 1/3
+ send_timeout_(configuration_->get_sd_ttl() * 666),
+ send_timeout_warning_(send_timeout_ / 2),
+ tcp_restart_aborts_max_(configuration_->get_max_tcp_restart_aborts()),
+ tcp_connect_time_max_(configuration_->get_max_tcp_connect_time()),
+ aborted_restart_count_(0) {
+ is_supporting_magic_cookies_ = true;
+}
+
+tcp_client_endpoint_impl::~tcp_client_endpoint_impl() {
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ its_host->release_port(local_.port(), true);
+ }
+}
+
+bool tcp_client_endpoint_impl::is_local() const {
+ return false;
+}
+
+void tcp_client_endpoint_impl::start() {
+ connect();
+}
+
+void tcp_client_endpoint_impl::restart(bool _force) {
+ if (!_force && state_ == cei_state_e::CONNECTING) {
+ std::chrono::steady_clock::time_point its_current
+ = std::chrono::steady_clock::now();
+ long its_connect_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+ its_current - connect_timepoint_).count();
+ if (aborted_restart_count_ < tcp_restart_aborts_max_
+ && its_connect_duration < tcp_connect_time_max_) {
+ aborted_restart_count_++;
+ return;
+ } else {
+ VSOMEIP_WARNING << "tce::restart: maximum number of aborted restarts ["
+ << tcp_restart_aborts_max_ << "] reached! its_connect_duration: "
+ << its_connect_duration;
+ }
+ }
+ state_ = cei_state_e::CONNECTING;
+ std::string address_port_local;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ address_port_local = get_address_port_local();
+ shutdown_and_close_socket_unlocked(true);
+ recv_buffer_ = std::make_shared<message_buffer_t>(recv_buffer_size_initial_, 0);
+ }
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (const auto&m : queue_) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SERVICE_POS_MIN],
+ (*m)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_METHOD_POS_MIN],
+ (*m)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_CLIENT_POS_MIN],
+ (*m)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*m)[VSOMEIP_SESSION_POS_MIN],
+ (*m)[VSOMEIP_SESSION_POS_MAX]);
+ VSOMEIP_WARNING << "tce::restart: dropping message: "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]"
+ << " size: " << std::dec << m->size();
+ }
+ queue_.clear();
+ queue_size_ = 0;
+ }
+ VSOMEIP_WARNING << "tce::restart: local: " << address_port_local
+ << " remote: " << get_address_port_remote();
+ start_connect_timer();
+}
+
+void tcp_client_endpoint_impl::connect() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::system::error_code its_error;
+ socket_->open(remote_.protocol(), its_error);
+
+ if (!its_error || its_error == boost::asio::error::already_open) {
+ // Nagle algorithm off
+ socket_->set_option(ip::tcp::no_delay(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't disable "
+ << "Nagle algorithm: " << its_error.message()
+ << " remote:" << get_address_port_remote();
+ }
+
+ socket_->set_option(boost::asio::socket_base::keep_alive(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
+ << "keep_alive: " << its_error.message()
+ << " remote:" << get_address_port_remote();
+ }
+
+ // Enable SO_REUSEADDR to avoid bind problems with services going offline
+ // and coming online again and the user has specified only a small number
+ // of ports in the clients section for one service instance
+ socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
+ << "SO_REUSEADDR: " << its_error.message()
+ << " remote:" << get_address_port_remote();
+ }
+ socket_->set_option(boost::asio::socket_base::linger(true, 0), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: couldn't enable "
+ << "SO_LINGER: " << its_error.message()
+ << " remote:" << get_address_port_remote();
+ }
+
+#ifndef _WIN32
+ // If specified, bind to device
+ std::string its_device(configuration_->get_device());
+ if (its_device != "") {
+ if (setsockopt(socket_->native_handle(),
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ VSOMEIP_WARNING << "TCP Client: Could not bind to device \"" << its_device << "\"";
+ }
+ }
+#endif
+
+ // In case a client endpoint port was configured,
+ // bind to it before connecting
+ if (local_.port() != ILLEGAL_PORT) {
+ boost::system::error_code its_bind_error;
+ socket_->bind(local_, its_bind_error);
+ if(its_bind_error) {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: "
+ "Error binding socket: " << its_bind_error.message()
+ << " remote:" << get_address_port_remote();
+ try {
+ // don't connect on bind error to avoid using a random port
strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
- shared_from_this(), its_bind_error));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << "tcp_client_endpoint_impl::connect: "
- << e.what() << " remote:" << get_address_port_remote();
- }
- return;
- }
- }
- state_ = cei_state_e::CONNECTING;
- connect_timepoint_ = std::chrono::steady_clock::now();
- aborted_restart_count_ = 0;
- socket_->async_connect(
- remote_,
+ shared_from_this(), its_bind_error));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "tcp_client_endpoint_impl::connect: "
+ << e.what() << " remote:" << get_address_port_remote();
+ }
+ return;
+ }
+ }
+ state_ = cei_state_e::CONNECTING;
+ connect_timepoint_ = std::chrono::steady_clock::now();
+ aborted_restart_count_ = 0;
+ socket_->async_connect(
+ remote_,
strand_.wrap(
std::bind(
&tcp_client_endpoint_base_impl::connect_cbk,
shared_from_this(),
std::placeholders::_1
)
- )
- );
- } else {
- VSOMEIP_WARNING << "tcp_client_endpoint::connect: Error opening socket: "
- << its_error.message() << " remote:" << get_address_port_remote();
- strand_.post(std::bind(&tcp_client_endpoint_base_impl::connect_cbk,
- shared_from_this(), its_error));
- }
-}
-
-void tcp_client_endpoint_impl::receive() {
- message_buffer_ptr_t its_recv_buffer;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- its_recv_buffer = recv_buffer_;
- }
- receive(its_recv_buffer, 0, 0);
-}
-
-void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
- std::size_t _recv_buffer_size,
- std::size_t _missing_capacity) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if(socket_->is_open()) {
- const std::size_t its_capacity(_recv_buffer->capacity());
- size_t buffer_size = its_capacity - _recv_buffer_size;
- try {
- if (_missing_capacity) {
- if (_missing_capacity > MESSAGE_SIZE_UNLIMITED) {
- VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!";
- return;
- }
- const std::size_t its_required_capacity(_recv_buffer_size + _missing_capacity);
- if (its_capacity < its_required_capacity) {
- _recv_buffer->reserve(its_required_capacity);
- _recv_buffer->resize(its_required_capacity, 0x0);
- if (_recv_buffer->size() > 1048576) {
- VSOMEIP_INFO << "tce: recv_buffer size is: " <<
- _recv_buffer->size()
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- }
- }
- buffer_size = _missing_capacity;
- } else if (buffer_shrink_threshold_
- && shrink_count_ > buffer_shrink_threshold_
- && _recv_buffer_size == 0) {
- _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
- _recv_buffer->shrink_to_fit();
- buffer_size = recv_buffer_size_initial_;
- shrink_count_ = 0;
- }
- } catch (const std::exception &e) {
- handle_recv_buffer_exception(e, _recv_buffer, _recv_buffer_size);
- // don't start receiving again
- return;
- }
- socket_->async_receive(
- boost::asio::buffer(&(*_recv_buffer)[_recv_buffer_size], buffer_size),
+ )
+ );
+ } else {
+ VSOMEIP_WARNING << "tcp_client_endpoint::connect: Error opening socket: "
+ << its_error.message() << " remote:" << get_address_port_remote();
+ strand_.post(std::bind(&tcp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(), its_error));
+ }
+}
+
+void tcp_client_endpoint_impl::receive() {
+ message_buffer_ptr_t its_recv_buffer;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ its_recv_buffer = recv_buffer_;
+ }
+ receive(its_recv_buffer, 0, 0);
+}
+
+void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
+ std::size_t _recv_buffer_size,
+ std::size_t _missing_capacity) {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if(socket_->is_open()) {
+ const std::size_t its_capacity(_recv_buffer->capacity());
+ size_t buffer_size = its_capacity - _recv_buffer_size;
+ try {
+ if (_missing_capacity) {
+ if (_missing_capacity > MESSAGE_SIZE_UNLIMITED) {
+ VSOMEIP_ERROR << "Missing receive buffer capacity exceeds allowed maximum!";
+ return;
+ }
+ const std::size_t its_required_capacity(_recv_buffer_size + _missing_capacity);
+ if (its_capacity < its_required_capacity) {
+ _recv_buffer->reserve(its_required_capacity);
+ _recv_buffer->resize(its_required_capacity, 0x0);
+ if (_recv_buffer->size() > 1048576) {
+ VSOMEIP_INFO << "tce: recv_buffer size is: " <<
+ _recv_buffer->size()
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ }
+ buffer_size = _missing_capacity;
+ } else if (buffer_shrink_threshold_
+ && shrink_count_ > buffer_shrink_threshold_
+ && _recv_buffer_size == 0) {
+ _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
+ _recv_buffer->shrink_to_fit();
+ buffer_size = recv_buffer_size_initial_;
+ shrink_count_ = 0;
+ }
+ } catch (const std::exception &e) {
+ handle_recv_buffer_exception(e, _recv_buffer, _recv_buffer_size);
+ // don't start receiving again
+ return;
+ }
+ socket_->async_receive(
+ boost::asio::buffer(&(*_recv_buffer)[_recv_buffer_size], buffer_size),
strand_.wrap(
std::bind(
&tcp_client_endpoint_impl::receive_cbk,
@@ -257,595 +272,618 @@ void tcp_client_endpoint_impl::receive(message_buffer_ptr_t _recv_buffer,
_recv_buffer,
_recv_buffer_size
)
- )
- );
- }
-}
-
-void tcp_client_endpoint_impl::send_queued() {
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
- const service_t its_service = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
- (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
- const method_t its_method = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
- (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
- const client_t its_client = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
- (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
- const session_t its_session = VSOMEIP_BYTES_TO_WORD(
- (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
- (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
-
- if (has_enabled_magic_cookies_) {
- const std::chrono::steady_clock::time_point now =
- std::chrono::steady_clock::now();
- if (std::chrono::duration_cast<std::chrono::milliseconds>(
- now - last_cookie_sent_) > std::chrono::milliseconds(10000)) {
- send_magic_cookie(its_buffer);
- last_cookie_sent_ = now;
- }
- }
-
-
-#if 0
- std::stringstream msg;
- msg << "tcei<" << remote_.address() << ":"
- << std::dec << remote_.port() << ">::sq: ";
- for (std::size_t i = 0; i < its_buffer->size(); i++)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*its_buffer)[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (socket_->is_open()) {
- boost::asio::async_write(
- *socket_,
- boost::asio::buffer(*its_buffer),
- std::bind(&tcp_client_endpoint_impl::write_completion_condition,
- std::static_pointer_cast<tcp_client_endpoint_impl>(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer->size(),
- its_service, its_method, its_client, its_session,
- std::chrono::steady_clock::now()),
- std::bind(
- &tcp_client_endpoint_base_impl::send_cbk,
- shared_from_this(),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer
- )
- );
- }
- }
-}
-
-bool tcp_client_endpoint_impl::get_remote_address(
- boost::asio::ip::address &_address) const {
- if (remote_address_.is_unspecified()) {
- return false;
- }
- _address = remote_address_;
- return true;
-}
-
-void tcp_client_endpoint_impl::set_local_port() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::system::error_code its_error;
- if (socket_->is_open()) {
- endpoint_type its_endpoint = socket_->local_endpoint(its_error);
- if (!its_error) {
- local_port_ = its_endpoint.port();
- } else {
- VSOMEIP_WARNING << "tcp_client_endpoint_impl::set_local_port() "
- << " couldn't get local_endpoint: " << its_error.message();
- }
- }
-}
-
-std::size_t tcp_client_endpoint_impl::write_completion_condition(
- const boost::system::error_code& _error, std::size_t _bytes_transferred,
- std::size_t _bytes_to_send, service_t _service, method_t _method,
- client_t _client, session_t _session,
- std::chrono::steady_clock::time_point _start) {
-
- if (_error) {
- VSOMEIP_ERROR << "tce::write_completion_condition: "
- << _error.message() << "(" << std::dec << _error.value()
- << ") bytes transferred: " << std::dec << _bytes_transferred
- << " bytes to sent: " << std::dec << _bytes_to_send << " "
- << "remote:" << get_address_port_remote() << " ("
- << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _method << "."
- << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
- return 0;
- }
-
- std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
- std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
- if (passed > send_timeout_warning_) {
- if (passed > send_timeout_) {
- VSOMEIP_ERROR << "tce::write_completion_condition: "
- << _error.message() << "(" << std::dec << _error.value()
- << ") took longer than " << std::dec << send_timeout_.count()
- << "ms bytes transferred: " << std::dec << _bytes_transferred
- << " bytes to sent: " << std::dec << _bytes_to_send << " "
- << "remote:" << get_address_port_remote() << " ("
- << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _method << "."
- << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
- } else {
- VSOMEIP_WARNING << "tce::write_completion_condition: "
- << _error.message() << "(" << std::dec << _error.value()
- << ") took longer than " << std::dec << send_timeout_warning_.count()
- << "ms bytes transferred: " << std::dec << _bytes_transferred
- << " bytes to sent: " << std::dec << _bytes_to_send << " "
- << "remote:" << get_address_port_remote() << " ("
- << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _method << "."
- << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
- }
- }
- return _bytes_to_send - _bytes_transferred;
-}
-
-std::uint16_t tcp_client_endpoint_impl::get_remote_port() const {
- return remote_port_;
-}
-
-bool tcp_client_endpoint_impl::is_reliable() const {
- return true;
-}
-
-bool tcp_client_endpoint_impl::is_magic_cookie(const message_buffer_ptr_t& _recv_buffer,
- size_t _offset) const {
- return (0 == std::memcmp(SERVICE_COOKIE, &(*_recv_buffer)[_offset], sizeof(SERVICE_COOKIE)));
-}
-
-void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) {
- if (max_message_size_ == MESSAGE_SIZE_UNLIMITED
- || max_message_size_ - _buffer->size() >=
- VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {
- _buffer->insert(
- _buffer->begin(),
- CLIENT_COOKIE,
- CLIENT_COOKIE + sizeof(CLIENT_COOKIE)
- );
- queue_size_ += sizeof(CLIENT_COOKIE);
- } else {
- VSOMEIP_WARNING << "Packet full. Cannot insert magic cookie!";
- }
-}
-
-void tcp_client_endpoint_impl::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes,
- message_buffer_ptr_t _recv_buffer, std::size_t _recv_buffer_size) {
- if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- return;
- }
-#if 0
- std::stringstream msg;
- msg << "cei::rcb (" << _error.message() << "): ";
- for (std::size_t i = 0; i < _bytes + _recv_buffer_size; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int) (_recv_buffer)[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- std::unique_lock<std::mutex> its_lock(socket_mutex_);
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- std::uint32_t its_missing_capacity(0);
- if (!_error && 0 < _bytes) {
- if (_recv_buffer_size + _bytes < _recv_buffer_size) {
- VSOMEIP_ERROR << "receive buffer overflow in tcp client endpoint ~> abort!";
- return;
- }
- _recv_buffer_size += _bytes;
-
- size_t its_iteration_gap = 0;
- bool has_full_message(false);
- do {
- uint64_t read_message_size
- = utility::get_message_size(&(*_recv_buffer)[its_iteration_gap],
- _recv_buffer_size);
- if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
- VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
- return;
- }
- uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
- has_full_message = (current_message_size > VSOMEIP_RETURN_CODE_POS
- && current_message_size <= _recv_buffer_size);
- if (has_full_message) {
- bool needs_forwarding(true);
- if (is_magic_cookie(_recv_buffer, its_iteration_gap)) {
- has_enabled_magic_cookies_ = true;
- } else {
- if (has_enabled_magic_cookies_) {
- uint32_t its_offset = find_magic_cookie(&(*_recv_buffer)[its_iteration_gap],
- (uint32_t) _recv_buffer_size);
- if (its_offset < current_message_size) {
- VSOMEIP_ERROR << "Message includes Magic Cookie. Ignoring it.";
- current_message_size = its_offset;
- needs_forwarding = false;
- }
- }
- }
- if (needs_forwarding) {
- if (!has_enabled_magic_cookies_) {
- its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
- current_message_size, this,
- boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT,
- remote_address_,
- remote_port_);
- } else {
- // Only call on_message without a magic cookie in front of the buffer!
- if (!is_magic_cookie(_recv_buffer, its_iteration_gap)) {
- its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
- current_message_size, this,
- boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT,
- remote_address_,
- remote_port_);
- }
- }
- }
- calculate_shrink_count(_recv_buffer, _recv_buffer_size);
- _recv_buffer_size -= current_message_size;
- its_iteration_gap += current_message_size;
- its_missing_capacity = 0;
- } else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
- const uint32_t its_offset = find_magic_cookie(
- &(*_recv_buffer)[its_iteration_gap], _recv_buffer_size);
- if (its_offset < _recv_buffer_size) {
- _recv_buffer_size -= its_offset;
- its_iteration_gap += its_offset;
- has_full_message = true; // trigger next loop
- VSOMEIP_ERROR << "Detected Magic Cookie within message data."
- << " Resyncing. local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- }
- }
-
- if (!has_full_message) {
- if (_recv_buffer_size > VSOMEIP_RETURN_CODE_POS &&
- ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
- !utility::is_valid_message_type(static_cast<message_type_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])) ||
- !utility::is_valid_return_code(static_cast<return_code_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))
- )) {
- if ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
- VSOMEIP_ERROR << "tce: Wrong protocol version: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- // ensure to send back a message w/ wrong protocol version
- its_lock.unlock();
- its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
- VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
- boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT,
- remote_address_,
- remote_port_);
- its_lock.lock();
- } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
- (*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS]))) {
- VSOMEIP_ERROR << "tce: Invalid message type: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
- (*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))) {
- VSOMEIP_ERROR << "tce: Invalid return code: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- }
- state_ = cei_state_e::CONNECTING;
- shutdown_and_close_socket_unlocked(false);
- its_lock.unlock();
- its_host->on_disconnect(shared_from_this());
- restart(true);
- return;
- } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
- current_message_size > max_message_size_) {
- _recv_buffer_size = 0;
- _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
- _recv_buffer->shrink_to_fit();
- if (has_enabled_magic_cookies_) {
- VSOMEIP_ERROR << "Received a TCP message which exceeds "
- << "maximum message size ("
- << std::dec << current_message_size
- << "). Magic Cookies are enabled: "
- << "Resetting receiver. local: "
- << get_address_port_local() << " remote: "
- << get_address_port_remote();
- } else {
- VSOMEIP_ERROR << "Received a TCP message which exceeds "
- << "maximum message size ("
- << std::dec << current_message_size
- << ") Magic cookies are disabled, "
- << "Restarting connection. "
- << "local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- state_ = cei_state_e::CONNECTING;
- shutdown_and_close_socket_unlocked(false);
- its_lock.unlock();
- its_host->on_disconnect(shared_from_this());
- restart(true);
- return;
- }
- } else if (current_message_size > _recv_buffer_size) {
- its_missing_capacity = current_message_size
- - static_cast<std::uint32_t>(_recv_buffer_size);
- } else if (VSOMEIP_SOMEIP_HEADER_SIZE > _recv_buffer_size) {
- its_missing_capacity = VSOMEIP_SOMEIP_HEADER_SIZE
- - static_cast<std::uint32_t>(_recv_buffer_size);
- } else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
- // no need to check for magic cookie here again: has_full_message
- // would have been set to true if there was one present in the data
- _recv_buffer_size = 0;
- _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
- _recv_buffer->shrink_to_fit();
- its_missing_capacity = 0;
- VSOMEIP_ERROR << "tce::c<" << this
- << ">rcb: recv_buffer_capacity: "
- << _recv_buffer->capacity()
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote()
- << ". Didn't find magic cookie in broken data, trying to resync.";
- } else {
- VSOMEIP_ERROR << "tce::c<" << this
- << ">rcb: recv_buffer_size is: " << std::dec
- << _recv_buffer_size << " but couldn't read "
- "out message_size. recv_buffer_capacity: "
- << _recv_buffer->capacity()
- << " its_iteration_gap: " << its_iteration_gap
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote()
- << ". Restarting connection due to missing/broken data TCP stream.";
- state_ = cei_state_e::CONNECTING;
- shutdown_and_close_socket_unlocked(false);
- its_lock.unlock();
- its_host->on_disconnect(shared_from_this());
- restart(true);
- return;
- }
- }
- } while (has_full_message && _recv_buffer_size);
- if (its_iteration_gap) {
- // Copy incomplete message to front for next receive_cbk iteration
- for (size_t i = 0; i < _recv_buffer_size; ++i) {
- (*_recv_buffer)[i] = (*_recv_buffer)[i + its_iteration_gap];
- }
- // Still more capacity needed after shifting everything to front?
- if (its_missing_capacity &&
- its_missing_capacity <= _recv_buffer->capacity() - _recv_buffer_size) {
- its_missing_capacity = 0;
- }
- }
- its_lock.unlock();
- receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
- } else {
- VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk: "
- << _error.message() << "(" << std::dec << _error.value()
- << ") local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- if (_error == boost::asio::error::eof ||
- _error == boost::asio::error::timed_out ||
- _error == boost::asio::error::bad_descriptor ||
- _error == boost::asio::error::connection_reset) {
- if (state_ == cei_state_e::CONNECTING) {
- VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk already"
- " restarting" << get_remote_information();
- } else {
+ )
+ );
+ }
+}
+
+void tcp_client_endpoint_impl::send_queued() {
+ message_buffer_ptr_t its_buffer;
+ if(queue_.size()) {
+ its_buffer = queue_.front();
+ } else {
+ return;
+ }
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MIN],
+ (*its_buffer)[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_METHOD_POS_MIN],
+ (*its_buffer)[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MIN],
+ (*its_buffer)[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ (*its_buffer)[VSOMEIP_SESSION_POS_MIN],
+ (*its_buffer)[VSOMEIP_SESSION_POS_MAX]);
+
+ if (has_enabled_magic_cookies_) {
+ const std::chrono::steady_clock::time_point now =
+ std::chrono::steady_clock::now();
+ if (std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - last_cookie_sent_) > std::chrono::milliseconds(10000)) {
+ send_magic_cookie(its_buffer);
+ last_cookie_sent_ = now;
+ }
+ }
+
+
+#if 0
+ std::stringstream msg;
+ msg << "tcei<" << remote_.address() << ":"
+ << std::dec << remote_.port() << ">::sq: ";
+ for (std::size_t i = 0; i < its_buffer->size(); i++)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int)(*its_buffer)[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (socket_->is_open()) {
+ boost::asio::async_write(
+ *socket_,
+ boost::asio::buffer(*its_buffer),
+ std::bind(&tcp_client_endpoint_impl::write_completion_condition,
+ std::static_pointer_cast<tcp_client_endpoint_impl>(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer->size(),
+ its_service, its_method, its_client, its_session,
+ std::chrono::steady_clock::now()),
+ std::bind(
+ &tcp_client_endpoint_base_impl::send_cbk,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer
+ )
+ );
+ }
+ }
+}
+
+void tcp_client_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ configuration_->get_configured_timing_requests(_service,
+ remote_address_.to_string(), remote_port_, _method,
+ _debouncing, _maximum_retention);
+}
+
+bool tcp_client_endpoint_impl::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ if (remote_address_.is_unspecified()) {
+ return false;
+ }
+ _address = remote_address_;
+ return true;
+}
+
+void tcp_client_endpoint_impl::set_local_port() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::system::error_code its_error;
+ if (socket_->is_open()) {
+ endpoint_type its_endpoint = socket_->local_endpoint(its_error);
+ if (!its_error) {
+ local_port_ = its_endpoint.port();
+ } else {
+ VSOMEIP_WARNING << "tcp_client_endpoint_impl::set_local_port() "
+ << " couldn't get local_endpoint: " << its_error.message();
+ }
+ }
+}
+
+std::size_t tcp_client_endpoint_impl::write_completion_condition(
+ const boost::system::error_code& _error, std::size_t _bytes_transferred,
+ std::size_t _bytes_to_send, service_t _service, method_t _method,
+ client_t _client, session_t _session,
+ const std::chrono::steady_clock::time_point _start) {
+
+ if (_error) {
+ VSOMEIP_ERROR << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ return 0;
+ }
+
+ const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+ const std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
+ if (passed > send_timeout_warning_) {
+ if (passed > send_timeout_) {
+ VSOMEIP_ERROR << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ } else {
+ VSOMEIP_WARNING << "tce::write_completion_condition: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") took longer than " << std::dec << send_timeout_warning_.count()
+ << "ms bytes transferred: " << std::dec << _bytes_transferred
+ << " bytes to sent: " << std::dec << _bytes_to_send << " "
+ << "remote:" << get_address_port_remote() << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _session << "]";
+ }
+ }
+ return _bytes_to_send - _bytes_transferred;
+}
+
+std::uint16_t tcp_client_endpoint_impl::get_remote_port() const {
+ return remote_port_;
+}
+
+bool tcp_client_endpoint_impl::is_reliable() const {
+ return true;
+}
+
+bool tcp_client_endpoint_impl::is_magic_cookie(const message_buffer_ptr_t& _recv_buffer,
+ size_t _offset) const {
+ return (0 == std::memcmp(SERVICE_COOKIE, &(*_recv_buffer)[_offset], sizeof(SERVICE_COOKIE)));
+}
+
+void tcp_client_endpoint_impl::send_magic_cookie(message_buffer_ptr_t &_buffer) {
+ if (max_message_size_ == MESSAGE_SIZE_UNLIMITED
+ || max_message_size_ - _buffer->size() >=
+ VSOMEIP_SOMEIP_HEADER_SIZE + VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE) {
+ _buffer->insert(
+ _buffer->begin(),
+ CLIENT_COOKIE,
+ CLIENT_COOKIE + sizeof(CLIENT_COOKIE)
+ );
+ queue_size_ += sizeof(CLIENT_COOKIE);
+ } else {
+ VSOMEIP_WARNING << "Packet full. Cannot insert magic cookie!";
+ }
+}
+
+void tcp_client_endpoint_impl::receive_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t& _recv_buffer, std::size_t _recv_buffer_size) {
+ if (_error == boost::asio::error::operation_aborted) {
+ // endpoint was stopped
+ return;
+ }
+#if 0
+ std::stringstream msg;
+ msg << "cei::rcb (" << _error.message() << "): ";
+ for (std::size_t i = 0; i < _bytes + _recv_buffer_size; ++i)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int) (_recv_buffer)[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ std::unique_lock<std::mutex> its_lock(socket_mutex_);
+ std::shared_ptr<routing_host> its_host = routing_host_.lock();
+ if (its_host) {
+ std::uint32_t its_missing_capacity(0);
+ if (!_error && 0 < _bytes) {
+ if (_recv_buffer_size + _bytes < _recv_buffer_size) {
+ VSOMEIP_ERROR << "receive buffer overflow in tcp client endpoint ~> abort!";
+ return;
+ }
+ _recv_buffer_size += _bytes;
+
+ size_t its_iteration_gap = 0;
+ bool has_full_message(false);
+ do {
+ uint64_t read_message_size
+ = utility::get_message_size(&(*_recv_buffer)[its_iteration_gap],
+ _recv_buffer_size);
+ if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
+ VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
+ return;
+ }
+ uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
+ has_full_message = (current_message_size > VSOMEIP_RETURN_CODE_POS
+ && current_message_size <= _recv_buffer_size);
+ if (has_full_message) {
+ bool needs_forwarding(true);
+ if (is_magic_cookie(_recv_buffer, its_iteration_gap)) {
+ has_enabled_magic_cookies_ = true;
+ } else {
+ if (has_enabled_magic_cookies_) {
+ uint32_t its_offset = find_magic_cookie(&(*_recv_buffer)[its_iteration_gap],
+ (uint32_t) _recv_buffer_size);
+ if (its_offset < current_message_size) {
+ VSOMEIP_ERROR << "Message includes Magic Cookie. Ignoring it.";
+ current_message_size = its_offset;
+ needs_forwarding = false;
+ }
+ }
+ }
+ if (needs_forwarding) {
+ if (!has_enabled_magic_cookies_) {
+ its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
+ current_message_size, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ } else {
+ // Only call on_message without a magic cookie in front of the buffer!
+ if (!is_magic_cookie(_recv_buffer, its_iteration_gap)) {
+ its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
+ current_message_size, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ }
+ }
+ }
+ calculate_shrink_count(_recv_buffer, _recv_buffer_size);
+ _recv_buffer_size -= current_message_size;
+ its_iteration_gap += current_message_size;
+ its_missing_capacity = 0;
+ } else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
+ const uint32_t its_offset = find_magic_cookie(
+ &(*_recv_buffer)[its_iteration_gap], _recv_buffer_size);
+ if (its_offset < _recv_buffer_size) {
+ _recv_buffer_size -= its_offset;
+ its_iteration_gap += its_offset;
+ has_full_message = true; // trigger next loop
+ VSOMEIP_ERROR << "Detected Magic Cookie within message data."
+ << " Resyncing. local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ }
+
+ if (!has_full_message) {
+ if (_recv_buffer_size > VSOMEIP_RETURN_CODE_POS &&
+ ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(static_cast<message_type_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if ((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ VSOMEIP_ERROR << "tce: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ // ensure to send back a message w/ wrong protocol version
+ its_lock.unlock();
+ its_host->on_message(&(*_recv_buffer)[its_iteration_gap],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ its_lock.lock();
+ } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
+ (*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ VSOMEIP_ERROR << "tce: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ (*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS]))) {
+ VSOMEIP_ERROR << "tce: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*recv_buffer_)[its_iteration_gap + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
+ its_ep_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
+ } else if (max_message_size_ != MESSAGE_SIZE_UNLIMITED &&
+ current_message_size > max_message_size_) {
+ _recv_buffer_size = 0;
+ _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
+ _recv_buffer->shrink_to_fit();
+ if (has_enabled_magic_cookies_) {
+ VSOMEIP_ERROR << "Received a TCP message which exceeds "
+ << "maximum message size ("
+ << std::dec << current_message_size
+ << "). Magic Cookies are enabled: "
+ << "Resetting receiver. local: "
+ << get_address_port_local() << " remote: "
+ << get_address_port_remote();
+ } else {
+ VSOMEIP_ERROR << "Received a TCP message which exceeds "
+ << "maximum message size ("
+ << std::dec << current_message_size
+ << ") Magic cookies are disabled, "
+ << "Restarting connection. "
+ << "local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
+ its_ep_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
+ }
+ } else if (current_message_size > _recv_buffer_size) {
+ its_missing_capacity = current_message_size
+ - static_cast<std::uint32_t>(_recv_buffer_size);
+ } else if (VSOMEIP_SOMEIP_HEADER_SIZE > _recv_buffer_size) {
+ its_missing_capacity = VSOMEIP_SOMEIP_HEADER_SIZE
+ - static_cast<std::uint32_t>(_recv_buffer_size);
+ } else if (has_enabled_magic_cookies_ && _recv_buffer_size > 0) {
+ // no need to check for magic cookie here again: has_full_message
+ // would have been set to true if there was one present in the data
+ _recv_buffer_size = 0;
+ _recv_buffer->resize(recv_buffer_size_initial_, 0x0);
+ _recv_buffer->shrink_to_fit();
+ its_missing_capacity = 0;
+ VSOMEIP_ERROR << "tce::c<" << this
+ << ">rcb: recv_buffer_capacity: "
+ << _recv_buffer->capacity()
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Didn't find magic cookie in broken data, trying to resync.";
+ } else {
+ VSOMEIP_ERROR << "tce::c<" << this
+ << ">rcb: recv_buffer_size is: " << std::dec
+ << _recv_buffer_size << " but couldn't read "
+ "out message_size. recv_buffer_capacity: "
+ << _recv_buffer->capacity()
+ << " its_iteration_gap: " << its_iteration_gap
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << ". Restarting connection due to missing/broken data TCP stream.";
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
+ its_ep_host->on_disconnect(shared_from_this());
+ restart(true);
+ return;
+ }
+ }
+ } while (has_full_message && _recv_buffer_size);
+ if (its_iteration_gap) {
+ // Copy incomplete message to front for next receive_cbk iteration
+ for (size_t i = 0; i < _recv_buffer_size; ++i) {
+ (*_recv_buffer)[i] = (*_recv_buffer)[i + its_iteration_gap];
+ }
+ // Still more capacity needed after shifting everything to front?
+ if (its_missing_capacity &&
+ its_missing_capacity <= _recv_buffer->capacity() - _recv_buffer_size) {
+ its_missing_capacity = 0;
+ }
+ }
+ its_lock.unlock();
+ receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ } else {
+ VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk: "
+ << _error.message() << "(" << std::dec << _error.value()
+ << ") local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ if (_error == boost::asio::error::eof ||
+ _error == boost::asio::error::timed_out ||
+ _error == boost::asio::error::bad_descriptor ||
+ _error == boost::asio::error::connection_reset) {
+ if (state_ == cei_state_e::CONNECTING) {
+ VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk already"
+ " restarting" << get_remote_information();
+ } else {
VSOMEIP_WARNING << "tcp_client_endpoint receive_cbk restarting.";
- state_ = cei_state_e::CONNECTING;
- shutdown_and_close_socket_unlocked(false);
- its_lock.unlock();
- its_host->on_disconnect(shared_from_this());
- restart(true);
- }
- } else {
- its_lock.unlock();
- receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
- }
- }
- }
-}
-
-void tcp_client_endpoint_impl::calculate_shrink_count(const message_buffer_ptr_t& _recv_buffer,
- std::size_t _recv_buffer_size) {
- if (buffer_shrink_threshold_) {
- if (_recv_buffer->capacity() != recv_buffer_size_initial_) {
- if (_recv_buffer_size < (_recv_buffer->capacity() >> 1)) {
- shrink_count_++;
- } else {
- shrink_count_ = 0;
- }
- }
- }
-}
-
-
-const std::string tcp_client_endpoint_impl::get_address_port_remote() const {
- boost::system::error_code ec;
- std::string its_address_port;
- its_address_port.reserve(21);
- boost::asio::ip::address its_address;
- if (get_remote_address(its_address)) {
- its_address_port += its_address.to_string();
- }
- its_address_port += ":";
- its_address_port += std::to_string(remote_port_);
- return its_address_port;
-}
-
-const std::string tcp_client_endpoint_impl::get_address_port_local() const {
- std::string its_address_port;
- its_address_port.reserve(21);
- boost::system::error_code ec;
- if (socket_->is_open()) {
- endpoint_type its_local_endpoint = socket_->local_endpoint(ec);
- if (!ec) {
- its_address_port += its_local_endpoint.address().to_string(ec);
- its_address_port += ":";
- its_address_port.append(std::to_string(its_local_endpoint.port()));
- }
- }
- return its_address_port;
-}
-
-void tcp_client_endpoint_impl::handle_recv_buffer_exception(
- const std::exception &_e,
- const message_buffer_ptr_t& _recv_buffer,
- std::size_t _recv_buffer_size) {
- boost::system::error_code ec;
-
- std::stringstream its_message;
- its_message <<"tcp_client_endpoint_impl::connection catched exception"
- << _e.what() << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote()
- << " shutting down connection. Start of buffer: ";
-
- for (std::size_t i = 0; i < _recv_buffer_size && i < 16; i++) {
- its_message << std::setw(2) << std::setfill('0') << std::hex
- << (int) ((*_recv_buffer)[i]) << " ";
- }
-
- its_message << " Last 16 Bytes captured: ";
- for (int i = 15; _recv_buffer_size > 15 && i >= 0; i--) {
- its_message << std::setw(2) << std::setfill('0') << std::hex
- << (int) ((*_recv_buffer)[i]) << " ";
- }
- VSOMEIP_ERROR << its_message.str();
- _recv_buffer->clear();
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- sending_blocked_ = true;
- }
- {
- std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
- boost::system::error_code ec;
- connect_timer_.cancel(ec);
- }
- if (socket_->is_open()) {
- boost::system::error_code its_error;
- socket_->shutdown(socket_type::shutdown_both, its_error);
- socket_->close(its_error);
- }
-}
-
-void tcp_client_endpoint_impl::print_status() {
- std::size_t its_data_size(0);
- std::size_t its_queue_size(0);
- std::size_t its_receive_buffer_capacity(0);
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- its_queue_size = queue_.size();
- its_data_size = queue_size_;
- }
- std::string local;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- local = get_address_port_local();
- its_receive_buffer_capacity = recv_buffer_->capacity();
- }
-
- VSOMEIP_INFO << "status tce: " << local << " -> "
- << get_address_port_remote()
- << " queue: " << std::dec << its_queue_size
- << " data: " << std::dec << its_data_size
- << " recv_buffer: " << std::dec << its_receive_buffer_capacity;
-}
-
-std::string tcp_client_endpoint_impl::get_remote_information() const {
- boost::system::error_code ec;
- return remote_.address().to_string(ec) + ":"
- + std::to_string(remote_.port());
-}
-
-void tcp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error,
- std::size_t _bytes,
- message_buffer_ptr_t _sent_msg) {
- (void)_bytes;
- if (!_error) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- if (queue_.size() > 0) {
- queue_size_ -= queue_.front()->size();
- queue_.pop_front();
- send_queued();
- }
- } else if (_error == boost::system::errc::destination_address_required) {
- VSOMEIP_WARNING << "tce::send_cbk received error: " << _error.message()
- << " (" << std::dec << _error.value() << ") "
- << get_remote_information();
- was_not_connected_ = true;
- } else if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- shutdown_and_close_socket(false);
- } else {
- if (state_ == cei_state_e::CONNECTING) {
- VSOMEIP_WARNING << "tce::send_cbk endpoint is already restarting:"
- << get_remote_information();
- } else {
- state_ = cei_state_e::CONNECTING;
- shutdown_and_close_socket(false);
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- its_host->on_disconnect(shared_from_this());
- }
- restart(true);
- }
- service_t its_service(0);
- method_t its_method(0);
- client_t its_client(0);
- session_t its_session(0);
- if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
- its_service = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
- (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
- its_method = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
- (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
- its_client = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
- (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
- its_session = VSOMEIP_BYTES_TO_WORD(
- (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
- (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
- }
- VSOMEIP_WARNING << "tce::send_cbk received error: "
- << _error.message() << " (" << std::dec
- << _error.value() << ") " << get_remote_information()
- << " " << std::dec << queue_.size()
- << " " << std::dec << queue_size_ << " ("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
- }
-}
-
-std::uint32_t tcp_client_endpoint_impl::get_max_allowed_reconnects() const {
- return MAX_RECONNECTS_UNLIMITED;
-}
-
-void tcp_client_endpoint_impl::max_allowed_reconnects_reached() {
- return;
-}
-
-} // namespace vsomeip
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket_unlocked(false);
+ its_lock.unlock();
+ std::shared_ptr<endpoint_host> its_ep_host = endpoint_host_.lock();
+ its_ep_host->on_disconnect(shared_from_this());
+ restart(true);
+ }
+ } else {
+ its_lock.unlock();
+ receive(_recv_buffer, _recv_buffer_size, its_missing_capacity);
+ }
+ }
+ }
+}
+
+void tcp_client_endpoint_impl::calculate_shrink_count(const message_buffer_ptr_t& _recv_buffer,
+ std::size_t _recv_buffer_size) {
+ if (buffer_shrink_threshold_) {
+ if (_recv_buffer->capacity() != recv_buffer_size_initial_) {
+ if (_recv_buffer_size < (_recv_buffer->capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ }
+}
+
+
+const std::string tcp_client_endpoint_impl::get_address_port_remote() const {
+ boost::system::error_code ec;
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::asio::ip::address its_address;
+ if (get_remote_address(its_address)) {
+ its_address_port += its_address.to_string();
+ }
+ its_address_port += ":";
+ its_address_port += std::to_string(remote_port_);
+ return its_address_port;
+}
+
+const std::string tcp_client_endpoint_impl::get_address_port_local() const {
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::system::error_code ec;
+ if (socket_->is_open()) {
+ endpoint_type its_local_endpoint = socket_->local_endpoint(ec);
+ if (!ec) {
+ its_address_port += its_local_endpoint.address().to_string(ec);
+ its_address_port += ":";
+ its_address_port.append(std::to_string(its_local_endpoint.port()));
+ }
+ }
+ return its_address_port;
+}
+
+void tcp_client_endpoint_impl::handle_recv_buffer_exception(
+ const std::exception &_e,
+ const message_buffer_ptr_t& _recv_buffer,
+ std::size_t _recv_buffer_size) {
+ boost::system::error_code ec;
+
+ std::stringstream its_message;
+ its_message <<"tcp_client_endpoint_impl::connection catched exception"
+ << _e.what() << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote()
+ << " shutting down connection. Start of buffer: ";
+
+ for (std::size_t i = 0; i < _recv_buffer_size && i < 16; i++) {
+ its_message << std::setw(2) << std::setfill('0') << std::hex
+ << (int) ((*_recv_buffer)[i]) << " ";
+ }
+
+ its_message << " Last 16 Bytes captured: ";
+ for (int i = 15; _recv_buffer_size > 15 && i >= 0; i--) {
+ its_message << std::setw(2) << std::setfill('0') << std::hex
+ << (int) ((*_recv_buffer)[static_cast<size_t>(i)]) << " ";
+ }
+ VSOMEIP_ERROR << its_message.str();
+ _recv_buffer->clear();
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ sending_blocked_ = true;
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(connect_timer_mutex_);
+ boost::system::error_code ec;
+ connect_timer_.cancel(ec);
+ }
+ if (socket_->is_open()) {
+ boost::system::error_code its_error;
+ socket_->shutdown(socket_type::shutdown_both, its_error);
+ socket_->close(its_error);
+ }
+}
+
+void tcp_client_endpoint_impl::print_status() {
+ std::size_t its_data_size(0);
+ std::size_t its_queue_size(0);
+ std::size_t its_receive_buffer_capacity(0);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ its_queue_size = queue_.size();
+ its_data_size = queue_size_;
+ }
+ std::string local;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ local = get_address_port_local();
+ its_receive_buffer_capacity = recv_buffer_->capacity();
+ }
+
+ VSOMEIP_INFO << "status tce: " << local << " -> "
+ << get_address_port_remote()
+ << " queue: " << std::dec << its_queue_size
+ << " data: " << std::dec << its_data_size
+ << " recv_buffer: " << std::dec << its_receive_buffer_capacity;
+}
+
+std::string tcp_client_endpoint_impl::get_remote_information() const {
+ boost::system::error_code ec;
+ return remote_.address().to_string(ec) + ":"
+ + std::to_string(remote_.port());
+}
+
+void tcp_client_endpoint_impl::send_cbk(boost::system::error_code const &_error,
+ std::size_t _bytes,
+ const message_buffer_ptr_t& _sent_msg) {
+ (void)_bytes;
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (queue_.size() > 0) {
+ queue_size_ -= queue_.front()->size();
+ queue_.pop_front();
+ send_queued();
+ }
+ } else if (_error == boost::system::errc::destination_address_required) {
+ VSOMEIP_WARNING << "tce::send_cbk received error: " << _error.message()
+ << " (" << std::dec << _error.value() << ") "
+ << get_remote_information();
+ was_not_connected_ = true;
+ } else if (_error == boost::asio::error::operation_aborted) {
+ // endpoint was stopped
+ shutdown_and_close_socket(false);
+ } else {
+ if (state_ == cei_state_e::CONNECTING) {
+ VSOMEIP_WARNING << "tce::send_cbk endpoint is already restarting:"
+ << get_remote_information();
+ } else {
+ state_ = cei_state_e::CONNECTING;
+ shutdown_and_close_socket(false);
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ its_host->on_disconnect(shared_from_this());
+ }
+ restart(true);
+ }
+ service_t its_service(0);
+ method_t its_method(0);
+ client_t its_client(0);
+ session_t its_session(0);
+ if (_sent_msg && _sent_msg->size() > VSOMEIP_SESSION_POS_MAX) {
+ its_service = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SERVICE_POS_MAX]);
+ its_method = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MIN],
+ (*_sent_msg)[VSOMEIP_METHOD_POS_MAX]);
+ its_client = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MIN],
+ (*_sent_msg)[VSOMEIP_CLIENT_POS_MAX]);
+ its_session = VSOMEIP_BYTES_TO_WORD(
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MIN],
+ (*_sent_msg)[VSOMEIP_SESSION_POS_MAX]);
+ }
+ VSOMEIP_WARNING << "tce::send_cbk received error: "
+ << _error.message() << " (" << std::dec
+ << _error.value() << ") " << get_remote_information()
+ << " " << std::dec << queue_.size()
+ << " " << std::dec << queue_size_ << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session << "]";
+ }
+}
+
+bool tcp_client_endpoint_impl::tp_segmentation_enabled(service_t _service,
+ method_t _method) const {
+ (void)_service;
+ (void)_method;
+ return false;
+}
+
+std::uint32_t tcp_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return MAX_RECONNECTS_UNLIMITED;
+}
+
+void tcp_client_endpoint_impl::max_allowed_reconnects_reached() {
+ return;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
index 30402c5..b7b1d0a 100644
--- a/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/tcp_server_endpoint_impl.cpp
@@ -1,3 +1,4 @@
+
// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,31 +9,34 @@
#include <boost/asio/write.hpp>
#include <vsomeip/constants.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/endpoint_definition.hpp"
#include "../include/endpoint_host.hpp"
+#include "../../routing/include/routing_host.hpp"
#include "../include/tcp_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../utility/include/utility.hpp"
#include "../../utility/include/byteorder.hpp"
-#include "../../configuration/include/internal.hpp"
namespace ip = boost::asio::ip;
-namespace vsomeip {
+namespace vsomeip_v3 {
tcp_server_endpoint_impl::tcp_server_endpoint_impl(
- std::shared_ptr<endpoint_host> _host, endpoint_type _local,
- boost::asio::io_service &_io, std::uint32_t _max_message_size,
- std::uint32_t _buffer_shrink_threshold,
- std::chrono::milliseconds _send_timeout,
- configuration::endpoint_queue_limit_t _queue_limit)
- : tcp_server_endpoint_base_impl(_host, _local, _io,
- _max_message_size, _queue_limit),
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration)
+ : tcp_server_endpoint_base_impl(_endpoint_host, _routing_host, _local, _io,
+ _configuration->get_max_message_size_reliable(_local.address().to_string(), _local.port()),
+ _configuration->get_endpoint_queue_limit(_local.address().to_string(), _local.port()),
+ _configuration),
acceptor_(_io),
- buffer_shrink_threshold_(_buffer_shrink_threshold),
+ buffer_shrink_threshold_(configuration_->get_buffer_shrink_threshold()),
local_port_(_local.port()),
- send_timeout_(_send_timeout) {
+ // send timeout after 2/3 of configured ttl, warning after 1/3
+ send_timeout_(configuration_->get_sd_ttl() * 666) {
is_supporting_magic_cookies_ = true;
boost::system::error_code ec;
@@ -40,6 +44,18 @@ tcp_server_endpoint_impl::tcp_server_endpoint_impl(
boost::asio::detail::throw_error(ec, "acceptor open");
acceptor_.set_option(boost::asio::socket_base::reuse_address(true), ec);
boost::asio::detail::throw_error(ec, "acceptor set_option");
+
+#ifndef _WIN32
+ // If specified, bind to device
+ std::string its_device(configuration_->get_device());
+ if (its_device != "") {
+ if (setsockopt(acceptor_.native_handle(),
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ VSOMEIP_WARNING << "TCP Server: Could not bind to device \"" << its_device << "\"";
+ }
+ }
+#endif
+
acceptor_.bind(_local, ec);
boost::asio::detail::throw_error(ec, "acceptor bind");
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
@@ -93,11 +109,34 @@ void tcp_server_endpoint_impl::stop() {
bool tcp_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data,
- uint32_t _size, bool _flush) {
+ const byte_t *_data, uint32_t _size) {
std::lock_guard<std::mutex> its_lock(mutex_);
endpoint_type its_target(_target->get_address(), _target->get_port());
- return send_intern(its_target, _data, _size, _flush);
+ return send_intern(its_target, _data, _size);
+}
+
+bool tcp_server_endpoint_impl::send_error(
+ const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) {
+ bool ret(false);
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ const endpoint_type its_target(_target->get_address(), _target->get_port());
+ const queue_iterator_type target_queue_iterator(find_or_create_queue_unlocked(its_target));
+ auto& its_qpair = target_queue_iterator->second;
+ const bool queue_size_zero_on_entry(its_qpair.second.empty());
+
+ if (check_message_size(nullptr, _size, its_target) == endpoint_impl::cms_ret_e::MSG_OK &&
+ check_queue_limit(_data, _size, its_qpair.first)) {
+ its_qpair.second.emplace_back(
+ std::make_shared<message_buffer_t>(_data, _data + _size));
+ its_qpair.first += _size;
+
+ if (queue_size_zero_on_entry) { // no writing in progress
+ send_queued(target_queue_iterator);
+ }
+ ret = true;
+ }
+ return ret;
}
void tcp_server_endpoint_impl::send_queued(const queue_iterator_type _queue_iterator) {
@@ -121,7 +160,17 @@ void tcp_server_endpoint_impl::send_queued(const queue_iterator_type _queue_iter
}
}
-bool tcp_server_endpoint_impl::is_established(std::shared_ptr<endpoint_definition> _endpoint) {
+void tcp_server_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ configuration_->get_configured_timing_responses(_service,
+ tcp_server_endpoint_base_impl::local_.address().to_string(),
+ tcp_server_endpoint_base_impl::local_.port(), _method,
+ _debouncing, _maximum_retention);
+}
+
+bool tcp_server_endpoint_impl::is_established(const std::shared_ptr<endpoint_definition>& _endpoint) {
bool is_connected = false;
endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
{
@@ -156,7 +205,7 @@ void tcp_server_endpoint_impl::remove_connection(
}
}
-void tcp_server_endpoint_impl::accept_cbk(connection::ptr _connection,
+void tcp_server_endpoint_impl::accept_cbk(const connection::ptr& _connection,
boost::system::error_code const &_error) {
if (!_error) {
@@ -218,7 +267,7 @@ bool tcp_server_endpoint_impl::is_reliable() const {
// class tcp_service_impl::connection
///////////////////////////////////////////////////////////////////////////////
tcp_server_endpoint_impl::connection::connection(
- std::weak_ptr<tcp_server_endpoint_impl> _server,
+ const std::weak_ptr<tcp_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
std::uint32_t _recv_buffer_size_initial,
std::uint32_t _buffer_shrink_threshold,
@@ -243,7 +292,7 @@ tcp_server_endpoint_impl::connection::connection(
tcp_server_endpoint_impl::connection::ptr
tcp_server_endpoint_impl::connection::create(
- std::weak_ptr<tcp_server_endpoint_impl> _server,
+ const std::weak_ptr<tcp_server_endpoint_impl>& _server,
std::uint32_t _max_message_size,
std::uint32_t _buffer_shrink_threshold,
bool _magic_cookies_enabled,
@@ -375,6 +424,32 @@ void tcp_server_endpoint_impl::connection::send_queued(
}
}
+void tcp_server_endpoint_impl::connection::send_queued_sync(
+ const queue_iterator_type _queue_iterator) {
+ message_buffer_ptr_t its_buffer = _queue_iterator->second.second.front();
+ if (magic_cookies_enabled_) {
+ const std::chrono::steady_clock::time_point now =
+ std::chrono::steady_clock::now();
+ if (std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - last_cookie_sent_) > std::chrono::milliseconds(10000)) {
+ if (send_magic_cookie(its_buffer)) {
+ last_cookie_sent_ = now;
+ _queue_iterator->second.first += sizeof(SERVICE_COOKIE);
+ }
+ }
+ }
+
+ try {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::asio::write(socket_, boost::asio::buffer(*its_buffer));
+ } catch (const boost::system::system_error &e) {
+ if (e.code() != boost::asio::error::broken_pipe) {
+ VSOMEIP_ERROR << "tcp_server_endpoint_impl::connection::"
+ << __func__ << " " << e.what();
+ }
+ }
+}
+
bool tcp_server_endpoint_impl::connection::send_magic_cookie(
message_buffer_ptr_t &_buffer) {
if (max_message_size_ == MESSAGE_SIZE_UNLIMITED
@@ -412,7 +487,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
<< (int) recv_buffer_[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
- std::shared_ptr<endpoint_host> its_host = its_server->host_.lock();
+ std::shared_ptr<routing_host> its_host = its_server->routing_host_.lock();
if (its_host) {
if (!_error && 0 < _bytes) {
if (recv_buffer_size_ + _bytes < recv_buffer_size_) {
@@ -451,9 +526,12 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
<< " remote: " << get_address_port_remote();
}
if (!is_magic_cookie(its_iteration_gap)) {
- its_host->on_error(&recv_buffer_[its_iteration_gap],
- static_cast<length_t>(recv_buffer_size_),its_server.get(),
- remote_address_, remote_port_);
+ auto its_endpoint_host = its_server->endpoint_host_.lock();
+ if (its_endpoint_host) {
+ its_endpoint_host->on_error(&recv_buffer_[its_iteration_gap],
+ static_cast<length_t>(recv_buffer_size_),its_server.get(),
+ remote_address_, remote_port_);
+ }
}
current_message_size = its_offset;
needs_forwarding = false;
@@ -464,18 +542,15 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
if (utility::is_request(
recv_buffer_[its_iteration_gap
+ VSOMEIP_MESSAGE_TYPE_POS])) {
- client_t its_client;
- std::memcpy(&its_client,
- &recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MIN],
- sizeof(client_t));
- if (its_client != MAGIC_COOKIE_NETWORK_BYTE_ORDER) {
- session_t its_session;
- std::memcpy(&its_session,
- &recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MIN],
+ recv_buffer_[its_iteration_gap + VSOMEIP_CLIENT_POS_MAX]);
+ if (its_client != MAGIC_COOKIE_CLIENT) {
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MIN],
+ recv_buffer_[its_iteration_gap + VSOMEIP_SESSION_POS_MAX]);
its_server->clients_mutex_.lock();
its_server->clients_[its_client][its_session] = remote_;
- its_server->endpoint_to_client_[remote_] = its_client;
its_server->clients_mutex_.unlock();
}
}
@@ -483,8 +558,9 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
its_host->on_message(&recv_buffer_[its_iteration_gap],
current_message_size, its_server.get(),
boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT, remote_address_,
- remote_port_);
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_, remote_port_);
} else {
// Only call on_message without a magic cookie in front of the buffer!
if (!is_magic_cookie(its_iteration_gap)) {
@@ -492,6 +568,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
current_message_size, its_server.get(),
boost::asio::ip::address(),
VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
remote_address_, remote_port_);
}
}
@@ -512,17 +589,23 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
<< " remote: " << get_address_port_remote();
}
if (!is_magic_cookie(its_iteration_gap)) {
- its_host->on_error(&recv_buffer_[its_iteration_gap],
- static_cast<length_t>(recv_buffer_size_), its_server.get(),
- remote_address_, remote_port_);
+ auto its_endpoint_host = its_server->endpoint_host_.lock();
+ if (its_endpoint_host) {
+ its_endpoint_host->on_error(&recv_buffer_[its_iteration_gap],
+ static_cast<length_t>(recv_buffer_size_), its_server.get(),
+ remote_address_, remote_port_);
+ }
}
recv_buffer_size_ -= its_offset;
its_iteration_gap += its_offset;
has_full_message = true; // trigger next loop
if (!is_magic_cookie(its_iteration_gap)) {
- its_host->on_error(&recv_buffer_[its_iteration_gap],
- static_cast<length_t>(recv_buffer_size_), its_server.get(),
- remote_address_, remote_port_);
+ auto its_endpoint_host = its_server->endpoint_host_.lock();
+ if (its_endpoint_host) {
+ its_endpoint_host->on_error(&recv_buffer_[its_iteration_gap],
+ static_cast<length_t>(recv_buffer_size_), its_server.get(),
+ remote_address_, remote_port_);
+ }
}
}
}
@@ -548,6 +631,7 @@ void tcp_server_endpoint_impl::connection::receive_cbk(
VSOMEIP_SOMEIP_HEADER_SIZE + 8, its_server.get(),
boost::asio::ip::address(),
VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
remote_address_, remote_port_);
} else if (!utility::is_valid_message_type(static_cast<message_type_e>(
recv_buffer_[its_iteration_gap + VSOMEIP_MESSAGE_TYPE_POS]))) {
@@ -688,18 +772,6 @@ void tcp_server_endpoint_impl::connection::calculate_shrink_count() {
}
}
-client_t tcp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- const endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
- std::lock_guard<std::mutex> its_lock(clients_mutex_);
- auto found_endpoint = endpoint_to_client_.find(endpoint);
- if (found_endpoint != endpoint_to_client_.end()) {
- // TODO: Check system byte order before convert!
- const client_t client = client_t(found_endpoint->second << 8 | found_endpoint->second >> 8);
- return client;
- }
- return 0;
-}
-
void tcp_server_endpoint_impl::connection::set_remote_info(
const endpoint_type &_remote) {
remote_ = _remote;
@@ -748,7 +820,7 @@ void tcp_server_endpoint_impl::connection::handle_recv_buffer_exception(
its_message << " Last 16 Bytes captured: ";
for (int i = 15; recv_buffer_size_ > 15 && i >= 0; i--) {
its_message << std::setw(2) << std::setfill('0') << std::hex
- << (int) (recv_buffer_[i]) << " ";
+ << (int) (recv_buffer_[static_cast<size_t>(i)]) << " ";
}
VSOMEIP_ERROR << its_message.str();
recv_buffer_.clear();
@@ -773,7 +845,7 @@ tcp_server_endpoint_impl::connection::write_completion_condition(
const boost::system::error_code& _error,
std::size_t _bytes_transferred, std::size_t _bytes_to_send,
service_t _service, method_t _method, client_t _client, session_t _session,
- std::chrono::steady_clock::time_point _start) {
+ const std::chrono::steady_clock::time_point _start) {
if (_error) {
VSOMEIP_ERROR << "tse::write_completion_condition: "
<< _error.message() << "(" << std::dec << _error.value()
@@ -788,8 +860,8 @@ tcp_server_endpoint_impl::connection::write_completion_condition(
return 0;
}
- std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
- std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
+ const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+ const std::chrono::milliseconds passed = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start);
if (passed > send_timeout_warning_) {
if (passed > send_timeout_) {
VSOMEIP_ERROR << "tse::write_completion_condition: "
@@ -876,4 +948,18 @@ std::string tcp_server_endpoint_impl::get_remote_information(
+ std::to_string(_queue_iterator->first.port());
}
-} // namespace vsomeip
+std::string tcp_server_endpoint_impl::get_remote_information(
+ const endpoint_type& _remote) const {
+ boost::system::error_code ec;
+ return _remote.address().to_string(ec) + ":"
+ + std::to_string(_remote.port());
+}
+
+bool tcp_server_endpoint_impl::tp_segmentation_enabled(service_t _service,
+ method_t _method) const {
+ (void)_service;
+ (void)_method;
+ return false;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/tp.cpp b/implementation/endpoints/src/tp.cpp
new file mode 100644
index 0000000..6d532f6
--- /dev/null
+++ b/implementation/endpoints/src/tp.cpp
@@ -0,0 +1,77 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/tp.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#else
+#include <Winsock2.h>
+#endif
+
+
+namespace vsomeip_v3 {
+namespace tp {
+
+tp_split_messages_t tp::tp_split_message(const std::uint8_t * const _data,
+ std::uint32_t _size) {
+ tp_split_messages_t split_messages;
+
+ if (_size < VSOMEIP_MAX_UDP_MESSAGE_SIZE) {
+ VSOMEIP_ERROR << __func__ << " called with size: " << std::dec << _size;
+ return split_messages;
+ }
+
+ const auto data_end = _data + _size;
+
+ for (auto current_offset = _data + VSOMEIP_FULL_HEADER_SIZE; current_offset < data_end;) {
+ auto msg = std::make_shared<message_buffer_t>();
+ msg->reserve(VSOMEIP_FULL_HEADER_SIZE + sizeof(tp_header_t) + tp_max_segment_length_);
+ // copy the header
+ msg->insert(msg->end(), _data, _data + VSOMEIP_FULL_HEADER_SIZE);
+ // change the message type
+ (*msg)[VSOMEIP_MESSAGE_TYPE_POS] = (*msg)[VSOMEIP_MESSAGE_TYPE_POS] | 0x20;
+ // check if last segment
+ const auto segment_end = current_offset + tp_max_segment_length_;
+ const bool is_last_segment = (segment_end >= data_end);
+ // insert tp_header
+ const tp_header_t header = htonl(
+ static_cast<tp_header_t>((current_offset - VSOMEIP_FULL_HEADER_SIZE - _data)) |
+ static_cast<tp_header_t>((is_last_segment) ? 0x0u : 0x1u));
+
+ const byte_t * const headerp = reinterpret_cast<const byte_t*>(&header);
+ msg->insert(msg->end(), headerp, headerp + sizeof(tp_header_t));
+
+ // insert payload
+ if (is_last_segment) {
+ msg->insert(msg->end(), current_offset, data_end);
+ current_offset = data_end;
+ } else {
+ msg->insert(msg->end(), current_offset, segment_end);
+ current_offset += tp_max_segment_length_;
+ }
+ // update length
+ const length_t its_length = static_cast<length_t>(msg->size()
+ - VSOMEIP_SOMEIP_HEADER_SIZE);
+ *(reinterpret_cast<length_t*>(&(*msg)[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length);
+ split_messages.emplace_back(std::move(msg));
+ }
+
+ return split_messages;
+}
+
+} // namespace tp
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/tp_message.cpp b/implementation/endpoints/src/tp_message.cpp
new file mode 100644
index 0000000..f786a4f
--- /dev/null
+++ b/implementation/endpoints/src/tp_message.cpp
@@ -0,0 +1,352 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+#include <sstream>
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/tp_message.hpp"
+#include "../include/tp.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#else
+#include <Winsock2.h>
+#endif
+
+
+namespace vsomeip_v3 {
+namespace tp {
+
+tp_message::tp_message(const byte_t* const _data, std::uint32_t _data_length,
+ std::uint32_t _max_message_size) :
+ timepoint_creation_(std::chrono::steady_clock::now()),
+ max_message_size_(_max_message_size),
+ current_message_size_(0),
+ last_segment_received_(false) {
+ if (_data_length < VSOMEIP_FULL_HEADER_SIZE + VSOMEIP_TP_HEADER_SIZE) {
+ VSOMEIP_ERROR << __func__ << " received too short SOME/IP-TP message "
+ << get_message_id(_data, _data_length);
+ return;
+ }
+ // copy header
+ message_.insert(message_.end(), _data, _data + VSOMEIP_FULL_HEADER_SIZE);
+ // remove TP flag
+ message_[VSOMEIP_MESSAGE_TYPE_POS] = static_cast<byte_t>(tp::tp_flag_unset(
+ message_[VSOMEIP_MESSAGE_TYPE_POS]));
+
+ const length_t its_segment_size = _data_length - VSOMEIP_FULL_HEADER_SIZE
+ - VSOMEIP_TP_HEADER_SIZE;
+ const tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ _data[VSOMEIP_TP_HEADER_POS_MIN],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ _data[VSOMEIP_TP_HEADER_POS_MAX]);
+
+ if (check_lengths(_data, _data_length, its_segment_size,
+ tp::more_segments(its_tp_header))) {
+ const length_t its_offset = tp::get_offset(its_tp_header);
+ segments_.emplace(segment_t(its_offset, its_offset + its_segment_size - 1));
+ if (its_offset != 0) {
+ // segment different than the first segment was received
+ message_.resize(VSOMEIP_FULL_HEADER_SIZE + its_offset, 0x0);
+ if (!tp::more_segments(its_tp_header)) {
+ // received the last segment of the segmented message first
+ last_segment_received_ = true;
+ }
+ }
+ message_.insert(message_.end(), &_data[VSOMEIP_TP_PAYLOAD_POS],
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_segment_size);
+ current_message_size_ += VSOMEIP_FULL_HEADER_SIZE + its_segment_size;
+ }
+}
+
+bool tp_message::add_segment(const byte_t* const _data,
+ std::uint32_t _data_length) {
+ if (_data_length < VSOMEIP_FULL_HEADER_SIZE + VSOMEIP_TP_HEADER_SIZE) {
+ VSOMEIP_ERROR << __func__ << " received too short SOME/IP-TP message "
+ << get_message_id(_data, _data_length);
+ return false;
+ }
+ bool ret = false;
+
+ const length_t its_segment_size = _data_length - VSOMEIP_FULL_HEADER_SIZE
+ - VSOMEIP_TP_HEADER_SIZE;
+ const tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ _data[VSOMEIP_TP_HEADER_POS_MIN],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ _data[VSOMEIP_TP_HEADER_POS_MAX]);
+
+ if (check_lengths(_data, _data_length, its_segment_size,
+ tp::more_segments(its_tp_header))) {
+ const length_t its_offset = tp::get_offset(its_tp_header);
+ const auto emplace_res = segments_.emplace(
+ segment_t(its_offset, its_offset + its_segment_size - 1));
+ if (!emplace_res.second) {
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " received duplicate segment " << get_message_id(_data, _data_length)
+ << "TP offset: 0x" << std::hex << its_offset;
+ } else {
+ const auto& seg_current = emplace_res.first;
+ const auto& seg_next = std::next(seg_current);
+ const bool current_segment_is_last = (seg_next == segments_.end());
+ const bool current_segment_is_first = (seg_current == segments_.begin());
+ if (current_segment_is_last) {
+ if (current_segment_is_first) {
+ // received segment of message but the first received segment was invalid
+ // resize + append
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " received 2nd segment of message. But the "
+ "first received segment already wasn't accepted. "
+ "The message can't be completed anymore: "
+ << get_message_id(_data, _data_length);
+ if (its_offset != 0) {
+ // segment different than the first segment was received
+ message_.resize(VSOMEIP_FULL_HEADER_SIZE + its_offset, 0x0);
+ if (!tp::more_segments(its_tp_header)) {
+ // received the last segment of the segmented message first
+ last_segment_received_ = true;
+ }
+ }
+ // append to end of message
+ message_.insert(message_.end(), &_data[VSOMEIP_TP_PAYLOAD_POS],
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_segment_size);
+ current_message_size_ += its_segment_size;
+ } else {
+ const auto& seg_prev = std::prev(seg_current);
+ if (seg_prev->end_ < seg_current->start_) {
+ const bool direct_previous_segment_present = (seg_prev->end_ + 1 == seg_current->start_);
+ if (!direct_previous_segment_present) {
+ // received segment out of order behind the current end of received segments
+ //resize + append
+ message_.resize(VSOMEIP_FULL_HEADER_SIZE + its_offset, 0x0);
+ }
+ // append to end of message
+ message_.insert(message_.end(), &_data[VSOMEIP_TP_PAYLOAD_POS],
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_segment_size);
+ current_message_size_ += its_segment_size;
+ } else {
+ // this segment starts before the end of the previous and
+ // would overwrite already received data
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " completely accepting segment would overwrite previous segment "
+ << get_message_id(_data, _data_length)
+ << "previous segment end: " << std::dec << seg_prev->end_ + 1
+ << " this segment start: " << std::dec << seg_current->start_;
+ message_.insert(message_.end(),
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + ((seg_prev->end_ + 1) - seg_current->start_),
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_segment_size);
+ // update start of current segment
+ const std::uint32_t current_end = seg_current->end_;
+ segments_.erase(seg_current);
+ segments_.emplace(segment_t(seg_prev->end_ + 1, current_end));
+ current_message_size_ += current_end - seg_prev->end_;
+ }
+ }
+ } else {
+ // received segment in wrong order and other segments afterwards were already received
+ if ((seg_current != segments_.begin() && std::prev(seg_current)->end_ < seg_current->start_)
+ || seg_current == segments_.begin()) { // no need to check prev_segment if current segment is the first
+ if (seg_current->end_ < seg_next->start_) {
+ std::memcpy(&message_[VSOMEIP_FULL_HEADER_SIZE + its_offset], &_data[VSOMEIP_TP_PAYLOAD_POS], its_segment_size);
+ current_message_size_ += its_segment_size;
+ } else {
+ // this segment ends after the start of the next and
+ // would overwrite already received data
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " completely accepting segment would overwrite next segment "
+ << get_message_id(_data, _data_length)
+ << "next segment start: " << std::dec << seg_next->start_
+ << " this segment end: " << std::dec << seg_current->end_ + 1;
+ std::memcpy(&message_[VSOMEIP_FULL_HEADER_SIZE + its_offset], &_data[VSOMEIP_TP_PAYLOAD_POS], seg_next->start_ - its_offset);
+ // update current segment length to match size of memory
+ std::uint32_t current_start = seg_current->start_;
+ segments_.erase(seg_current);
+ segments_.emplace(segment_t(current_start, seg_next->start_ - 1));
+ current_message_size_ += seg_next->start_ - current_start;
+ }
+ } else if (seg_current->end_ < seg_next->start_) {
+ // this segment starts before the end of the previous and
+ // would overwrite already received data. But ends before the
+ // start of the next segment
+ const auto& seg_prev = std::prev(seg_current);
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " completely accepting segment would overwrite previous segment "
+ << get_message_id(_data, _data_length)
+ << "previous segment end: " << std::dec << seg_prev->end_
+ << " this segment start: " << std::dec << seg_current->start_;
+ const length_t its_corrected_offset = seg_prev->end_ + 1;
+ std::memcpy(&message_[VSOMEIP_FULL_HEADER_SIZE + its_corrected_offset],
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_corrected_offset - its_offset,
+ seg_next->start_ - its_corrected_offset);
+ // update current segment length to match size of memory
+ std::uint32_t current_end = seg_current->end_;
+ segments_.erase(seg_current);
+ segments_.emplace(segment_t(seg_prev->end_ + 1, current_end));
+ current_message_size_ += current_end - seg_prev->end_;
+ } else {
+ // this segment starts before the end of the previous and
+ // ends after the start of the next segment and would
+ // overwrite already received data.
+ const auto& seg_prev = std::prev(seg_current);
+ VSOMEIP_WARNING << __func__ << ":" << __LINE__
+ << " completely accepting segment would overwrite "
+ << "previous and next segment "
+ << get_message_id(_data, _data_length)
+ << "previous segment end: " << std::dec << seg_prev->end_
+ << " this segment start: " << std::dec << seg_current->start_
+ << " this segment end: " << std::dec << seg_current->end_
+ << " next segment start: " << std::dec << seg_next->start_;
+ const length_t its_corrected_offset = seg_prev->end_ + 1;
+ std::memcpy(&message_[VSOMEIP_FULL_HEADER_SIZE + its_corrected_offset],
+ &_data[VSOMEIP_TP_PAYLOAD_POS] + its_corrected_offset - its_offset,
+ seg_next->start_ - its_corrected_offset);
+ segments_.erase(seg_current);
+ segments_.emplace(segment_t(seg_prev->end_ + 1, seg_next->start_ - 1));
+ current_message_size_ += seg_next->start_ - (seg_prev->end_ + 1);
+ }
+ }
+ if (!tp::more_segments(its_tp_header)) {
+ // received the last segment
+ last_segment_received_ = true;
+ }
+ if (last_segment_received_) {
+ // check if all segments are present
+ std::uint32_t last_end = (std::numeric_limits<std::uint32_t>::max)();
+ bool complete(true);
+ for (const auto& seg : segments_) {
+ if (last_end + 1 != seg.start_) {
+ complete = false;
+ break;
+ } else {
+ last_end = seg.end_;
+ }
+ }
+ if (complete) {
+ // all segments were received -> update length field of message
+ const length_t its_length = static_cast<length_t>(
+ message_.size() - VSOMEIP_SOMEIP_HEADER_SIZE);
+ *(reinterpret_cast<length_t*>(&message_[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length);
+ // all segments were received -> update return code field of message
+ message_[VSOMEIP_RETURN_CODE_POS] = _data[VSOMEIP_RETURN_CODE_POS];
+ ret = true;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+message_buffer_t tp_message::get_message() {
+ return std::move(message_);
+}
+
+std::chrono::steady_clock::time_point tp_message::get_creation_time() const {
+ return timepoint_creation_;
+}
+
+std::string tp_message::get_message_id(const byte_t* const _data, std::uint32_t _data_length) {
+ std::stringstream ss;
+ if (_data_length >= VSOMEIP_FULL_HEADER_SIZE) {
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_SESSION_POS_MIN], _data[VSOMEIP_SESSION_POS_MAX]);
+ const interface_version_t its_interface_version =
+ _data[VSOMEIP_INTERFACE_VERSION_POS];
+ const message_type_e its_msg_type = tp::tp_flag_unset(
+ _data[VSOMEIP_MESSAGE_TYPE_POS]);
+
+ ss << "("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ") ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_interface_version) << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_msg_type) << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_session
+ << "] ";
+ if (_data_length > VSOMEIP_TP_HEADER_POS_MAX) {
+ const tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ _data[VSOMEIP_TP_HEADER_POS_MIN],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ _data[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ _data[VSOMEIP_TP_HEADER_POS_MAX]);
+ const length_t its_offset = tp::get_offset(its_tp_header);
+ ss << " TP offset: 0x" << std::hex << its_offset << " ";
+ }
+ }
+ return ss.str();
+}
+
+bool tp_message::check_lengths(const byte_t* const _data,
+ std::uint32_t _data_length,
+ length_t _segment_size, bool _more_fragments) {
+ const length_t its_length = VSOMEIP_BYTES_TO_LONG(
+ _data[VSOMEIP_LENGTH_POS_MIN],
+ _data[VSOMEIP_LENGTH_POS_MIN + 1],
+ _data[VSOMEIP_LENGTH_POS_MIN + 2],
+ _data[VSOMEIP_LENGTH_POS_MAX]);
+ bool ret(true);
+ if (!tp::tp_flag_is_set(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ VSOMEIP_ERROR << __func__ << ": TP flag not set "
+ << get_message_id(_data, _data_length);
+ ret = false;
+ } else if (_data_length != its_length + VSOMEIP_SOMEIP_HEADER_SIZE) {
+ VSOMEIP_ERROR << __func__
+ << ": data length doesn't match header length field"
+ << get_message_id(_data, _data_length)
+ << " data: " << std::dec << _data_length
+ << " header: " << std::dec << its_length;
+ ret = false;
+ } else if (_segment_size != its_length - VSOMEIP_TP_HEADER_SIZE
+ - (VSOMEIP_FULL_HEADER_SIZE - VSOMEIP_SOMEIP_HEADER_SIZE)) {
+ VSOMEIP_ERROR << __func__
+ << ": segment size doesn't align with header length field"
+ << get_message_id(_data, _data_length)
+ << "segment size: " << std::dec << _segment_size
+ << " data: " << std::dec << _data_length
+ << " header: " << std::dec << its_length;
+ ret = false;
+ } else if (_segment_size > tp::tp_max_segment_length_) {
+ VSOMEIP_ERROR << __func__ << ": Segment exceeds allowed size "
+ << get_message_id(_data, _data_length)
+ << "segment size: " << std::dec << _segment_size << " (max. "
+ << std::dec << tp::tp_max_segment_length_
+ << ") data: " << std::dec << _data_length
+ << " header: " << std::dec << its_length;
+ ret = false;
+ } else if (_more_fragments && _segment_size % 16 > 0) {
+ VSOMEIP_ERROR << __func__ << ": Segment size not multiple of 16 "
+ << get_message_id(_data, _data_length)
+ << "segment size: " << std::dec << _segment_size
+ << " data: " << std::dec << _data_length
+ << " header: " << std::dec << its_length;
+ ret = false;
+ } else if (current_message_size_ + _segment_size > max_message_size_) {
+ VSOMEIP_ERROR << __func__ << ": Message exceeds maximum configured size: "
+ << get_message_id(_data, _data_length)
+ << "segment size: " << std::dec << _segment_size
+ << " current message size: " << std::dec << current_message_size_
+ << " maximum message size: " << std::dec << max_message_size_;
+ ret = false;
+ }
+ return ret;
+}
+
+} // namespace tp
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/tp_reassembler.cpp b/implementation/endpoints/src/tp_reassembler.cpp
new file mode 100644
index 0000000..07a31e0
--- /dev/null
+++ b/implementation/endpoints/src/tp_reassembler.cpp
@@ -0,0 +1,202 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+
+#include "../include/tp_reassembler.hpp"
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/enumeration_types.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/tp.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+namespace vsomeip_v3 {
+namespace tp {
+
+tp_reassembler::tp_reassembler(std::uint32_t _max_message_size, boost::asio::io_service &_io) :
+ max_message_size_(_max_message_size),
+ cleanup_timer_running_(false),
+ cleanup_timer_(_io) {
+}
+
+std::pair<bool, message_buffer_t> tp_reassembler::process_tp_message(
+ const byte_t* const _data, std::uint32_t _data_size,
+ const boost::asio::ip::address& _address, std::uint16_t _port) {
+ std::pair<bool, message_buffer_t> ret;
+ if (_data_size < VSOMEIP_FULL_HEADER_SIZE) {
+ return std::make_pair(false, message_buffer_t());
+ }
+
+ cleanup_timer_start(false);
+
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN],
+ _data[VSOMEIP_SERVICE_POS_MAX]);
+ const method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
+ _data[VSOMEIP_METHOD_POS_MAX]);
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
+ _data[VSOMEIP_CLIENT_POS_MAX]);
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SESSION_POS_MIN],
+ _data[VSOMEIP_SESSION_POS_MAX]);
+ const interface_version_t its_interface_version = _data[VSOMEIP_INTERFACE_VERSION_POS];
+ const message_type_e its_msg_type = tp::tp_flag_unset(_data[VSOMEIP_MESSAGE_TYPE_POS]);
+
+ const std::uint64_t its_tp_message_id = ((static_cast<std::uint64_t>(its_service) << 48) |
+ (static_cast<std::uint64_t>(its_method) << 32) |
+ (static_cast<std::uint64_t>(its_client) << 16) |
+ (static_cast<std::uint64_t>(its_interface_version) << 8) |
+ (static_cast<std::uint64_t>(its_msg_type)));
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ ret.first = false;
+ const auto found_ip = tp_messages_.find(_address);
+ if (found_ip != tp_messages_.end()) {
+ const auto found_port = found_ip->second.find(_port);
+ if (found_port != found_ip->second.end()) {
+ auto found_tp_msg = found_port->second.find(its_tp_message_id);
+ if (found_tp_msg != found_port->second.end()) {
+ if (found_tp_msg->second.first == its_session) {
+ // received additional segment for already known message
+ if (found_tp_msg->second.second.add_segment(_data, _data_size)) {
+ // message is complete
+ ret.first = true;
+ ret.second = found_tp_msg->second.second.get_message();
+ // cleanup tp_message as message was moved and cleanup map
+ found_port->second.erase(its_tp_message_id);
+ if (found_port->second.empty()) {
+ found_ip->second.erase(found_port);
+ if (found_ip->second.empty()) {
+ tp_messages_.erase(found_ip);
+ }
+ }
+ }
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Received new segment "
+ "although old one is not finished yet. Dropping "
+ "old. ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ") ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_interface_version) << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_msg_type) << "] Old: 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << found_tp_msg->second.first << ", new: 0x"
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ // new segment with different session id -> throw away current
+ found_tp_msg->second.first = its_session;
+ found_tp_msg->second.second = tp_message(_data, _data_size, max_message_size_);
+ }
+ } else {
+ found_port->second.emplace(
+ std::make_pair(its_tp_message_id,
+ std::make_pair(its_session,
+ tp_message(_data, _data_size, max_message_size_))));
+ }
+ } else {
+ found_ip->second[_port].emplace(
+ std::make_pair(its_tp_message_id,
+ std::make_pair(its_session,
+ tp_message(_data, _data_size, max_message_size_))));
+ }
+ } else {
+ tp_messages_[_address][_port].emplace(
+ std::make_pair(its_tp_message_id,
+ std::make_pair(its_session,
+ tp_message(_data, _data_size, max_message_size_))));
+ }
+ return ret;
+}
+
+bool tp_reassembler::cleanup_unfinished_messages() {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ const std::chrono::steady_clock::time_point now =
+ std::chrono::steady_clock::now();
+ for (auto ip_iter = tp_messages_.begin(); ip_iter != tp_messages_.end();) {
+ for (auto port_iter = ip_iter->second.begin();
+ port_iter != ip_iter->second.end();) {
+ for (auto tp_id_iter = port_iter->second.begin();
+ tp_id_iter != port_iter->second.end();) {
+ if (std::chrono::duration_cast<std::chrono::milliseconds>(
+ now - tp_id_iter->second.second.get_creation_time()).count()
+ > 5000) {
+ // message is older than 5 seconds delete it
+ const service_t its_service = static_cast<service_t>(tp_id_iter->first >> 48);
+ const method_t its_method = static_cast<method_t>(tp_id_iter->first >> 32);
+ const client_t its_client = static_cast<client_t>(tp_id_iter->first >> 16);
+ const interface_version_t its_interface_version = static_cast<interface_version_t>(tp_id_iter->first >> 8);
+ const message_type_e its_msg_type = static_cast<message_type_e>(tp_id_iter->first >> 0);
+ VSOMEIP_WARNING << __func__
+ << ": deleting unfinished SOME/IP-TP message from: "
+ << ip_iter->first.to_string() << ":" << std::dec
+ << port_iter->first << " ("
+ << std::hex << std::setw(4) << std::setfill('0') << its_client << ") ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_method << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_interface_version) << "."
+ << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(its_msg_type) << "."
+ << std::hex << std::setw(4) << std::setfill('0') << tp_id_iter->second.first << "]";
+ tp_id_iter = port_iter->second.erase(tp_id_iter);
+ } else {
+ tp_id_iter++;
+ }
+ }
+ if (port_iter->second.empty()) {
+ port_iter = ip_iter->second.erase(port_iter);
+ } else {
+ port_iter++;
+ }
+ }
+ if (ip_iter->second.empty()) {
+ ip_iter = tp_messages_.erase(ip_iter);
+ } else {
+ ip_iter++;
+ }
+ }
+ return !tp_messages_.empty();
+}
+
+void tp_reassembler::stop() {
+ std::lock_guard<std::mutex> its_lock(cleanup_timer_mutex_);
+ boost::system::error_code ec;
+ cleanup_timer_.cancel(ec);
+}
+
+void tp_reassembler::cleanup_timer_start(bool _force) {
+ std::lock_guard<std::mutex> its_lock(cleanup_timer_mutex_);
+ cleanup_timer_start_unlocked(_force);
+}
+
+void tp_reassembler::cleanup_timer_start_unlocked(bool _force) {
+ boost::system::error_code ec;
+ if (!cleanup_timer_running_ || _force) {
+ cleanup_timer_.expires_from_now(std::chrono::seconds(5));
+ cleanup_timer_running_ = true;
+ cleanup_timer_.async_wait(
+ std::bind(&tp_reassembler::cleanup_timer_cbk,
+ shared_from_this(), std::placeholders::_1));
+ }
+}
+
+void tp_reassembler::cleanup_timer_cbk(
+ const boost::system::error_code _error) {
+ if (!_error) {
+ std::lock_guard<std::mutex> its_lock(cleanup_timer_mutex_);
+ if (cleanup_unfinished_messages()) {
+ cleanup_timer_start_unlocked(true);
+ } else {
+ // don't start timer again as there are no more segmented messages present
+ cleanup_timer_running_ = false;
+ }
+ }
+}
+
+} //namespace tp
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/udp_client_endpoint_impl.cpp b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
index 67c9703..ec8c991 100644
--- a/implementation/endpoints/src/udp_client_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_client_endpoint_impl.cpp
@@ -1,382 +1,439 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <iomanip>
-#include <sstream>
-
-#include <boost/asio/ip/multicast.hpp>
-
-#include "../include/endpoint_host.hpp"
-#include "../include/udp_client_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/utility.hpp"
-
-namespace vsomeip {
-
-udp_client_endpoint_impl::udp_client_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local,
- endpoint_type _remote,
- boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _udp_receive_buffer_size)
- : udp_client_endpoint_base_impl(_host, _local, _remote, _io,
- VSOMEIP_MAX_UDP_MESSAGE_SIZE, _queue_limit),
- remote_address_(_remote.address()),
- remote_port_(_remote.port()),
- udp_receive_buffer_size_(_udp_receive_buffer_size) {
-}
-
-udp_client_endpoint_impl::~udp_client_endpoint_impl() {
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (its_host) {
- its_host->release_port(local_.port(), false);
- }
-}
-
-bool udp_client_endpoint_impl::is_local() const {
- return false;
-}
-
-void udp_client_endpoint_impl::connect() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::system::error_code its_error;
- socket_->open(remote_.protocol(), its_error);
- if (!its_error || its_error == boost::asio::error::already_open) {
- // Enable SO_REUSEADDR to avoid bind problems with services going offline
- // and coming online again and the user has specified only a small number
- // of ports in the clients section for one service instance
- socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't enable "
- << "SO_REUSEADDR: " << its_error.message() << " remote:"
- << get_address_port_remote();
- }
- socket_->set_option(boost::asio::socket_base::receive_buffer_size(
- udp_receive_buffer_size_), its_error);
- if (its_error) {
- VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't set "
- << "SO_RCVBUF: " << its_error.message() << " to: "
- << std::dec << udp_receive_buffer_size_ << " remote:"
- << get_address_port_remote();
- } else {
- boost::asio::socket_base::receive_buffer_size its_option;
- socket_->get_option(its_option, its_error);
- if (its_error) {
- VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
- << "SO_RCVBUF: " << its_error.message() << " remote:"
- << get_address_port_remote();
- } else {
- VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
- << std::dec << its_option.value();
- }
- }
-
- // In case a client endpoint port was configured,
- // bind to it before connecting
- if (local_.port() != ILLEGAL_PORT) {
- boost::system::error_code its_bind_error;
- socket_->bind(local_, its_bind_error);
- if(its_bind_error) {
- VSOMEIP_WARNING << "udp_client_endpoint::connect: "
- "Error binding socket: " << its_bind_error.message()
- << " remote:" << get_address_port_remote();
- try {
- // don't connect on bind error to avoid using a random port
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iomanip>
+#include <sstream>
+
+#include <boost/asio/ip/multicast.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/endpoint_host.hpp"
+#include "../include/tp.hpp"
+#include "../../routing/include/routing_host.hpp"
+#include "../include/udp_client_endpoint_impl.hpp"
+#include "../../utility/include/utility.hpp"
+
+namespace vsomeip_v3 {
+
+udp_client_endpoint_impl::udp_client_endpoint_impl(
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
+ const endpoint_type& _remote,
+ boost::asio::io_service &_io,
+ const std::shared_ptr<configuration>& _configuration)
+ : udp_client_endpoint_base_impl(_endpoint_host, _routing_host, _local,
+ _remote, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE,
+ _configuration->get_endpoint_queue_limit(
+ _remote.address().to_string(),
+ _remote.port()),
+ _configuration),
+ remote_address_(_remote.address()),
+ remote_port_(_remote.port()),
+ udp_receive_buffer_size_(_configuration->get_udp_receive_buffer_size()),
+ tp_reassembler_(std::make_shared<tp::tp_reassembler>(
+ _configuration->get_max_message_size_unreliable(), _io)) {
+ is_supporting_someip_tp_ = true;
+}
+
+udp_client_endpoint_impl::~udp_client_endpoint_impl() {
+ std::shared_ptr<endpoint_host> its_host = endpoint_host_.lock();
+ if (its_host) {
+ its_host->release_port(local_.port(), false);
+ }
+ tp_reassembler_->stop();
+}
+
+bool udp_client_endpoint_impl::is_local() const {
+ return false;
+}
+
+void udp_client_endpoint_impl::connect() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::system::error_code its_error;
+ socket_->open(remote_.protocol(), its_error);
+ if (!its_error || its_error == boost::asio::error::already_open) {
+ // Enable SO_REUSEADDR to avoid bind problems with services going offline
+ // and coming online again and the user has specified only a small number
+ // of ports in the clients section for one service instance
+ socket_->set_option(boost::asio::socket_base::reuse_address(true), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't enable "
+ << "SO_REUSEADDR: " << its_error.message() << " remote:"
+ << get_address_port_remote();
+ }
+ socket_->set_option(boost::asio::socket_base::receive_buffer_size(
+ udp_receive_buffer_size_), its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't set "
+ << "SO_RCVBUF: " << its_error.message() << " to: "
+ << std::dec << udp_receive_buffer_size_ << " remote:"
+ << get_address_port_remote();
+ } else {
+ boost::asio::socket_base::receive_buffer_size its_option;
+ socket_->get_option(its_option, its_error);
+ if (its_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::connect: couldn't get "
+ << "SO_RCVBUF: " << its_error.message() << " remote:"
+ << get_address_port_remote();
+ } else {
+ VSOMEIP_INFO << "udp_client_endpoint_impl::connect: SO_RCVBUF is: "
+ << std::dec << its_option.value();
+ }
+ }
+
+#ifndef _WIN32
+ // If specified, bind to device
+ std::string its_device(configuration_->get_device());
+ if (its_device != "") {
+ if (setsockopt(socket_->native_handle(),
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ VSOMEIP_WARNING << "UDP Client: Could not bind to device \"" << its_device << "\"";
+ }
+ }
+#endif
+
+ // In case a client endpoint port was configured,
+ // bind to it before connecting
+ if (local_.port() != ILLEGAL_PORT) {
+ boost::system::error_code its_bind_error;
+ socket_->bind(local_, its_bind_error);
+ if(its_bind_error) {
+ VSOMEIP_WARNING << "udp_client_endpoint::connect: "
+ "Error binding socket: " << its_bind_error.message()
+ << " remote:" << get_address_port_remote();
+ try {
+ // don't connect on bind error to avoid using a random port
strand_.post(std::bind(&client_endpoint_impl::connect_cbk,
- shared_from_this(), its_bind_error));
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
- << e.what() << " remote:" << get_address_port_remote();
- }
- return;
- }
- }
- state_ = cei_state_e::CONNECTING;
- socket_->async_connect(
- remote_,
+ shared_from_this(), its_bind_error));
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "udp_client_endpoint_impl::connect: "
+ << e.what() << " remote:" << get_address_port_remote();
+ }
+ return;
+ }
+ }
+
+ state_ = cei_state_e::CONNECTING;
+ socket_->async_connect(
+ remote_,
strand_.wrap(
std::bind(
&udp_client_endpoint_base_impl::connect_cbk,
shared_from_this(),
std::placeholders::_1
)
- )
- );
- } else {
- VSOMEIP_WARNING << "udp_client_endpoint::connect: Error opening socket: "
- << its_error.message() << " remote:" << get_address_port_remote();
- strand_.post(std::bind(&udp_client_endpoint_base_impl::connect_cbk,
- shared_from_this(), its_error));
- }
-}
-
-void udp_client_endpoint_impl::start() {
- connect();
-}
-
-void udp_client_endpoint_impl::restart(bool _force) {
- if (!_force && state_ == cei_state_e::CONNECTING) {
- return;
- }
- state_ = cei_state_e::CONNECTING;
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- queue_.clear();
- }
- std::string local;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- local = get_address_port_local();
- }
- shutdown_and_close_socket(false);
- was_not_connected_ = true;
- reconnect_counter_ = 0;
- VSOMEIP_WARNING << "uce::restart: local: " << local
- << " remote: " << get_address_port_remote();
- start_connect_timer();
-}
-
-void udp_client_endpoint_impl::send_queued() {
- message_buffer_ptr_t its_buffer;
- if(queue_.size()) {
- its_buffer = queue_.front();
- } else {
- return;
- }
-#if 0
- std::stringstream msg;
- msg << "ucei<" << remote_.address() << ":"
- << std::dec << remote_.port() << ">::sq: ";
- for (std::size_t i = 0; i < its_buffer->size(); i++)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int)(*its_buffer)[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_->async_send(
- boost::asio::buffer(*its_buffer),
- std::bind(
- &udp_client_endpoint_base_impl::send_cbk,
- shared_from_this(),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer
- )
- );
- }
-}
-
-void udp_client_endpoint_impl::receive() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (!socket_->is_open()) {
- return;
- }
- message_buffer_ptr_t its_buffer = std::make_shared<message_buffer_t>(VSOMEIP_MAX_UDP_MESSAGE_SIZE);
- socket_->async_receive_from(
- boost::asio::buffer(*its_buffer),
- remote_,
- strand_.wrap(
- std::bind(
- &udp_client_endpoint_impl::receive_cbk,
- std::dynamic_pointer_cast<
- udp_client_endpoint_impl
- >(shared_from_this()),
- std::placeholders::_1,
- std::placeholders::_2,
- its_buffer
- )
- )
- );
-}
-
-bool udp_client_endpoint_impl::get_remote_address(
- boost::asio::ip::address &_address) const {
- if (remote_address_.is_unspecified()) {
- return false;
- }
- _address = remote_address_;
- return true;
-}
-
-void udp_client_endpoint_impl::set_local_port() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- boost::system::error_code its_error;
- if (socket_->is_open()) {
- endpoint_type its_endpoint = socket_->local_endpoint(its_error);
- if (!its_error) {
- local_port_ = its_endpoint.port();
- } else {
- VSOMEIP_WARNING << "udp_client_endpoint_impl::set_local_port() "
- << " couldn't get local_endpoint: " << its_error.message();
- }
- }
-}
-
-std::uint16_t udp_client_endpoint_impl::get_remote_port() const {
- return remote_port_;
-}
-
-void udp_client_endpoint_impl::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes,
- message_buffer_ptr_t _recv_buffer) {
- if (_error == boost::asio::error::operation_aborted) {
- // endpoint was stopped
- return;
- }
- std::shared_ptr<endpoint_host> its_host = host_.lock();
- if (!_error && 0 < _bytes && its_host) {
-#if 0
- std::stringstream msg;
- msg << "ucei::rcb(" << _error.message() << "): ";
- for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
- msg << std::hex << std::setw(2) << std::setfill('0')
- << (int) (*_recv_buffer)[i] << " ";
- VSOMEIP_INFO << msg.str();
-#endif
- std::size_t remaining_bytes = _bytes;
- std::size_t i = 0;
-
- do {
- uint64_t read_message_size
- = utility::get_message_size(&(*_recv_buffer)[i],
- remaining_bytes);
- if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
- VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
- return;
- }
- uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
- if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
- current_message_size <= remaining_bytes) {
- if (remaining_bytes - current_message_size > remaining_bytes) {
- VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
- return;
- } else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
- ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
- !utility::is_valid_message_type(static_cast<message_type_e>((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
- !utility::is_valid_return_code(static_cast<return_code_e>((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))
- )) {
- if ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
- VSOMEIP_ERROR << "uce: Wrong protocol version: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- // ensure to send back a message w/ wrong protocol version
- its_host->on_message(&(*_recv_buffer)[i],
- VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
- boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT,
- remote_address_,
- remote_port_);
- } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
- (*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
- VSOMEIP_ERROR << "uce: Invalid message type: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
- (*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))) {
- VSOMEIP_ERROR << "uce: Invalid return code: 0x"
- << std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS])
- << " local: " << get_address_port_local()
- << " remote: " << get_address_port_remote();
- }
- receive();
- return;
- }
- remaining_bytes -= current_message_size;
-
- its_host->on_message(&(*_recv_buffer)[i], current_message_size,
- this, boost::asio::ip::address(),
- VSOMEIP_ROUTING_CLIENT, remote_address_,
- remote_port_);
- } else {
- VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad "
- "length field. Message size: " << current_message_size
- << " Bytes. From: " << remote_.address() << ":"
- << remote_.port() << ". Dropping message.";
- remaining_bytes = 0;
- }
- i += current_message_size;
- } while (remaining_bytes > 0);
- }
- if (!_error) {
- receive();
- } else {
- if (_error == boost::asio::error::connection_refused) {
- shutdown_and_close_socket(false);
- } else {
- receive();
- }
- }
-}
-
-const std::string udp_client_endpoint_impl::get_address_port_remote() const {
- boost::system::error_code ec;
- std::string its_address_port;
- its_address_port.reserve(21);
- boost::asio::ip::address its_address;
- if (get_remote_address(its_address)) {
- its_address_port += its_address.to_string();
- }
- its_address_port += ":";
- its_address_port += std::to_string(remote_port_);
- return its_address_port;
-}
-
-const std::string udp_client_endpoint_impl::get_address_port_local() const {
- std::string its_address_port;
- its_address_port.reserve(21);
- boost::system::error_code ec;
- if (socket_->is_open()) {
- endpoint_type its_local_endpoint = socket_->local_endpoint(ec);
- if (!ec) {
- its_address_port += its_local_endpoint.address().to_string(ec);
- its_address_port += ":";
- its_address_port.append(std::to_string(its_local_endpoint.port()));
- }
- }
- return its_address_port;
-}
-
-void udp_client_endpoint_impl::print_status() {
- std::size_t its_data_size(0);
- std::size_t its_queue_size(0);
- {
- std::lock_guard<std::mutex> its_lock(mutex_);
- its_queue_size = queue_.size();
- its_data_size = queue_size_;
- }
- std::string local;
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- local = get_address_port_local();
- }
-
- VSOMEIP_INFO << "status uce: " << local << " -> "
- << get_address_port_remote()
- << " queue: " << std::dec << its_queue_size
- << " data: " << std::dec << its_data_size;
-}
-
-std::string udp_client_endpoint_impl::get_remote_information() const {
- boost::system::error_code ec;
- return remote_.address().to_string(ec) + ":"
- + std::to_string(remote_.port());
-}
-
-std::uint32_t udp_client_endpoint_impl::get_max_allowed_reconnects() const {
- return MAX_RECONNECTS_UNLIMITED;
-}
-
-void udp_client_endpoint_impl::max_allowed_reconnects_reached() {
- return;
-}
-
-} // namespace vsomeip
+ )
+ );
+ } else {
+ VSOMEIP_WARNING << "udp_client_endpoint::connect: Error opening socket: "
+ << its_error.message() << " remote:" << get_address_port_remote();
+ strand_.post(std::bind(&udp_client_endpoint_base_impl::connect_cbk,
+ shared_from_this(), its_error));
+ }
+}
+
+void udp_client_endpoint_impl::start() {
+ connect();
+}
+
+void udp_client_endpoint_impl::restart(bool _force) {
+ if (!_force && state_ == cei_state_e::CONNECTING) {
+ return;
+ }
+ state_ = cei_state_e::CONNECTING;
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ queue_.clear();
+ }
+ std::string local;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ local = get_address_port_local();
+ }
+ shutdown_and_close_socket(false);
+ was_not_connected_ = true;
+ reconnect_counter_ = 0;
+ VSOMEIP_WARNING << "uce::restart: local: " << local
+ << " remote: " << get_address_port_remote();
+ start_connect_timer();
+}
+
+void udp_client_endpoint_impl::send_queued() {
+ message_buffer_ptr_t its_buffer;
+ if(queue_.size()) {
+ its_buffer = queue_.front();
+ } else {
+ return;
+ }
+#if 0
+ std::stringstream msg;
+ msg << "ucei<" << remote_.address() << ":"
+ << std::dec << remote_.port() << ">::sq: ";
+ for (std::size_t i = 0; i < its_buffer->size(); i++)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int)(*its_buffer)[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ socket_->async_send(
+ boost::asio::buffer(*its_buffer),
+ std::bind(
+ &udp_client_endpoint_base_impl::send_cbk,
+ shared_from_this(),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer
+ )
+ );
+ }
+}
+
+void udp_client_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ configuration_->get_configured_timing_requests(_service,
+ remote_address_.to_string(), remote_port_, _method,
+ _debouncing, _maximum_retention);
+}
+
+void udp_client_endpoint_impl::receive() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ if (!socket_->is_open()) {
+ return;
+ }
+ message_buffer_ptr_t its_buffer = std::make_shared<message_buffer_t>(VSOMEIP_MAX_UDP_MESSAGE_SIZE);
+ socket_->async_receive_from(
+ boost::asio::buffer(*its_buffer),
+ const_cast<endpoint_type&>(remote_),
+ strand_.wrap(
+ std::bind(
+ &udp_client_endpoint_impl::receive_cbk,
+ std::dynamic_pointer_cast<
+ udp_client_endpoint_impl
+ >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ its_buffer
+ )
+ )
+ );
+}
+
+bool udp_client_endpoint_impl::get_remote_address(
+ boost::asio::ip::address &_address) const {
+ if (remote_address_.is_unspecified()) {
+ return false;
+ }
+ _address = remote_address_;
+ return true;
+}
+
+void udp_client_endpoint_impl::set_local_port() {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ boost::system::error_code its_error;
+ if (socket_->is_open()) {
+ endpoint_type its_endpoint = socket_->local_endpoint(its_error);
+ if (!its_error) {
+ local_port_ = its_endpoint.port();
+ } else {
+ VSOMEIP_WARNING << "udp_client_endpoint_impl::set_local_port() "
+ << " couldn't get local_endpoint: " << its_error.message();
+ }
+ }
+}
+
+std::uint16_t udp_client_endpoint_impl::get_remote_port() const {
+ return remote_port_;
+}
+
+void udp_client_endpoint_impl::receive_cbk(
+ boost::system::error_code const &_error, std::size_t _bytes,
+ const message_buffer_ptr_t& _recv_buffer) {
+ if (_error == boost::asio::error::operation_aborted) {
+ // endpoint was stopped
+ return;
+ }
+ std::shared_ptr<routing_host> its_host = routing_host_.lock();
+ if (!_error && 0 < _bytes && its_host) {
+#if 0
+ std::stringstream msg;
+ msg << "ucei::rcb(" << _error.message() << "): ";
+ for (std::size_t i = 0; i < _bytes + recv_buffer_size_; ++i)
+ msg << std::hex << std::setw(2) << std::setfill('0')
+ << (int) (*_recv_buffer)[i] << " ";
+ VSOMEIP_INFO << msg.str();
+#endif
+ std::size_t remaining_bytes = _bytes;
+ std::size_t i = 0;
+
+ do {
+ uint64_t read_message_size
+ = utility::get_message_size(&(*_recv_buffer)[i],
+ remaining_bytes);
+ if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
+ VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
+ return;
+ }
+ uint32_t current_message_size = static_cast<uint32_t>(read_message_size);
+ if (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
+ current_message_size <= remaining_bytes) {
+ if (remaining_bytes - current_message_size > remaining_bytes) {
+ VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
+ return;
+ } else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
+ ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(tp::tp::tp_flag_unset((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))
+ )) {
+ if ((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ VSOMEIP_ERROR << "uce: Wrong protocol version: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_PROTOCOL_VERSION_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ // ensure to send back a message w/ wrong protocol version
+ its_host->on_message(&(*_recv_buffer)[i],
+ VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
+ boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ } else if (!utility::is_valid_message_type(tp::tp::tp_flag_unset(
+ (*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ VSOMEIP_ERROR << "uce: Invalid message type: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ } else if (!utility::is_valid_return_code(static_cast<return_code_e>(
+ (*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS]))) {
+ VSOMEIP_ERROR << "uce: Invalid return code: 0x"
+ << std::hex << std::setw(2) << std::setfill('0')
+ << std::uint32_t((*_recv_buffer)[i + VSOMEIP_RETURN_CODE_POS])
+ << " local: " << get_address_port_local()
+ << " remote: " << get_address_port_remote();
+ }
+ receive();
+ return;
+ } else if (tp::tp::tp_flag_is_set((*_recv_buffer)[i + VSOMEIP_MESSAGE_TYPE_POS])) {
+ const auto res = tp_reassembler_->process_tp_message(
+ &(*_recv_buffer)[i], current_message_size,
+ remote_address_, remote_port_);
+ if (res.first) {
+ its_host->on_message(&res.second[0],
+ static_cast<std::uint32_t>(res.second.size()),
+ this, boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ }
+ } else {
+ its_host->on_message(&(*_recv_buffer)[i], current_message_size,
+ this, boost::asio::ip::address(),
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ remote_address_,
+ remote_port_);
+ }
+ remaining_bytes -= current_message_size;
+ } else {
+ VSOMEIP_ERROR << "Received a unreliable vSomeIP message with bad "
+ "length field. Message size: " << current_message_size
+ << " Bytes. From: " << remote_.address() << ":"
+ << remote_.port() << ". Dropping message.";
+ remaining_bytes = 0;
+ }
+ i += current_message_size;
+ } while (remaining_bytes > 0);
+ }
+ if (!_error) {
+ receive();
+ } else {
+ if (_error == boost::asio::error::connection_refused) {
+ shutdown_and_close_socket(false);
+ } else {
+ receive();
+ }
+ }
+}
+
+const std::string udp_client_endpoint_impl::get_address_port_remote() const {
+ boost::system::error_code ec;
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::asio::ip::address its_address;
+ if (get_remote_address(its_address)) {
+ its_address_port += its_address.to_string();
+ }
+ its_address_port += ":";
+ its_address_port += std::to_string(remote_port_);
+ return its_address_port;
+}
+
+const std::string udp_client_endpoint_impl::get_address_port_local() const {
+ std::string its_address_port;
+ its_address_port.reserve(21);
+ boost::system::error_code ec;
+ if (socket_->is_open()) {
+ endpoint_type its_local_endpoint = socket_->local_endpoint(ec);
+ if (!ec) {
+ its_address_port += its_local_endpoint.address().to_string(ec);
+ its_address_port += ":";
+ its_address_port.append(std::to_string(its_local_endpoint.port()));
+ }
+ }
+ return its_address_port;
+}
+
+void udp_client_endpoint_impl::print_status() {
+ std::size_t its_data_size(0);
+ std::size_t its_queue_size(0);
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ its_queue_size = queue_.size();
+ its_data_size = queue_size_;
+ }
+ std::string local;
+ {
+ std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ local = get_address_port_local();
+ }
+
+ VSOMEIP_INFO << "status uce: " << local << " -> "
+ << get_address_port_remote()
+ << " queue: " << std::dec << its_queue_size
+ << " data: " << std::dec << its_data_size;
+}
+
+std::string udp_client_endpoint_impl::get_remote_information() const {
+ boost::system::error_code ec;
+ return remote_.address().to_string(ec) + ":"
+ + std::to_string(remote_.port());
+}
+
+bool udp_client_endpoint_impl::tp_segmentation_enabled(service_t _service,
+ method_t _method) const {
+ return configuration_->tp_segment_messages_client_to_service(_service,
+ remote_address_.to_string(), remote_port_, _method);
+}
+
+bool udp_client_endpoint_impl::is_reliable() const {
+ return false;
+}
+
+std::uint32_t udp_client_endpoint_impl::get_max_allowed_reconnects() const {
+ return MAX_RECONNECTS_UNLIMITED;
+}
+
+void udp_client_endpoint_impl::max_allowed_reconnects_reached() {
+ return;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/udp_server_endpoint_impl.cpp b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
index 6ad7ce8..0a65b2e 100644
--- a/implementation/endpoints/src/udp_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/udp_server_endpoint_impl.cpp
@@ -9,70 +9,87 @@
#include <boost/asio/ip/multicast.hpp>
#include <vsomeip/constants.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/endpoint_definition.hpp"
#include "../include/endpoint_host.hpp"
+#include "../include/tp.hpp"
+#include "../../routing/include/routing_host.hpp"
#include "../include/udp_server_endpoint_impl.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
#include "../../service_discovery/include/defines.hpp"
namespace ip = boost::asio::ip;
-namespace vsomeip {
+namespace vsomeip_v3 {
udp_server_endpoint_impl::udp_server_endpoint_impl(
- std::shared_ptr< endpoint_host > _host,
- endpoint_type _local,
+ const std::shared_ptr<endpoint_host>& _endpoint_host,
+ const std::shared_ptr<routing_host>& _routing_host,
+ const endpoint_type& _local,
boost::asio::io_service &_io,
- configuration::endpoint_queue_limit_t _queue_limit,
- std::uint32_t _udp_receive_buffer_size)
- : server_endpoint_impl<ip::udp_ext>(
- _host, _local, _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE, _queue_limit),
- socket_(_io, _local.protocol()),
+ const std::shared_ptr<configuration>& _configuration) :
+ server_endpoint_impl<ip::udp_ext>(_endpoint_host, _routing_host, _local,
+ _io, VSOMEIP_MAX_UDP_MESSAGE_SIZE,
+ _configuration->get_endpoint_queue_limit(_configuration->get_unicast_address().to_string(), _local.port()),
+ _configuration),
+ unicast_socket_(_io, _local.protocol()),
+ unicast_recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0),
joined_group_(false),
- recv_buffer_(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0),
- local_port_(_local.port()) {
+ local_port_(_local.port()),
+ tp_reassembler_(std::make_shared<tp::tp_reassembler>(_configuration->get_max_message_size_unreliable(), _io)),
+ tp_cleanup_timer_(_io) {
+ is_supporting_someip_tp_ = true;
+
boost::system::error_code ec;
boost::asio::socket_base::reuse_address optionReuseAddress(true);
- socket_.set_option(optionReuseAddress, ec);
+ unicast_socket_.set_option(optionReuseAddress, ec);
boost::asio::detail::throw_error(ec, "reuse address");
- socket_.bind(_local, ec);
+#ifndef _WIN32
+ // If specified, bind to device
+ std::string its_device(configuration_->get_device());
+ if (its_device != "") {
+ if (setsockopt(unicast_socket_.native_handle(),
+ SOL_SOCKET, SO_BINDTODEVICE, its_device.c_str(), (int)its_device.size()) == -1) {
+ VSOMEIP_WARNING << "UDP Server: Could not bind to device \"" << its_device << "\"";
+ }
+ }
+#endif
+
+ unicast_socket_.bind(_local, ec);
boost::asio::detail::throw_error(ec, "bind");
- if (_local.address().is_v4()) {
- boost::asio::ip::address_v4 its_unicast_address
- = _host->get_configuration()->get_unicast_address().to_v4();
- boost::asio::ip::multicast::outbound_interface option(its_unicast_address);
- socket_.set_option(option, ec);
+ if (local_.address().is_v4()) {
+ boost::asio::ip::multicast::outbound_interface option(_local.address().to_v4());
+ unicast_socket_.set_option(option, ec);
boost::asio::detail::throw_error(ec, "outbound interface option IPv4");
- } else if (_local.address().is_v6()) {
- boost::asio::ip::address_v6 its_unicast_address
- = _host->get_configuration()->get_unicast_address().to_v6();
+ } else if (local_.address().is_v6()) {
boost::asio::ip::multicast::outbound_interface option(
- static_cast<unsigned int>(its_unicast_address.scope_id()));
- socket_.set_option(option, ec);
+ static_cast<unsigned int>(local_.address().to_v6().scope_id()));
+ unicast_socket_.set_option(option, ec);
boost::asio::detail::throw_error(ec, "outbound interface option IPv6");
}
boost::asio::socket_base::broadcast option(true);
- socket_.set_option(option, ec);
+ unicast_socket_.set_option(option, ec);
boost::asio::detail::throw_error(ec, "broadcast option");
+ const std::uint32_t its_udp_recv_buffer_size =
+ configuration_->get_udp_receive_buffer_size();
+ unicast_socket_.set_option(boost::asio::socket_base::receive_buffer_size(
+ its_udp_recv_buffer_size), ec);
- socket_.set_option(boost::asio::socket_base::receive_buffer_size(
- _udp_receive_buffer_size), ec);
if (ec) {
VSOMEIP_WARNING << "udp_server_endpoint_impl:: couldn't set "
<< "SO_RCVBUF: " << ec.message() << " to: " << std::dec
- << _udp_receive_buffer_size << " local port: " << std::dec
+ << its_udp_recv_buffer_size << " local port: " << std::dec
<< local_port_;
} else {
boost::asio::socket_base::receive_buffer_size its_option;
- socket_.get_option(its_option, ec);
+ unicast_socket_.get_option(its_option, ec);
if (ec) {
VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
<< "SO_RCVBUF: " << ec.message() << " local port:"
@@ -83,14 +100,13 @@ udp_server_endpoint_impl::udp_server_endpoint_impl(
}
}
-
#ifdef _WIN32
const char* optval("0001");
- ::setsockopt(socket_.native(), IPPROTO_IP, IP_PKTINFO,
+ ::setsockopt(unicast_socket_.native_handle(), IPPROTO_IP, IP_PKTINFO,
optval, sizeof(optval));
#else
int optval(1);
- ::setsockopt(socket_.native(), IPPROTO_IP, IP_PKTINFO,
+ ::setsockopt(unicast_socket_.native_handle(), IPPROTO_IP, IP_PKTINFO,
&optval, sizeof(optval));
#endif
}
@@ -108,24 +124,63 @@ void udp_server_endpoint_impl::start() {
void udp_server_endpoint_impl::stop() {
server_endpoint_impl::stop();
+
{
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if (socket_.is_open()) {
+ std::lock_guard<std::mutex> its_lock(unicast_socket_mutex_);
+
+ if (unicast_socket_.is_open()) {
boost::system::error_code its_error;
- socket_.shutdown(socket_type::shutdown_both, its_error);
- socket_.close(its_error);
+ unicast_socket_.shutdown(socket_type::shutdown_both, its_error);
+ unicast_socket_.close(its_error);
}
}
+
+ {
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+
+ if (multicast_socket_ && multicast_socket_->is_open()) {
+ boost::system::error_code its_error;
+ multicast_socket_->shutdown(socket_type::shutdown_both, its_error);
+ multicast_socket_->close(its_error);
+ }
+ }
+
+ tp_reassembler_->stop();
}
void udp_server_endpoint_impl::receive() {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- if(socket_.is_open()) {
- socket_.async_receive_from(
- boost::asio::buffer(&recv_buffer_[0], max_message_size_),
- remote_,
+ receive_unicast();
+ receive_multicast();
+}
+
+void udp_server_endpoint_impl::receive_unicast() {
+ std::lock_guard<std::mutex> its_lock(unicast_socket_mutex_);
+
+ if(unicast_socket_.is_open()) {
+ unicast_socket_.async_receive_from(
+ boost::asio::buffer(&unicast_recv_buffer_[0], max_message_size_),
+ unicast_remote_,
std::bind(
- &udp_server_endpoint_impl::receive_cbk,
+ &udp_server_endpoint_impl::on_unicast_received,
+ std::dynamic_pointer_cast<
+ udp_server_endpoint_impl >(shared_from_this()),
+ std::placeholders::_1,
+ std::placeholders::_2,
+ std::placeholders::_3
+ )
+ );
+ }
+}
+
+void udp_server_endpoint_impl::receive_multicast() {
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+
+ if (multicast_socket_ && multicast_socket_->is_open()) {
+ multicast_socket_->async_receive_from(
+ boost::asio::buffer(&(*multicast_recv_buffer_)[0], max_message_size_),
+ multicast_remote_,
+ std::bind(
+ &udp_server_endpoint_impl::on_multicast_received,
std::dynamic_pointer_cast<
udp_server_endpoint_impl >(shared_from_this()),
std::placeholders::_1,
@@ -138,14 +193,39 @@ void udp_server_endpoint_impl::receive() {
bool udp_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush) {
+ const byte_t *_data, uint32_t _size) {
std::lock_guard<std::mutex> its_lock(mutex_);
endpoint_type its_target(_target->get_address(), _target->get_port());
- return send_intern(its_target, _data, _size, _flush);
+ return send_intern(its_target, _data, _size);
+}
+
+bool udp_server_endpoint_impl::send_error(
+ const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) {
+ bool ret(false);
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ const endpoint_type its_target(_target->get_address(), _target->get_port());
+ const queue_iterator_type target_queue_iterator(find_or_create_queue_unlocked(its_target));
+ auto& its_qpair = target_queue_iterator->second;
+ const bool queue_size_zero_on_entry(its_qpair.second.empty());
+
+ if (check_message_size(nullptr, _size, its_target) == endpoint_impl::cms_ret_e::MSG_OK &&
+ check_queue_limit(_data, _size, its_qpair.first)) {
+ its_qpair.second.emplace_back(
+ std::make_shared<message_buffer_t>(_data, _data + _size));
+ its_qpair.first += _size;
+
+ if (queue_size_zero_on_entry) { // no writing in progress
+ send_queued(target_queue_iterator);
+ }
+ ret = true;
+ }
+ return ret;
}
void udp_server_endpoint_impl::send_queued(
const queue_iterator_type _queue_iterator) {
+
message_buffer_ptr_t its_buffer = _queue_iterator->second.second.front();
#if 0
std::stringstream msg;
@@ -156,9 +236,9 @@ void udp_server_endpoint_impl::send_queued(
<< (int)(*its_buffer)[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
- {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_.async_send_to(
+ std::lock_guard<std::mutex> its_lock(unicast_socket_mutex_);
+
+ unicast_socket_.async_send_to(
boost::asio::buffer(*its_buffer),
_queue_iterator->first,
std::bind(
@@ -169,7 +249,16 @@ void udp_server_endpoint_impl::send_queued(
std::placeholders::_2
)
);
- }
+}
+
+void udp_server_endpoint_impl::get_configured_times_from_endpoint(
+ service_t _service, method_t _method,
+ std::chrono::nanoseconds *_debouncing,
+ std::chrono::nanoseconds *_maximum_retention) const {
+ configuration_->get_configured_timing_responses(_service,
+ udp_server_endpoint_base_impl::local_.address().to_string(),
+ udp_server_endpoint_base_impl::local_.port(), _method,
+ _debouncing, _maximum_retention);
}
bool udp_server_endpoint_impl::is_joined(const std::string &_address) const {
@@ -193,6 +282,70 @@ void udp_server_endpoint_impl::join(const std::string &_address) {
auto join_func = [this](const std::string &_address) {
try {
+ VSOMEIP_TRACE << "Joining to multicast group " << _address
+ << " from " << local_.address().to_string();
+
+ boost::system::error_code ec;
+
+ if (!multicast_recv_buffer_) {
+ multicast_recv_buffer_ = std::unique_ptr<message_buffer_t>(
+ new message_buffer_t(VSOMEIP_MAX_UDP_MESSAGE_SIZE, 0));
+ }
+
+ if (!multicast_ep_) {
+ multicast_ep_ = std::unique_ptr<endpoint_type>(
+ new endpoint_type(boost::asio::ip::address_v4::any(), local_port_));
+ }
+
+ if (!multicast_socket_) {
+ multicast_socket_ = std::unique_ptr<socket_type>(
+ new socket_type(service_, local_.protocol()));
+
+ boost::asio::socket_base::reuse_address optionReuseAddress(true);
+ multicast_socket_->set_option(optionReuseAddress, ec);
+ boost::asio::detail::throw_error(ec, "reuse address in multicast");
+
+ multicast_socket_->bind(*multicast_ep_, ec);
+ boost::asio::detail::throw_error(ec, "bind multicast");
+
+ const std::uint32_t its_udp_recv_buffer_size =
+ configuration_->get_udp_receive_buffer_size();
+
+ multicast_socket_->set_option(boost::asio::socket_base::receive_buffer_size(
+ its_udp_recv_buffer_size), ec);
+
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl:: couldn't set "
+ << "SO_RCVBUF: " << ec.message() << " to: " << std::dec
+ << its_udp_recv_buffer_size << " local port: " << std::dec
+ << local_port_;
+ } else {
+ boost::asio::socket_base::receive_buffer_size its_option;
+ multicast_socket_->get_option(its_option, ec);
+
+ if (ec) {
+ VSOMEIP_WARNING << "udp_server_endpoint_impl: couldn't get "
+ << "SO_RCVBUF: " << ec.message() << " local port:"
+ << std::dec << local_port_;
+ } else {
+ VSOMEIP_INFO << "udp_server_endpoint_impl: SO_RCVBUF (Multicast) is: "
+ << std::dec << its_option.value();
+ }
+ }
+
+#ifdef _WIN32
+ const char* optval("0001");
+ ::setsockopt(multicast_socket_->native_handle(), IPPROTO_IP, IP_PKTINFO,
+ optval, sizeof(optval));
+#else
+ int optval(1);
+ ::setsockopt(multicast_socket_->native_handle(), IPPROTO_IP, IP_PKTINFO,
+ &optval, sizeof(optval));
+#endif
+
+ receive_multicast();
+ }
+
bool is_v4(false);
bool is_v6(false);
{
@@ -200,30 +353,31 @@ void udp_server_endpoint_impl::join(const std::string &_address) {
is_v4 = local_.address().is_v4();
is_v6 = local_.address().is_v6();
}
+
if (is_v4) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_.set_option(ip::udp_ext::socket::reuse_address(true));
- socket_.set_option(
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+ multicast_socket_->set_option(ip::udp_ext::socket::reuse_address(true));
+ multicast_socket_->set_option(
boost::asio::ip::multicast::enable_loopback(false));
#ifdef _WIN32
- socket_.set_option(boost::asio::ip::multicast::join_group(
+ multicast_socket_->set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v4(),
local_.address().to_v4()));
#else
- socket_.set_option(boost::asio::ip::multicast::join_group(
+ multicast_socket_->set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v4()));
#endif
} else if (is_v6) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_.set_option(ip::udp_ext::socket::reuse_address(true));
- socket_.set_option(
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+ multicast_socket_->set_option(ip::udp_ext::socket::reuse_address(true));
+ multicast_socket_->set_option(
boost::asio::ip::multicast::enable_loopback(false));
#ifdef _WIN32
- socket_.set_option(boost::asio::ip::multicast::join_group(
+ multicast_socket_->set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v6(),
local_.address().to_v6().scope_id()));
#else
- socket_.set_option(boost::asio::ip::multicast::join_group(
+ multicast_socket_->set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string(_address).to_v6()));
#endif
}
@@ -249,6 +403,9 @@ void udp_server_endpoint_impl::join(const std::string &_address) {
void udp_server_endpoint_impl::leave(const std::string &_address) {
try {
if (is_joined(_address)) {
+ VSOMEIP_TRACE << "Leaving the multicast group " << _address
+ << " from " << local_.address().to_string();
+
bool is_v4(false);
bool is_v6(false);
{
@@ -257,12 +414,12 @@ void udp_server_endpoint_impl::leave(const std::string &_address) {
is_v6 = local_.address().is_v6();
}
if (is_v4) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_.set_option(boost::asio::ip::multicast::leave_group(
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+ multicast_socket_->set_option(boost::asio::ip::multicast::leave_group(
boost::asio::ip::address::from_string(_address)));
} else if (is_v6) {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
- socket_.set_option(boost::asio::ip::multicast::leave_group(
+ std::lock_guard<std::mutex> its_lock(multicast_socket_mutex_);
+ multicast_socket_->set_option(boost::asio::ip::multicast::leave_group(
boost::asio::ip::address::from_string(_address)));
}
{
@@ -270,6 +427,10 @@ void udp_server_endpoint_impl::leave(const std::string &_address) {
joined_.erase(_address);
if (!joined_.size()) {
joined_group_ = false;
+
+ multicast_socket_.reset(nullptr);
+ multicast_ep_.reset(nullptr);
+ multicast_recv_buffer_.reset(nullptr);
}
}
}
@@ -308,10 +469,32 @@ std::uint16_t udp_server_endpoint_impl::get_local_port() const {
return local_port_;
}
-// TODO: find a better way to structure the receive functions
-void udp_server_endpoint_impl::receive_cbk(
- boost::system::error_code const &_error, std::size_t _bytes,
+void udp_server_endpoint_impl::on_unicast_received(
+ boost::system::error_code const &_error,
+ std::size_t _bytes,
+ boost::asio::ip::address const &_destination) {
+ on_message_received(_error, _bytes, _destination, unicast_remote_, unicast_recv_buffer_);
+ receive_unicast();
+}
+
+void udp_server_endpoint_impl::on_multicast_received(
+ boost::system::error_code const &_error,
+ std::size_t _bytes,
boost::asio::ip::address const &_destination) {
+
+ // Filter messages sent from the same source address
+ if (multicast_remote_.address() != local_.address()) {
+ on_message_received(_error, _bytes, _destination, multicast_remote_, *multicast_recv_buffer_);
+ }
+
+ receive_multicast();
+}
+
+void udp_server_endpoint_impl::on_message_received(
+ boost::system::error_code const &_error, std::size_t _bytes,
+ boost::asio::ip::address const &_destination,
+ endpoint_type const &_remote,
+ message_buffer_t const &_buffer) {
#if 0
std::stringstream msg;
msg << "usei::rcb(" << _error.message() << "): ";
@@ -320,16 +503,17 @@ void udp_server_endpoint_impl::receive_cbk(
<< (int) recv_buffer_[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
- std::shared_ptr<endpoint_host> its_host = this->host_.lock();
+ std::shared_ptr<routing_host> its_host = routing_host_.lock();
+
if (its_host) {
if (!_error && 0 < _bytes) {
std::size_t remaining_bytes = _bytes;
std::size_t i = 0;
- const boost::asio::ip::address its_remote_address(remote_.address());
- const std::uint16_t its_remote_port(remote_.port());
+ const boost::asio::ip::address its_remote_address(_remote.address());
+ const std::uint16_t its_remote_port(_remote.port());
do {
uint64_t read_message_size
- = utility::get_message_size(&this->recv_buffer_[i],
+ = utility::get_message_size(&_buffer[i],
remaining_bytes);
if (read_message_size > MESSAGE_SIZE_UNLIMITED) {
VSOMEIP_ERROR << "Message size exceeds allowed maximum!";
@@ -342,62 +526,58 @@ void udp_server_endpoint_impl::receive_cbk(
VSOMEIP_ERROR << "buffer underflow in udp client endpoint ~> abort!";
return;
} else if (current_message_size > VSOMEIP_RETURN_CODE_POS &&
- (recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
- !utility::is_valid_message_type(static_cast<message_type_e>(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
- !utility::is_valid_return_code(static_cast<return_code_e>(recv_buffer_[i + VSOMEIP_RETURN_CODE_POS]))
+ (_buffer[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION ||
+ !utility::is_valid_message_type(tp::tp::tp_flag_unset(_buffer[i + VSOMEIP_MESSAGE_TYPE_POS])) ||
+ !utility::is_valid_return_code(static_cast<return_code_e>(_buffer[i + VSOMEIP_RETURN_CODE_POS]))
)) {
- if (recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
+ if (_buffer[i + VSOMEIP_PROTOCOL_VERSION_POS] != VSOMEIP_PROTOCOL_VERSION) {
VSOMEIP_ERROR << "use: Wrong protocol version: 0x"
<< std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t(recv_buffer_[i + VSOMEIP_PROTOCOL_VERSION_POS])
+ << std::uint32_t(_buffer[i + VSOMEIP_PROTOCOL_VERSION_POS])
<< " local: " << get_address_port_local()
<< " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
// ensure to send back a message w/ wrong protocol version
- its_host->on_message(&recv_buffer_[i],
+ its_host->on_message(&_buffer[i],
VSOMEIP_SOMEIP_HEADER_SIZE + 8, this,
_destination,
VSOMEIP_ROUTING_CLIENT,
- its_remote_address,
- its_remote_port);
- } else if (!utility::is_valid_message_type(static_cast<message_type_e>(
- recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
+ std::make_pair(ANY_UID, ANY_GID),
+ its_remote_address, its_remote_port);
+ } else if (!utility::is_valid_message_type(tp::tp::tp_flag_unset(
+ _buffer[i + VSOMEIP_MESSAGE_TYPE_POS]))) {
VSOMEIP_ERROR << "use: Invalid message type: 0x"
<< std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])
+ << std::uint32_t(_buffer[i + VSOMEIP_MESSAGE_TYPE_POS])
<< " local: " << get_address_port_local()
<< " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
} else if (!utility::is_valid_return_code(static_cast<return_code_e>(
- recv_buffer_[i + VSOMEIP_RETURN_CODE_POS]))) {
+ _buffer[i + VSOMEIP_RETURN_CODE_POS]))) {
VSOMEIP_ERROR << "use: Invalid return code: 0x"
<< std::hex << std::setw(2) << std::setfill('0')
- << std::uint32_t(recv_buffer_[i + VSOMEIP_RETURN_CODE_POS])
+ << std::uint32_t(_buffer[i + VSOMEIP_RETURN_CODE_POS])
<< " local: " << get_address_port_local()
<< " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
}
- receive();
return;
}
remaining_bytes -= current_message_size;
- service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[i + VSOMEIP_SERVICE_POS_MIN],
- recv_buffer_[i + VSOMEIP_SERVICE_POS_MAX]);
+ const service_t its_service = VSOMEIP_BYTES_TO_WORD(_buffer[i + VSOMEIP_SERVICE_POS_MIN],
+ _buffer[i + VSOMEIP_SERVICE_POS_MAX]);
if (utility::is_request(
- recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])) {
- client_t its_client;
- std::memcpy(&its_client,
- &recv_buffer_[i + VSOMEIP_CLIENT_POS_MIN],
- sizeof(client_t));
- if (its_client != MAGIC_COOKIE_NETWORK_BYTE_ORDER) {
- session_t its_session;
- std::memcpy(&its_session,
- &recv_buffer_[i + VSOMEIP_SESSION_POS_MIN],
- sizeof(session_t));
+ _buffer[i + VSOMEIP_MESSAGE_TYPE_POS])) {
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ _buffer[i + VSOMEIP_CLIENT_POS_MIN],
+ _buffer[i + VSOMEIP_CLIENT_POS_MAX]);
+ if (its_client != MAGIC_COOKIE_CLIENT) {
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ _buffer[i + VSOMEIP_SESSION_POS_MIN],
+ _buffer[i + VSOMEIP_SESSION_POS_MAX]);
clients_mutex_.lock();
- clients_[its_client][its_session] = remote_;
- endpoint_to_client_[remote_] = its_client;
+ clients_[its_client][its_session] = _remote;
clients_mutex_.unlock();
}
} else if (its_service != VSOMEIP_SD_SERVICE
- && utility::is_notification(recv_buffer_[i + VSOMEIP_MESSAGE_TYPE_POS])
+ && utility::is_notification(_buffer[i + VSOMEIP_MESSAGE_TYPE_POS])
&& joined_group_) {
std::lock_guard<std::mutex> its_lock(joined_mutex_);
boost::system::error_code ec;
@@ -406,61 +586,91 @@ void udp_server_endpoint_impl::receive_cbk(
found_address->second = true;
}
}
- if (its_service != VSOMEIP_SD_SERVICE ||
- (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
- current_message_size >= remaining_bytes)) {
- its_host->on_message(&recv_buffer_[i],
- current_message_size, this, _destination,
- VSOMEIP_ROUTING_CLIENT, its_remote_address,
- its_remote_port);
+ if (tp::tp::tp_flag_is_set(_buffer[i + VSOMEIP_MESSAGE_TYPE_POS])) {
+ const auto res = tp_reassembler_->process_tp_message(
+ &_buffer[i], current_message_size,
+ its_remote_address, its_remote_port);
+ if (res.first) {
+ if (utility::is_request(res.second[VSOMEIP_MESSAGE_TYPE_POS])) {
+ const client_t its_client = VSOMEIP_BYTES_TO_WORD(
+ res.second[VSOMEIP_CLIENT_POS_MIN],
+ res.second[VSOMEIP_CLIENT_POS_MAX]);
+ if (its_client != MAGIC_COOKIE_CLIENT) {
+ const session_t its_session = VSOMEIP_BYTES_TO_WORD(
+ res.second[VSOMEIP_SESSION_POS_MIN],
+ res.second[VSOMEIP_SESSION_POS_MAX]);
+ clients_mutex_.lock();
+ clients_[its_client][its_session] = _remote;
+ clients_mutex_.unlock();
+ }
+ } else if (its_service != VSOMEIP_SD_SERVICE
+ && utility::is_notification(res.second[VSOMEIP_MESSAGE_TYPE_POS])
+ && joined_group_) {
+ std::lock_guard<std::mutex> its_lock(joined_mutex_);
+ boost::system::error_code ec;
+ const auto found_address = joined_.find(_destination.to_string(ec));
+ if (found_address != joined_.end()) {
+ found_address->second = true;
+ }
+ }
+ its_host->on_message(&res.second[0],
+ static_cast<std::uint32_t>(res.second.size()),
+ this, _destination, VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ its_remote_address, its_remote_port);
+ }
} else {
- //ignore messages for service discovery with shorter SomeIP length
- VSOMEIP_ERROR << "Received an unreliable vSomeIP SD message with too short length field";
+ if (its_service != VSOMEIP_SD_SERVICE ||
+ (current_message_size > VSOMEIP_SOMEIP_HEADER_SIZE &&
+ current_message_size >= remaining_bytes)) {
+ its_host->on_message(&_buffer[i],
+ current_message_size, this, _destination,
+ VSOMEIP_ROUTING_CLIENT,
+ std::make_pair(ANY_UID, ANY_GID),
+ its_remote_address, its_remote_port);
+ } else {
+ //ignore messages for service discovery with shorter SomeIP length
+ VSOMEIP_ERROR << "Received an unreliable vSomeIP SD message with too short length field"
+ << " local: " << get_address_port_local()
+ << " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
+ }
}
i += current_message_size;
} else {
- VSOMEIP_ERROR << "Received an unreliable vSomeIP message with bad length field";
+ VSOMEIP_ERROR << "Received an unreliable vSomeIP message with bad length field"
+ << " local: " << get_address_port_local()
+ << " remote: " << its_remote_address << ":" << std::dec << its_remote_port;
if (remaining_bytes > VSOMEIP_SERVICE_POS_MAX) {
- service_t its_service = VSOMEIP_BYTES_TO_WORD(recv_buffer_[VSOMEIP_SERVICE_POS_MIN],
- recv_buffer_[VSOMEIP_SERVICE_POS_MAX]);
+ service_t its_service = VSOMEIP_BYTES_TO_WORD(_buffer[VSOMEIP_SERVICE_POS_MIN],
+ _buffer[VSOMEIP_SERVICE_POS_MAX]);
if (its_service != VSOMEIP_SD_SERVICE) {
if (read_message_size == 0) {
VSOMEIP_ERROR << "Ignoring unreliable vSomeIP message with SomeIP message length 0!";
} else {
- its_host->on_error(&recv_buffer_[i],
- (uint32_t)remaining_bytes, this,
- its_remote_address, its_remote_port);
+ auto its_endpoint_host = endpoint_host_.lock();
+ if (its_endpoint_host) {
+ its_endpoint_host->on_error(&_buffer[i],
+ (uint32_t)remaining_bytes, this,
+ its_remote_address, its_remote_port);
+ }
}
}
}
remaining_bytes = 0;
}
} while (remaining_bytes > 0);
- receive();
- } else {
- receive();
}
}
}
-client_t udp_server_endpoint_impl::get_client(std::shared_ptr<endpoint_definition> _endpoint) {
- const endpoint_type endpoint(_endpoint->get_address(), _endpoint->get_port());
- std::lock_guard<std::mutex> its_lock(clients_mutex_);
- auto found_endpoint = endpoint_to_client_.find(endpoint);
- if (found_endpoint != endpoint_to_client_.end()) {
- // TODO: Check system byte order before convert!
- const client_t client = client_t(found_endpoint->second << 8 | found_endpoint->second >> 8);
- return client;
- }
- return 0;
-}
-
void udp_server_endpoint_impl::print_status() {
std::lock_guard<std::mutex> its_lock(mutex_);
VSOMEIP_INFO << "status use: " << std::dec << local_port_
<< " number queues: " << std::dec << queues_.size()
- << " recv_buffer: " << std::dec << recv_buffer_.capacity();
+ << " recv_buffer: " << std::dec << unicast_recv_buffer_.capacity()
+ << " multicast_recv_buffer: " << std::dec
+ << (multicast_recv_buffer_ ? multicast_recv_buffer_->capacity() : 0);
for (const auto &c : queues_) {
std::size_t its_data_size(0);
@@ -484,13 +694,24 @@ std::string udp_server_endpoint_impl::get_remote_information(
+ std::to_string(_queue_iterator->first.port());
}
+std::string udp_server_endpoint_impl::get_remote_information(
+ const endpoint_type& _remote) const {
+ boost::system::error_code ec;
+ return _remote.address().to_string(ec) + ":"
+ + std::to_string(_remote.port());
+}
+
+bool udp_server_endpoint_impl::is_reliable() const {
+ return false;
+}
+
const std::string udp_server_endpoint_impl::get_address_port_local() const {
- std::lock_guard<std::mutex> its_lock(socket_mutex_);
+ std::lock_guard<std::mutex> its_lock(unicast_socket_mutex_);
std::string its_address_port;
its_address_port.reserve(21);
boost::system::error_code ec;
- if (socket_.is_open()) {
- endpoint_type its_local_endpoint = socket_.local_endpoint(ec);
+ if (unicast_socket_.is_open()) {
+ endpoint_type its_local_endpoint = unicast_socket_.local_endpoint(ec);
if (!ec) {
its_address_port += its_local_endpoint.address().to_string(ec);
its_address_port += ":";
@@ -500,4 +721,11 @@ const std::string udp_server_endpoint_impl::get_address_port_local() const {
return its_address_port;
}
-} // namespace vsomeip
+bool udp_server_endpoint_impl::tp_segmentation_enabled(service_t _service,
+ method_t _method) const {
+ return configuration_->tp_segment_messages_service_to_client(_service,
+ local_.address().to_string(),
+ local_.port(), _method);
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
index 20d40d7..c2c917f 100644
--- a/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
+++ b/implementation/endpoints/src/virtual_server_endpoint_impl.cpp
@@ -3,16 +3,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include <vsomeip/constants.hpp>
-
#include "../include/virtual_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
-namespace vsomeip {
+#include <vsomeip/constants.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+namespace vsomeip_v3 {
virtual_server_endpoint_impl::virtual_server_endpoint_impl(
- const std::string &_address, uint16_t _port, bool _reliable)
- : address_(_address), port_(_port), reliable_(_reliable), use_count_(0) {
+ const std::string &_address, uint16_t _port, bool _reliable,
+ boost::asio::io_service& _service)
+ : address_(_address), port_(_port), reliable_(_reliable), use_count_(0),
+ service_(_service) {
}
virtual_server_endpoint_impl::~virtual_server_endpoint_impl() {
@@ -21,6 +23,14 @@ virtual_server_endpoint_impl::~virtual_server_endpoint_impl() {
void virtual_server_endpoint_impl::start() {
}
+void virtual_server_endpoint_impl::prepare_stop(endpoint::prepare_stop_handler_t _handler,
+ service_t _service) {
+ auto ptr = shared_from_this();
+ service_.post([ptr, _handler, _service]() {
+ _handler(ptr, _service);
+ });
+}
+
void virtual_server_endpoint_impl::stop() {
}
@@ -28,6 +38,10 @@ bool virtual_server_endpoint_impl::is_established() const {
return false;
}
+bool virtual_server_endpoint_impl::is_established_or_connected() const {
+ return false;
+}
+
void virtual_server_endpoint_impl::set_established(bool _established) {
(void) _established;
}
@@ -36,46 +50,43 @@ void virtual_server_endpoint_impl::set_connected(bool _connected) {
(void) _connected;
}
-bool virtual_server_endpoint_impl::send(const byte_t *_data, uint32_t _size,
- bool _flush) {
+bool virtual_server_endpoint_impl::send(const byte_t *_data, uint32_t _size) {
(void)_data;
(void)_size;
- (void)_flush;
return false;
}
bool virtual_server_endpoint_impl::send(const std::vector<byte_t>& _cmd_header,
- const byte_t *_data, uint32_t _size,
- bool _flush) {
+ const byte_t *_data, uint32_t _size) {
(void)_cmd_header;
(void)_data;
(void)_size;
- (void)_flush;
return false;
}
bool virtual_server_endpoint_impl::send_to(
const std::shared_ptr<endpoint_definition> _target,
- const byte_t *_data, uint32_t _size, bool _flush) {
+ const byte_t *_data, uint32_t _size) {
(void)_target;
(void)_data;
(void)_size;
- (void)_flush;
return false;
}
-void virtual_server_endpoint_impl::enable_magic_cookies() {
+bool virtual_server_endpoint_impl::send_error(
+ const std::shared_ptr<endpoint_definition> _target,
+ const byte_t *_data, uint32_t _size) {
+ (void)_target;
+ (void)_data;
+ (void)_size;
+ return false;
}
-void virtual_server_endpoint_impl::receive() {
-}
-void virtual_server_endpoint_impl::join(const std::string &_address) {
- (void)_address;
+void virtual_server_endpoint_impl::enable_magic_cookies() {
}
-void virtual_server_endpoint_impl::leave(const std::string &_address) {
- (void)_address;
+void virtual_server_endpoint_impl::receive() {
}
void virtual_server_endpoint_impl::add_default_target(
@@ -140,4 +151,7 @@ void virtual_server_endpoint_impl::print_status() {
}
-} // namespace vsomeip
+size_t virtual_server_endpoint_impl::get_queue_size() const {
+ return 0;;
+}
+} // namespace vsomeip_v3
diff --git a/implementation/helper/boost/asio/basic_datagram_socket_ext.hpp b/implementation/helper/1.55/boost/asio/basic_datagram_socket_ext.hpp
index 98314b9..43b2d93 100644
--- a/implementation/helper/boost/asio/basic_datagram_socket_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/basic_datagram_socket_ext.hpp
@@ -1,954 +1,954 @@
-//
-// basic_datagram_socket_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
-#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <iostream>
-
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <boost/asio/basic_socket.hpp>
-#include <boost/asio/datagram_socket_service_ext.hpp>
-#include <boost/asio/detail/handler_type_requirements_ext.hpp>
-#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/detail/type_traits.hpp>
-#include <boost/asio/error.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-
-/// Provides datagram-oriented socket functionality.
-/**
- * The basic_datagram_socket class template provides asynchronous and blocking
- * datagram-oriented socket functionality.
- *
- * @par Thread Safety
- * @e Distinct @e objects: Safe.@n
- * @e Shared @e objects: Unsafe.
- */
-template <typename Protocol,
- typename DatagramSocketService = datagram_socket_service_ext<Protocol> >
-class basic_datagram_socket_ext
- : public basic_socket<Protocol, DatagramSocketService>
-{
-public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename DatagramSocketService::native_handle_type native_type;
-
- /// The native representation of a socket.
- typedef typename DatagramSocketService::native_handle_type native_handle_type;
-
- /// The protocol type.
- typedef Protocol protocol_type;
-
- /// The endpoint type.
- typedef typename Protocol::endpoint endpoint_type;
-
- /// Construct a basic_datagram_socket without opening it.
- /**
- * This constructor creates a datagram socket without opening it. The open()
- * function must be called before data can be sent or received on the socket.
- *
- * @param io_service The io_service object that the datagram socket will use
- * to dispatch handlers for any asynchronous operations performed on the
- * socket.
- */
- explicit basic_datagram_socket_ext(boost::asio::io_service& io_service)
- : basic_socket<Protocol, DatagramSocketService>(io_service)
- {
- }
-
- /// Construct and open a basic_datagram_socket.
- /**
- * This constructor creates and opens a datagram socket.
- *
- * @param io_service The io_service object that the datagram socket will use
- * to dispatch handlers for any asynchronous operations performed on the
- * socket.
- *
- * @param protocol An object specifying protocol parameters to be used.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- basic_datagram_socket_ext(boost::asio::io_service& io_service,
- const protocol_type& protocol)
- : basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
- {
- }
-
- /// Construct a basic_datagram_socket, opening it and binding it to the given
- /// local endpoint.
- /**
- * This constructor creates a datagram socket and automatically opens it bound
- * to the specified endpoint on the local machine. The protocol used is the
- * protocol associated with the given endpoint.
- *
- * @param io_service The io_service object that the datagram socket will use
- * to dispatch handlers for any asynchronous operations performed on the
- * socket.
- *
- * @param endpoint An endpoint on the local machine to which the datagram
- * socket will be bound.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- basic_datagram_socket_ext(boost::asio::io_service& io_service,
- const endpoint_type& endpoint)
- : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
- {
- }
-
- /// Construct a basic_datagram_socket on an existing native socket.
- /**
- * This constructor creates a datagram socket object to hold an existing
- * native socket.
- *
- * @param io_service The io_service object that the datagram socket will use
- * to dispatch handlers for any asynchronous operations performed on the
- * socket.
- *
- * @param protocol An object specifying protocol parameters to be used.
- *
- * @param native_socket The new underlying socket implementation.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- basic_datagram_socket_ext(boost::asio::io_service& io_service,
- const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_socket<Protocol, DatagramSocketService>(
- io_service, protocol, native_socket)
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
- /// Move-construct a basic_datagram_socket from another.
- /**
- * This constructor moves a datagram socket from one object to another.
- *
- * @param other The other basic_datagram_socket object from which the move
- * will occur.
- *
- * @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
- */
- basic_datagram_socket_ext(basic_datagram_socket_ext&& other)
- : basic_socket<Protocol, DatagramSocketService>(
- BOOST_ASIO_MOVE_CAST(basic_datagram_socket_ext)(other))
- {
- }
-
- /// Move-assign a basic_datagram_socket from another.
- /**
- * This assignment operator moves a datagram socket from one object to
- * another.
- *
- * @param other The other basic_datagram_socket object from which the move
- * will occur.
- *
- * @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
- */
- basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other)
- {
- basic_socket<Protocol, DatagramSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_datagram_socket_ext)(other));
- return *this;
- }
-
- /// Move-construct a basic_datagram_socket from a socket of another protocol
- /// type.
- /**
- * This constructor moves a datagram socket from one object to another.
- *
- * @param other The other basic_datagram_socket object from which the move
- * will occur.
- *
- * @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
- */
- template <typename Protocol1, typename DatagramSocketService1>
- basic_datagram_socket_ext(
- basic_datagram_socket_ext<Protocol1, DatagramSocketService1>&& other,
- typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_socket<Protocol, DatagramSocketService>(
- BOOST_ASIO_MOVE_CAST2(basic_datagram_socket_ext<
- Protocol1, DatagramSocketService1>)(other))
- {
- }
-
- /// Move-assign a basic_datagram_socket from a socket of another protocol
- /// type.
- /**
- * This assignment operator moves a datagram socket from one object to
- * another.
- *
- * @param other The other basic_datagram_socket object from which the move
- * will occur.
- *
- * @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
- */
- template <typename Protocol1, typename DatagramSocketService1>
- typename enable_if<is_convertible<Protocol1, Protocol>::value,
- basic_datagram_socket_ext>::type& operator=(
- basic_datagram_socket_ext<Protocol1, DatagramSocketService1>&& other)
- {
- basic_socket<Protocol, DatagramSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST2(basic_datagram_socket_ext<
- Protocol1, DatagramSocketService1>)(other));
- return *this;
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
-
- /// Send some data on a connected socket.
- /**
- * This function is used to send data on the datagram socket. The function
- * call will block until the data has been sent successfully or an error
- * occurs.
- *
- * @param buffers One ore more data buffers to be sent on the socket.
- *
- * @returns The number of bytes sent.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @note The send operation can only be used with a connected socket. Use
- * the send_to function to send data on an unconnected datagram socket.
- *
- * @par Example
- * To send a single data buffer use the @ref buffer function as follows:
- * @code socket.send(boost::asio::buffer(data, size)); @endcode
- * See the @ref buffer documentation for information on sending multiple
- * buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename ConstBufferSequence>
- std::size_t send(const ConstBufferSequence& buffers)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().send(
- this->get_implementation(), buffers, 0, ec);
- boost::asio::detail::throw_error(ec, "send");
- return s;
- }
-
- /// Send some data on a connected socket.
- /**
- * This function is used to send data on the datagram socket. The function
- * call will block until the data has been sent successfully or an error
- * occurs.
- *
- * @param buffers One ore more data buffers to be sent on the socket.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @returns The number of bytes sent.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @note The send operation can only be used with a connected socket. Use
- * the send_to function to send data on an unconnected datagram socket.
- */
- template <typename ConstBufferSequence>
- std::size_t send(const ConstBufferSequence& buffers,
- socket_base::message_flags flags)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().send(
- this->get_implementation(), buffers, flags, ec);
- boost::asio::detail::throw_error(ec, "send");
- return s;
- }
-
- /// Send some data on a connected socket.
- /**
- * This function is used to send data on the datagram socket. The function
- * call will block until the data has been sent successfully or an error
- * occurs.
- *
- * @param buffers One or more data buffers to be sent on the socket.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @returns The number of bytes sent.
- *
- * @note The send operation can only be used with a connected socket. Use
- * the send_to function to send data on an unconnected datagram socket.
- */
- template <typename ConstBufferSequence>
- std::size_t send(const ConstBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return this->get_service().send(
- this->get_implementation(), buffers, flags, ec);
- }
-
- /// Start an asynchronous send on a connected socket.
- /**
- * This function is used to asynchronously send data on the datagram socket.
- * The function call always returns immediately.
- *
- * @param buffers One or more data buffers to be sent on the socket. Although
- * the buffers object may be copied as necessary, ownership of the underlying
- * memory blocks is retained by the caller, which must guarantee that they
- * remain valid until the handler is called.
- *
- * @param handler The handler to be called when the send operation completes.
- * Copies will be made of the handler as required. The function signature of
- * the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes sent.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @note The async_send operation can only be used with a connected socket.
- * Use the async_send_to function to send data on an unconnected datagram
- * socket.
- *
- * @par Example
- * To send a single data buffer use the @ref buffer function as follows:
- * @code
- * socket.async_send(boost::asio::buffer(data, size), handler);
- * @endcode
- * See the @ref buffer documentation for information on sending multiple
- * buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send(const ConstBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- return this->get_service().async_send(this->get_implementation(),
- buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
- }
-
- /// Start an asynchronous send on a connected socket.
- /**
- * This function is used to asynchronously send data on the datagram socket.
- * The function call always returns immediately.
- *
- * @param buffers One or more data buffers to be sent on the socket. Although
- * the buffers object may be copied as necessary, ownership of the underlying
- * memory blocks is retained by the caller, which must guarantee that they
- * remain valid until the handler is called.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @param handler The handler to be called when the send operation completes.
- * Copies will be made of the handler as required. The function signature of
- * the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes sent.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @note The async_send operation can only be used with a connected socket.
- * Use the async_send_to function to send data on an unconnected datagram
- * socket.
- */
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send(const ConstBufferSequence& buffers,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- return this->get_service().async_send(this->get_implementation(),
- buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
- }
-
- /// Send a datagram to the specified endpoint.
- /**
- * This function is used to send a datagram to the specified remote endpoint.
- * The function call will block until the data has been sent successfully or
- * an error occurs.
- *
- * @param buffers One or more data buffers to be sent to the remote endpoint.
- *
- * @param destination The remote endpoint to which the data will be sent.
- *
- * @returns The number of bytes sent.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @par Example
- * To send a single data buffer use the @ref buffer function as follows:
- * @code
- * boost::asio::ip::udp::endpoint destination(
- * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
- * socket.send_to(boost::asio::buffer(data, size), destination);
- * @endcode
- * See the @ref buffer documentation for information on sending multiple
- * buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename ConstBufferSequence>
- std::size_t send_to(const ConstBufferSequence& buffers,
- const endpoint_type& destination)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().send_to(
- this->get_implementation(), buffers, destination, 0, ec);
- boost::asio::detail::throw_error(ec, "send_to");
- return s;
- }
-
- /// Send a datagram to the specified endpoint.
- /**
- * This function is used to send a datagram to the specified remote endpoint.
- * The function call will block until the data has been sent successfully or
- * an error occurs.
- *
- * @param buffers One or more data buffers to be sent to the remote endpoint.
- *
- * @param destination The remote endpoint to which the data will be sent.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @returns The number of bytes sent.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- template <typename ConstBufferSequence>
- std::size_t send_to(const ConstBufferSequence& buffers,
- const endpoint_type& destination, socket_base::message_flags flags)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().send_to(
- this->get_implementation(), buffers, destination, flags, ec);
- boost::asio::detail::throw_error(ec, "send_to");
- return s;
- }
-
- /// Send a datagram to the specified endpoint.
- /**
- * This function is used to send a datagram to the specified remote endpoint.
- * The function call will block until the data has been sent successfully or
- * an error occurs.
- *
- * @param buffers One or more data buffers to be sent to the remote endpoint.
- *
- * @param destination The remote endpoint to which the data will be sent.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @returns The number of bytes sent.
- */
- template <typename ConstBufferSequence>
- std::size_t send_to(const ConstBufferSequence& buffers,
- const endpoint_type& destination, socket_base::message_flags flags,
- boost::system::error_code& ec)
- {
- return this->get_service().send_to(this->get_implementation(),
- buffers, destination, flags, ec);
- }
-
- /// Start an asynchronous send.
- /**
- * This function is used to asynchronously send a datagram to the specified
- * remote endpoint. The function call always returns immediately.
- *
- * @param buffers One or more data buffers to be sent to the remote endpoint.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param destination The remote endpoint to which the data will be sent.
- * Copies will be made of the endpoint as required.
- *
- * @param handler The handler to be called when the send operation completes.
- * Copies will be made of the handler as required. The function signature of
- * the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes sent.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @par Example
- * To send a single data buffer use the @ref buffer function as follows:
- * @code
- * boost::asio::ip::udp::endpoint destination(
- * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
- * socket.async_send_to(
- * boost::asio::buffer(data, size), destination, handler);
- * @endcode
- * See the @ref buffer documentation for information on sending multiple
- * buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send_to(const ConstBufferSequence& buffers,
- const endpoint_type& destination,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- return this->get_service().async_send_to(
- this->get_implementation(), buffers, destination, 0,
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
- }
-
- /// Start an asynchronous send.
- /**
- * This function is used to asynchronously send a datagram to the specified
- * remote endpoint. The function call always returns immediately.
- *
- * @param buffers One or more data buffers to be sent to the remote endpoint.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param flags Flags specifying how the send call is to be made.
- *
- * @param destination The remote endpoint to which the data will be sent.
- * Copies will be made of the endpoint as required.
- *
- * @param handler The handler to be called when the send operation completes.
- * Copies will be made of the handler as required. The function signature of
- * the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes sent.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- */
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send_to(const ConstBufferSequence& buffers,
- const endpoint_type& destination, socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- return this->get_service().async_send_to(
- this->get_implementation(), buffers, destination, flags,
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
- }
-
- /// Receive some data on a connected socket.
- /**
- * This function is used to receive data on the datagram socket. The function
- * call will block until data has been received successfully or an error
- * occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @returns The number of bytes received.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @note The receive operation can only be used with a connected socket. Use
- * the receive_from function to receive data on an unconnected datagram
- * socket.
- *
- * @par Example
- * To receive into a single data buffer use the @ref buffer function as
- * follows:
- * @code socket.receive(boost::asio::buffer(data, size)); @endcode
- * See the @ref buffer documentation for information on receiving into
- * multiple buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename MutableBufferSequence>
- std::size_t receive(const MutableBufferSequence& buffers)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().receive(
- this->get_implementation(), buffers, 0, ec);
- boost::asio::detail::throw_error(ec, "receive");
- return s;
- }
-
- /// Receive some data on a connected socket.
- /**
- * This function is used to receive data on the datagram socket. The function
- * call will block until data has been received successfully or an error
- * occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @returns The number of bytes received.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @note The receive operation can only be used with a connected socket. Use
- * the receive_from function to receive data on an unconnected datagram
- * socket.
- */
- template <typename MutableBufferSequence>
- std::size_t receive(const MutableBufferSequence& buffers,
- socket_base::message_flags flags)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().receive(
- this->get_implementation(), buffers, flags, ec);
- boost::asio::detail::throw_error(ec, "receive");
- return s;
- }
-
- /// Receive some data on a connected socket.
- /**
- * This function is used to receive data on the datagram socket. The function
- * call will block until data has been received successfully or an error
- * occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @returns The number of bytes received.
- *
- * @note The receive operation can only be used with a connected socket. Use
- * the receive_from function to receive data on an unconnected datagram
- * socket.
- */
- template <typename MutableBufferSequence>
- std::size_t receive(const MutableBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return this->get_service().receive(
- this->get_implementation(), buffers, flags, ec);
- }
-
- /// Start an asynchronous receive on a connected socket.
- /**
- * This function is used to asynchronously receive data from the datagram
- * socket. The function call always returns immediately.
- *
- * @param buffers One or more buffers into which the data will be received.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param handler The handler to be called when the receive operation
- * completes. Copies will be made of the handler as required. The function
- * signature of the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes received.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @note The async_receive operation can only be used with a connected socket.
- * Use the async_receive_from function to receive data on an unconnected
- * datagram socket.
- *
- * @par Example
- * To receive into a single data buffer use the @ref buffer function as
- * follows:
- * @code
- * socket.async_receive(boost::asio::buffer(data, size), handler);
- * @endcode
- * See the @ref buffer documentation for information on receiving into
- * multiple buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))
- async_receive(const MutableBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
-
- return this->get_service().async_receive(this->get_implementation(),
- buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
- }
-
- /// Start an asynchronous receive on a connected socket.
- /**
- * This function is used to asynchronously receive data from the datagram
- * socket. The function call always returns immediately.
- *
- * @param buffers One or more buffers into which the data will be received.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @param handler The handler to be called when the receive operation
- * completes. Copies will be made of the handler as required. The function
- * signature of the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes received.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @note The async_receive operation can only be used with a connected socket.
- * Use the async_receive_from function to receive data on an unconnected
- * datagram socket.
- */
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))
- async_receive(const MutableBufferSequence& buffers,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
-
- return this->get_service().async_receive(this->get_implementation(),
- buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
- }
-
- /// Receive a datagram with the endpoint of the sender.
- /**
- * This function is used to receive a datagram. The function call will block
- * until data has been received successfully or an error occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @param sender_endpoint An endpoint object that receives the endpoint of
- * the remote sender of the datagram.
- *
- * @returns The number of bytes received.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @par Example
- * To receive into a single data buffer use the @ref buffer function as
- * follows:
- * @code
- * boost::asio::ip::udp::endpoint sender_endpoint;
- * socket.receive_from(
- * boost::asio::buffer(data, size), sender_endpoint);
- * @endcode
- * See the @ref buffer documentation for information on receiving into
- * multiple buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename MutableBufferSequence>
- std::size_t receive_from(const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().receive_from(
- this->get_implementation(), buffers, sender_endpoint, 0, ec);
- boost::asio::detail::throw_error(ec, "receive_from");
- return s;
- }
-
- /// Receive a datagram with the endpoint of the sender.
- /**
- * This function is used to receive a datagram. The function call will block
- * until data has been received successfully or an error occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @param sender_endpoint An endpoint object that receives the endpoint of
- * the remote sender of the datagram.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @returns The number of bytes received.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- template <typename MutableBufferSequence>
- std::size_t receive_from(const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint, socket_base::message_flags flags)
- {
- boost::system::error_code ec;
- std::size_t s = this->get_service().receive_from(
- this->get_implementation(), buffers, sender_endpoint, flags, ec);
- boost::asio::detail::throw_error(ec, "receive_from");
- return s;
- }
-
- /// Receive a datagram with the endpoint of the sender.
- /**
- * This function is used to receive a datagram. The function call will block
- * until data has been received successfully or an error occurs.
- *
- * @param buffers One or more buffers into which the data will be received.
- *
- * @param sender_endpoint An endpoint object that receives the endpoint of
- * the remote sender of the datagram.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @returns The number of bytes received.
- */
- template <typename MutableBufferSequence>
- std::size_t receive_from(const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint, socket_base::message_flags flags,
- boost::system::error_code& ec)
- {
- return this->get_service().receive_from(this->get_implementation(),
- buffers, sender_endpoint, flags, ec);
- }
-
- /// Start an asynchronous receive.
- /**
- * This function is used to asynchronously receive a datagram. The function
- * call always returns immediately.
- *
- * @param buffers One or more buffers into which the data will be received.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param sender_endpoint An endpoint object that receives the endpoint of
- * the remote sender of the datagram. Ownership of the sender_endpoint object
- * is retained by the caller, which must guarantee that it is valid until the
- * handler is called.
- *
- * @param handler The handler to be called when the receive operation
- * completes. Copies will be made of the handler as required. The function
- * signature of the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes received.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @par Example
- * To receive into a single data buffer use the @ref buffer function as
- * follows:
- * @code socket.async_receive_from(
- * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
- * See the @ref buffer documentation for information on receiving into
- * multiple buffers in one go, and how to use it with arrays, boost::array or
- * std::vector.
- */
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t, boost::asio::ip::address))
- async_receive_from(const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
-
- return this->get_service().async_receive_from(
- this->get_implementation(), buffers, sender_endpoint, 0,
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
- }
-
- /// Start an asynchronous receive.
- /**
- * This function is used to asynchronously receive a datagram. The function
- * call always returns immediately.
- *
- * @param buffers One or more buffers into which the data will be received.
- * Although the buffers object may be copied as necessary, ownership of the
- * underlying memory blocks is retained by the caller, which must guarantee
- * that they remain valid until the handler is called.
- *
- * @param sender_endpoint An endpoint object that receives the endpoint of
- * the remote sender of the datagram. Ownership of the sender_endpoint object
- * is retained by the caller, which must guarantee that it is valid until the
- * handler is called.
- *
- * @param flags Flags specifying how the receive call is to be made.
- *
- * @param handler The handler to be called when the receive operation
- * completes. Copies will be made of the handler as required. The function
- * signature of the handler must be:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes received.
- * ); @endcode
- * Regardless of whether the asynchronous operation completes immediately or
- * not, the handler will not be invoked from within this function. Invocation
- * of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- */
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t, boost::asio::ip::address))
- async_receive_from(const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint, socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
-
- return this->get_service().async_receive_from(
- this->get_implementation(), buffers, sender_endpoint, flags,
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
- }
-};
-
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
+//
+// basic_datagram_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/datagram_socket_service_ext.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides datagram-oriented socket functionality.
+/**
+ * The basic_datagram_socket class template provides asynchronous and blocking
+ * datagram-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol,
+ typename DatagramSocketService = datagram_socket_service_ext<Protocol> >
+class basic_datagram_socket_ext
+ : public basic_socket<Protocol, DatagramSocketService>
+{
+public:
+ /// (Deprecated: Use native_handle_type.) The native representation of a
+ /// socket.
+ typedef typename DatagramSocketService::native_handle_type native_type;
+
+ /// The native representation of a socket.
+ typedef typename DatagramSocketService::native_handle_type native_handle_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_datagram_socket without opening it.
+ /**
+ * This constructor creates a datagram socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ */
+ explicit basic_datagram_socket_ext(boost::asio::io_service& io_service)
+ : basic_socket<Protocol, DatagramSocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_datagram_socket.
+ /**
+ * This constructor creates and opens a datagram socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
+ {
+ }
+
+ /// Construct a basic_datagram_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a datagram socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the datagram
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
+ {
+ }
+
+ /// Construct a basic_datagram_socket on an existing native socket.
+ /**
+ * This constructor creates a datagram socket object to hold an existing
+ * native socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket<Protocol, DatagramSocketService>(
+ io_service, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_datagram_socket from another.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ */
+ basic_datagram_socket_ext(basic_datagram_socket_ext&& other)
+ : basic_socket<Protocol, DatagramSocketService>(
+ BOOST_ASIO_MOVE_CAST(basic_datagram_socket_ext)(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from another.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ */
+ basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other)
+ {
+ basic_socket<Protocol, DatagramSocketService>::operator=(
+ BOOST_ASIO_MOVE_CAST(basic_datagram_socket_ext)(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ */
+ template <typename Protocol1, typename DatagramSocketService1>
+ basic_datagram_socket_ext(
+ basic_datagram_socket_ext<Protocol1, DatagramSocketService1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_socket<Protocol, DatagramSocketService>(
+ BOOST_ASIO_MOVE_CAST2(basic_datagram_socket_ext<
+ Protocol1, DatagramSocketService1>)(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ */
+ template <typename Protocol1, typename DatagramSocketService1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_datagram_socket_ext>::type& operator=(
+ basic_datagram_socket_ext<Protocol1, DatagramSocketService1>&& other)
+ {
+ basic_socket<Protocol, DatagramSocketService>::operator=(
+ BOOST_ASIO_MOVE_CAST2(basic_datagram_socket_ext<
+ Protocol1, DatagramSocketService1>)(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code socket.send(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.send_to(boost::asio::buffer(data, size), destination);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send_to(
+ this->get_implementation(), buffers, destination, 0, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send_to(
+ this->get_implementation(), buffers, destination, flags, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().send_to(this->get_implementation(),
+ buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_send_to(
+ * boost::asio::buffer(data, size), destination, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, 0,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, flags,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.receive(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * boost::asio::ip::udp::endpoint sender_endpoint;
+ * socket.receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().receive_from(this->get_implementation(),
+ buffers, sender_endpoint, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.async_receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0,
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags,
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
diff --git a/implementation/helper/1.55/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.55/boost/asio/basic_socket_acceptor_ext.hpp
new file mode 100644
index 0000000..4af4bac
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/basic_socket_acceptor_ext.hpp
@@ -0,0 +1,1139 @@
+//
+// basic_socket_acceptor_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/socket_acceptor_service_ext.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides the ability to accept new connections.
+/**
+ * The basic_socket_acceptor_ext class template is used for accepting new socket
+ * connections.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+template <typename Protocol,
+ typename SocketAcceptorService = socket_acceptor_service_ext<Protocol> >
+class basic_socket_acceptor_ext
+ : public basic_io_object<SocketAcceptorService>,
+ public socket_base
+{
+public:
+ /// (Deprecated: Use native_handle_type.) The native representation of an
+ /// acceptor.
+ typedef typename SocketAcceptorService::native_handle_type native_type;
+
+ /// The native representation of an acceptor.
+ typedef typename SocketAcceptorService::native_handle_type native_handle_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct an acceptor without opening it.
+ /**
+ * This constructor creates an acceptor without opening it to listen for new
+ * connections. The open() function must be called before the acceptor can
+ * accept new socket connections.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ */
+ explicit basic_socket_acceptor_ext(boost::asio::io_service& io_service)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ }
+
+ /// Construct an open acceptor.
+ /**
+ * This constructor creates an acceptor and automatically opens it.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct an acceptor opened on the given endpoint.
+ /**
+ * This constructor creates an acceptor and automatically opens it to listen
+ * for new connections on the specified endpoint.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param endpoint An endpoint on the local machine on which the acceptor
+ * will listen for new connections.
+ *
+ * @param reuse_addr Whether the constructor should set the socket option
+ * socket_base::reuse_address.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This constructor is equivalent to the following code:
+ * @code
+ * basic_socket_acceptor_ext<Protocol> acceptor(io_service);
+ * acceptor.open(endpoint.protocol());
+ * if (reuse_addr)
+ * acceptor.set_option(socket_base::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen(listen_backlog);
+ * @endcode
+ */
+ basic_socket_acceptor_ext(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint, bool reuse_addr = true)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ if (reuse_addr)
+ {
+ this->get_service().set_option(this->get_implementation(),
+ socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ this->get_service().listen(this->get_implementation(),
+ socket_base::max_connections, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Construct a basic_socket_acceptor_ext on an existing native acceptor.
+ /**
+ * This constructor creates an acceptor object to hold an existing native
+ * acceptor.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_handle_type& native_acceptor)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket_acceptor_ext from another.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor_ext(io_service&) constructor.
+ */
+ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other)
+ : basic_io_object<SocketAcceptorService>(
+ BOOST_ASIO_MOVE_CAST(basic_socket_acceptor_ext)(other))
+ {
+ }
+
+ /// Move-assign a basic_socket_acceptor_ext from another.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor_ext(io_service&) constructor.
+ */
+ basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other)
+ {
+ basic_io_object<SocketAcceptorService>::operator=(
+ BOOST_ASIO_MOVE_CAST(basic_socket_acceptor_ext)(other));
+ return *this;
+ }
+
+ // All socket acceptors have access to each other's implementations.
+ template <typename Protocol1, typename SocketAcceptorService1>
+ friend class basic_socket_acceptor_ext;
+
+ /// Move-construct a basic_socket_acceptor_ext from an acceptor of another
+ /// protocol type.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_service&) constructor.
+ */
+ template <typename Protocol1, typename SocketAcceptorService1>
+ basic_socket_acceptor_ext(
+ basic_socket_acceptor_ext<Protocol1, SocketAcceptorService1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_io_object<SocketAcceptorService>(other.get_io_service())
+ {
+ this->get_service().template converting_move_construct<Protocol1>(
+ this->get_implementation(), other.get_implementation());
+ }
+
+ /// Move-assign a basic_socket_acceptor_ext from an acceptor of another protocol
+ /// type.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_service&) constructor.
+ */
+ template <typename Protocol1, typename SocketAcceptorService1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_socket_acceptor_ext>::type& operator=(
+ basic_socket_acceptor_ext<Protocol1, SocketAcceptorService1>&& other)
+ {
+ basic_socket_acceptor_ext tmp(BOOST_ASIO_MOVE_CAST2(basic_socket_acceptor_ext<
+ Protocol1, SocketAcceptorService1>)(other));
+ basic_io_object<SocketAcceptorService>::operator=(
+ BOOST_ASIO_MOVE_CAST(basic_socket_acceptor_ext)(tmp));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::system::error_code ec;
+ * acceptor.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().open(this->get_implementation(), protocol, ec);
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor, boost::system::error_code& ec)
+ {
+ return this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.bind(endpoint);
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * boost::system::error_code ec;
+ * acceptor.bind(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().bind(this->get_implementation(), endpoint, ec);
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void listen(int backlog = socket_base::max_connections)
+ {
+ boost::system::error_code ec;
+ this->get_service().listen(this->get_implementation(), backlog, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code listen(int backlog, boost::system::error_code& ec)
+ {
+ return this->get_service().listen(this->get_implementation(), backlog, ec);
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->get_service().close(this->get_implementation(), ec);
+ }
+
+ /// (Deprecated: Use native_handle().) Get the native acceptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * acceptor. This is intended to allow access to native acceptor functionality
+ * that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Get the native acceptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * acceptor. This is intended to allow access to native acceptor functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->get_service().cancel(this->get_implementation(), ec);
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * boost::system::error_code ec;
+ * acceptor.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().set_option(
+ this->get_implementation(), option, ec);
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * acceptor.get_option(option);
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * boost::system::error_code ec;
+ * acceptor.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(GettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().get_option(
+ this->get_implementation(), option, ec);
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * socket.io_control(command);
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().io_control(
+ this->get_implementation(), command, ec);
+ }
+
+ /// Gets the non-blocking mode of the acceptor.
+ /**
+ * @returns @c true if the acceptor's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return this->get_service().non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ boost::system::error_code non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ return this->get_service().non_blocking(
+ this->get_implementation(), mode, ec);
+ }
+
+ /// Gets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native acceptor. This mode has no effect on the behaviour of the acceptor
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying acceptor is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the acceptor object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native acceptor.
+ */
+ bool native_non_blocking() const
+ {
+ return this->get_service().native_non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ boost::system::error_code native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ return this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().local_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ * Returns a default-constructed endpoint object if an error occurred and the
+ * error handler did not throw an exception.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().local_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * acceptor.accept(socket);
+ * @endcode
+ */
+ template <typename Protocol1, typename SocketService>
+ void accept(basic_socket<Protocol1, SocketService>& peer,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+ {
+ boost::system::error_code ec;
+ this->get_service().accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::soocket socket(io_service);
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename Protocol1, typename SocketService>
+ boost::system::error_code accept(
+ basic_socket<Protocol1, SocketService>& peer,
+ boost::system::error_code& ec,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket. The function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * acceptor.async_accept(socket, accept_handler);
+ * @endcode
+ */
+ template <typename Protocol1, typename SocketService, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket<Protocol1, SocketService>& peer,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a AcceptHandler.
+ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+
+ return this->get_service().async_accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.accept(socket, endpoint);
+ * @endcode
+ */
+ template <typename SocketService>
+ void accept(basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ this->get_service().accept(this->get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SocketService>
+ boost::system::error_code accept(
+ basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(
+ this->get_implementation(), peer, &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket, and additionally obtain the endpoint of the remote peer. The
+ * function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename SocketService, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a AcceptHandler.
+ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+
+ return this->get_service().async_accept(this->get_implementation(), peer,
+ &peer_endpoint, BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.55/boost/asio/basic_stream_socket_ext.hpp
new file mode 100644
index 0000000..ab55eda
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/basic_stream_socket_ext.hpp
@@ -0,0 +1,855 @@
+//
+// basic_stream_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/stream_socket_service_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides stream-oriented socket functionality.
+/**
+ * The basic_stream_socket_ext class template provides asynchronous and blocking
+ * stream-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Protocol,
+ typename StreamSocketService = stream_socket_service_ext<Protocol> >
+class basic_stream_socket_ext
+ : public basic_socket<Protocol, StreamSocketService>
+{
+public:
+ /// (Deprecated: Use native_handle_type.) The native representation of a
+ /// socket.
+ typedef typename StreamSocketService::native_handle_type native_type;
+
+ /// The native representation of a socket.
+ typedef typename StreamSocketService::native_handle_type native_handle_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_stream_socket_ext without opening it.
+ /**
+ * This constructor creates a stream socket without opening it. The socket
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_stream_socket_ext(boost::asio::io_service& io_service)
+ : basic_socket<Protocol, StreamSocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_stream_socket_ext.
+ /**
+ * This constructor creates and opens a stream socket. The socket needs to be
+ * connected or accepted before data can be sent or received on it.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_socket<Protocol, StreamSocketService>(io_service, protocol)
+ {
+ }
+
+ /// Construct a basic_stream_socket_ext, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a stream socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the stream
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_socket<Protocol, StreamSocketService>(io_service, endpoint)
+ {
+ }
+
+ /// Construct a basic_stream_socket_ext on an existing native socket.
+ /**
+ * This constructor creates a stream socket object to hold an existing native
+ * socket.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket<Protocol, StreamSocketService>(
+ io_service, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_stream_socket_ext from another.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_service&) constructor.
+ */
+ basic_stream_socket_ext(basic_stream_socket_ext&& other)
+ : basic_socket<Protocol, StreamSocketService>(
+ BOOST_ASIO_MOVE_CAST(basic_stream_socket_ext)(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket_ext from another.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_service&) constructor.
+ */
+ basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other)
+ {
+ basic_socket<Protocol, StreamSocketService>::operator=(
+ BOOST_ASIO_MOVE_CAST(basic_stream_socket_ext)(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_stream_socket_ext from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_service&) constructor.
+ */
+ template <typename Protocol1, typename StreamSocketService1>
+ basic_stream_socket_ext(
+ basic_stream_socket_ext<Protocol1, StreamSocketService1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_socket<Protocol, StreamSocketService>(
+ BOOST_ASIO_MOVE_CAST2(basic_stream_socket_ext<
+ Protocol1, StreamSocketService1>)(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket_ext from a socket of another protocol type.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_service&) constructor.
+ */
+ template <typename Protocol1, typename StreamSocketService1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_stream_socket_ext>::type& operator=(
+ basic_stream_socket_ext<Protocol1, StreamSocketService1>&& other)
+ {
+ basic_socket<Protocol, StreamSocketService>::operator=(
+ BOOST_ASIO_MOVE_CAST2(basic_stream_socket_ext<
+ Protocol1, StreamSocketService1>)(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent. Returns 0 if an error occurred.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send(
+ this->get_implementation(), buffers, 0,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send(
+ this->get_implementation(), buffers, flags,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received. Returns 0 if an error occurred.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().send(this->get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
diff --git a/implementation/helper/boost/asio/datagram_socket_service_ext.hpp b/implementation/helper/1.55/boost/asio/datagram_socket_service_ext.hpp
index 3934e50..7648581 100644
--- a/implementation/helper/boost/asio/datagram_socket_service_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/datagram_socket_service_ext.hpp
@@ -1,437 +1,437 @@
-//
-// datagram_socket_service_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_EXT_ASIO_DATAGRAM_SOCKET_SERVICE_EXT_HPP
-#define BOOST_EXT_ASIO_DATAGRAM_SOCKET_SERVICE_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <iostream>
-
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <boost/asio/async_result.hpp>
-#include <boost/asio/detail/type_traits.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-
-#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-# include <boost/asio/detail/null_socket_service.hpp>
-#elif defined(BOOST_ASIO_HAS_IOCP)
-# include "detail/win_iocp_socket_service_ext.hpp"
-#else
-# include "detail/reactive_socket_service_ext.hpp"
-#endif
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-
-/// Default service implementation for a datagram socket.
-template <typename Protocol>
-class datagram_socket_service_ext
-#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
-#else
- : public boost::asio::detail::service_base<datagram_socket_service_ext<Protocol> >
-#endif
-{
-public:
-#if defined(GENERATING_DOCUMENTATION)
- /// The unique service identifier.
- static boost::asio::io_service::id id;
-#endif
-
- /// The protocol type.
- typedef Protocol protocol_type;
-
- /// The endpoint type.
- typedef typename Protocol::endpoint endpoint_type;
-
-private:
- // The type of the platform-specific implementation.
-#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
- typedef detail::null_socket_service<Protocol> service_impl_type;
-#elif defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::win_iocp_socket_service_ext<Protocol> service_impl_type;
-#else
- typedef detail::reactive_socket_service_ext<Protocol> service_impl_type;
-#endif
-
-public:
- /// The type of a datagram socket.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined implementation_type;
-#else
- typedef typename service_impl_type::implementation_type implementation_type;
-#endif
-
- /// (Deprecated: Use native_handle_type.) The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
- /// The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_handle_type;
-#else
- typedef typename service_impl_type::native_handle_type native_handle_type;
-#endif
-
- /// Construct a new datagram socket service for the specified io_service.
- explicit datagram_socket_service_ext(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<
- datagram_socket_service_ext<Protocol> >(io_service),
- service_impl_(io_service)
- {
- }
-
- /// Construct a new datagram socket implementation.
- void construct(implementation_type& impl)
- {
- service_impl_.construct(impl);
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
- /// Move-construct a new datagram socket implementation.
- void move_construct(implementation_type& impl,
- implementation_type& other_impl)
- {
- service_impl_.move_construct(impl, other_impl);
- }
-
- /// Move-assign from another datagram socket implementation.
- void move_assign(implementation_type& impl,
- datagram_socket_service_ext& other_service,
- implementation_type& other_impl)
- {
- service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
- }
-
- /// Move-construct a new datagram socket implementation from another protocol
- /// type.
- template <typename Protocol1>
- void converting_move_construct(implementation_type& impl,
- typename datagram_socket_service_ext<
- Protocol1>::implementation_type& other_impl,
- typename enable_if<is_convertible<
- Protocol1, Protocol>::value>::type* = 0)
- {
- service_impl_.template converting_move_construct<Protocol1>(
- impl, other_impl);
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
-
- /// Destroy a datagram socket implementation.
- void destroy(implementation_type& impl)
- {
- service_impl_.destroy(impl);
- }
-
- // Open a new datagram socket implementation.
- boost::system::error_code open(implementation_type& impl,
- const protocol_type& protocol, boost::system::error_code& ec)
- {
- if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM))
- service_impl_.open(impl, protocol, ec);
- else
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- /// Assign an existing native socket to a datagram socket.
- boost::system::error_code assign(implementation_type& impl,
- const protocol_type& protocol, const native_handle_type& native_socket,
- boost::system::error_code& ec)
- {
- return service_impl_.assign(impl, protocol, native_socket, ec);
- }
-
- /// Determine whether the socket is open.
- bool is_open(const implementation_type& impl) const
- {
- return service_impl_.is_open(impl);
- }
-
- /// Close a datagram socket implementation.
- boost::system::error_code close(implementation_type& impl,
- boost::system::error_code& ec)
- {
- return service_impl_.close(impl, ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native socket implementation.
- native_type native(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
- }
-
- /// Get the native socket implementation.
- native_handle_type native_handle(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
- }
-
- /// Cancel all asynchronous operations associated with the socket.
- boost::system::error_code cancel(implementation_type& impl,
- boost::system::error_code& ec)
- {
- return service_impl_.cancel(impl, ec);
- }
-
- /// Determine whether the socket is at the out-of-band data mark.
- bool at_mark(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return service_impl_.at_mark(impl, ec);
- }
-
- /// Determine the number of bytes available for reading.
- std::size_t available(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return service_impl_.available(impl, ec);
- }
-
- // Bind the datagram socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
- const endpoint_type& endpoint, boost::system::error_code& ec)
- {
- return service_impl_.bind(impl, endpoint, ec);
- }
-
- /// Connect the datagram socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
- const endpoint_type& peer_endpoint, boost::system::error_code& ec)
- {
- return service_impl_.connect(impl, peer_endpoint, ec);
- }
-
- /// Start an asynchronous connect.
- template <typename ConnectHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
- void (boost::system::error_code))
- async_connect(implementation_type& impl,
- const endpoint_type& peer_endpoint,
- BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
- {
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
-
- service_impl_.async_connect(impl, peer_endpoint, init.handler);
-
- return init.result.get();
- }
-
- /// Set a socket option.
- template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
- const SettableSocketOption& option, boost::system::error_code& ec)
- {
- return service_impl_.set_option(impl, option, ec);
- }
-
- /// Get a socket option.
- template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
- GettableSocketOption& option, boost::system::error_code& ec) const
- {
- return service_impl_.get_option(impl, option, ec);
- }
-
- /// Perform an IO control command on the socket.
- template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
- IoControlCommand& command, boost::system::error_code& ec)
- {
- return service_impl_.io_control(impl, command, ec);
- }
-
- /// Gets the non-blocking mode of the socket.
- bool non_blocking(const implementation_type& impl) const
- {
- return service_impl_.non_blocking(impl);
- }
-
- /// Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(implementation_type& impl,
- bool mode, boost::system::error_code& ec)
- {
- return service_impl_.non_blocking(impl, mode, ec);
- }
-
- /// Gets the non-blocking mode of the native socket implementation.
- bool native_non_blocking(const implementation_type& impl) const
- {
- return service_impl_.native_non_blocking(impl);
- }
-
- /// Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
- bool mode, boost::system::error_code& ec)
- {
- return service_impl_.native_non_blocking(impl, mode, ec);
- }
-
- /// Get the local endpoint.
- endpoint_type local_endpoint(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return service_impl_.local_endpoint(impl, ec);
- }
-
- /// Get the remote endpoint.
- endpoint_type remote_endpoint(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return service_impl_.remote_endpoint(impl, ec);
- }
-
- /// Disable sends or receives on the socket.
- boost::system::error_code shutdown(implementation_type& impl,
- socket_base::shutdown_type what, boost::system::error_code& ec)
- {
- return service_impl_.shutdown(impl, what, ec);
- }
-
- /// Send the given data to the peer.
- template <typename ConstBufferSequence>
- std::size_t send(implementation_type& impl,
- const ConstBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return service_impl_.send(impl, buffers, flags, ec);
- }
-
- /// Start an asynchronous send.
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
-
- service_impl_.async_send(impl, buffers, flags, init.handler);
-
- return init.result.get();
- }
-
- /// Send a datagram to the specified endpoint.
- template <typename ConstBufferSequence>
- std::size_t send_to(implementation_type& impl,
- const ConstBufferSequence& buffers, const endpoint_type& destination,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return service_impl_.send_to(impl, buffers, destination, flags, ec);
- }
-
- /// Start an asynchronous send.
- template <typename ConstBufferSequence, typename WriteHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t))
- async_send_to(implementation_type& impl,
- const ConstBufferSequence& buffers, const endpoint_type& destination,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
- {
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
-
- service_impl_.async_send_to(impl, buffers,
- destination, flags, init.handler);
-
- return init.result.get();
- }
-
- /// Receive some data from the peer.
- template <typename MutableBufferSequence>
- std::size_t receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return service_impl_.receive(impl, buffers, flags, ec);
- }
-
- /// Start an asynchronous receive.
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))
- async_receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
-
- service_impl_.async_receive(impl, buffers, flags, init.handler);
-
- return init.result.get();
- }
-
- /// Receive a datagram with the endpoint of the sender.
- template <typename MutableBufferSequence>
- std::size_t receive_from(implementation_type& impl,
- const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
- ec);
- }
-
- /// Start an asynchronous receive that will get the endpoint of the sender.
- template <typename MutableBufferSequence, typename ReadHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t, boost::asio::ip::address))
- async_receive_from(implementation_type& impl,
- const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
- socket_base::message_flags flags,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
- {
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
-
- service_impl_.async_receive_from(impl, buffers,
- sender_endpoint, flags, init.handler);
-
- return init.result.get();
- }
-
-private:
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- service_impl_.shutdown_service();
- }
-
- // The platform-specific implementation.
- service_impl_type service_impl_;
-};
-
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
+//
+// datagram_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_EXT_ASIO_DATAGRAM_SOCKET_SERVICE_EXT_HPP
+#define BOOST_EXT_ASIO_DATAGRAM_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include "detail/win_iocp_socket_service_ext.hpp"
+#else
+# include "detail/reactive_socket_service_ext.hpp"
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a datagram socket.
+template <typename Protocol>
+class datagram_socket_service_ext
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<datagram_socket_service_ext<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef detail::null_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service_ext<Protocol> service_impl_type;
+#else
+ typedef detail::reactive_socket_service_ext<Protocol> service_impl_type;
+#endif
+
+public:
+ /// The type of a datagram socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// (Deprecated: Use native_handle_type.) The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_handle_type;
+#endif
+
+ /// Construct a new datagram socket service for the specified io_service.
+ explicit datagram_socket_service_ext(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ datagram_socket_service_ext<Protocol> >(io_service),
+ service_impl_(io_service)
+ {
+ }
+
+ /// Construct a new datagram socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new datagram socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another datagram socket implementation.
+ void move_assign(implementation_type& impl,
+ datagram_socket_service_ext& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+
+ /// Move-construct a new datagram socket implementation from another protocol
+ /// type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ typename datagram_socket_service_ext<
+ Protocol1>::implementation_type& other_impl,
+ typename enable_if<is_convertible<
+ Protocol1, Protocol>::value>::type* = 0)
+ {
+ service_impl_.template converting_move_construct<Protocol1>(
+ impl, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroy a datagram socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ // Open a new datagram socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM))
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ /// Assign an existing native socket to a datagram socket.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a datagram socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// (Deprecated: Use native_handle().) Get the native socket implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Get the native socket implementation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ // Bind the datagram socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Connect the datagram socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.connect(impl, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ detail::async_result_init<
+ ConnectHandler, void (boost::system::error_code)> init(
+ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+
+ service_impl_.async_connect(impl, peer_endpoint, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ bool non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.non_blocking(impl, mode, ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.native_non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.native_non_blocking(impl, mode, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, what, ec);
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ detail::async_result_init<
+ WriteHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+
+ service_impl_.async_send(impl, buffers, flags, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Send a datagram to the specified endpoint.
+ template <typename ConstBufferSequence>
+ std::size_t send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send_to(impl, buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ detail::async_result_init<
+ WriteHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+
+ service_impl_.async_send_to(impl, buffers,
+ destination, flags, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ detail::async_result_init<
+ ReadHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+
+ service_impl_.async_receive(impl, buffers, flags, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
+ ec);
+ }
+
+ /// Start an asynchronous receive that will get the endpoint of the sender.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ detail::async_result_init<
+ ReadHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+
+ service_impl_.async_receive_from(impl, buffers,
+ sender_endpoint, flags, init.handler);
+
+ return init.result.get();
+ }
+
+private:
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ service_impl_.shutdown_service();
+ }
+
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
diff --git a/implementation/helper/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext.hpp
index 1e16823..34b0375 100644
--- a/implementation/helper/boost/asio/detail/handler_type_requirements_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext.hpp
@@ -1,520 +1,520 @@
-//
-// detail/handler_type_requirements_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
-#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-// Older versions of gcc have difficulty compiling the sizeof expressions where
-// we test the handler type requirements. We'll disable checking of handler type
-// requirements for those compilers, but otherwise enable it by default.
-#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
-# if !defined(__GNUC__) || (__GNUC__ >= 4)
-# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
-# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
-#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
-
-// With C++0x we can use a combination of enhanced SFINAE and static_assert to
-// generate better template error messages. As this technique is not yet widely
-// portable, we'll only enable it for tested compilers.
-#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
-# if defined(__GNUC__)
-# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
-# if defined(__GXX_EXPERIMENTAL_CXX0X__)
-# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
-# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
-# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
-# endif // defined(__GNUC__)
-# if defined(BOOST_ASIO_MSVC)
-# if (_MSC_VER >= 1600)
-# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
-# endif // (_MSC_VER >= 1600)
-# endif // defined(BOOST_ASIO_MSVC)
-# if defined(__clang__)
-# if __has_feature(__cxx_static_assert__)
-# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
-# endif // __has_feature(cxx_static_assert)
-# endif // defined(__clang__)
-#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
-
-#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-# include <boost/asio/handler_type.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-
-// Newer gcc, clang need special treatment to suppress unused typedef warnings.
-#if defined(__clang__)
-# if defined(__apple_build_version__)
-# if (__clang_major__ >= 7)
-# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif
-# endif // (__clang_major__ >= 7)
-# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
- || (__clang_major__ > 3)
-# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif
-# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
- // || (__clang_major__ > 3)
-#elif defined(__GNUC__)
-# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
-# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
-# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
-#endif // defined(__GNUC__)
-#if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-# define BOOST_ASIO_UNUSED_TYPEDEF
-#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-
-# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
-
-template <typename Handler>
-auto zero_arg_handler_test(Handler h, void*)
- -> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
- ((h)()),
- char(0));
-
-template <typename Handler>
-char (&zero_arg_handler_test(Handler, ...))[2];
-
-template <typename Handler, typename Arg1>
-auto one_arg_handler_test(Handler h, Arg1* a1)
- -> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
- ((h)(*a1)),
- char(0));
-
-template <typename Handler>
-char (&one_arg_handler_test(Handler h, ...))[2];
-
-template <typename Handler, typename Arg1, typename Arg2>
-auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
- -> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
- ((h)(*a1, *a2)),
- char(0));
-
-template <typename Handler>
-char (&two_arg_handler_test(Handler, ...))[2];
-
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
-auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3)
- -> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
- ((h)(*a1, *a2, *a3)),
- char(0));
-
-template <typename Handler>
-char (&three_arg_handler_test(Handler, ...))[2];
-
-# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
- static_assert(expr, msg);
-
-# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
-
-# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
-
-# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
-
-template <typename T> T& lvref();
-template <typename T> T& lvref(T);
-template <typename T> const T& clvref();
-template <typename T> const T& clvref(T);
-template <typename T> char argbyv(T);
-
-#if 0
-template <int>
-struct handler_type_requirements
-{
-};
-#endif
-
-#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void()) asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::zero_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), 0)) == 1, \
- "CompletionHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()(), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, std::size_t, \
- boost::asio::ip::address)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::three_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const std::size_t*>(0), \
- static_cast<const boost::asio::ip::address*>(0))) == 1, \
- "ReadHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const std::size_t>(), \
- boost::asio::detail::lvref<const boost::asio::ip::address>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-
-#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, std::size_t)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const std::size_t*>(0))) == 1, \
- "WriteHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const std::size_t>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0))) == 1, \
- "AcceptHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0))) == 1, \
- "ConnectHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
- handler_type, handler, iter_type) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, iter_type)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const iter_type*>(0))) == 1, \
- "ComposedConnectHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const iter_type>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
- handler_type, handler, iter_type) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, iter_type)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const iter_type*>(0))) == 1, \
- "ResolveHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const iter_type>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0))) == 1, \
- "WaitHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, int)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const int*>(0))) == 1, \
- "SignalHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const int>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0))) == 1, \
- "HandshakeHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, std::size_t)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0), \
- static_cast<const std::size_t*>(0))) == 1, \
- "BufferedHandshakeHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const std::size_t>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
- handler_type, handler) \
- \
- typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code)) \
- asio_true_handler_type; \
- \
- BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>(), \
- static_cast<const boost::system::error_code*>(0))) == 1, \
- "ShutdownHandler type requirements not met") \
- \
- typedef boost::asio::detail::handler_type_requirements< \
- sizeof( \
- boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
- asio_true_handler_type>())) + \
- sizeof( \
- boost::asio::detail::lvref< \
- asio_true_handler_type>()( \
- boost::asio::detail::lvref<const boost::system::error_code>()), \
- char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
-#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-
-#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_READ_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
- handler_type, handler, iter_type) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
- handler_type, handler, iter_type) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
- handler_type, handler) \
- typedef int BOOST_ASIO_UNUSED_TYPEDEF
-
-#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+//
+// detail/handler_type_requirements_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/handler_type.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// Newer gcc, clang need special treatment to suppress unused typedef warnings.
+#if defined(__clang__)
+# if defined(__apple_build_version__)
+# if (__clang_major__ >= 7)
+# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif
+# endif // (__clang_major__ >= 7)
+# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
+ || (__clang_major__ > 3)
+# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif
+# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
+ // || (__clang_major__ > 3)
+#elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+#if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF
+#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1, *a2, *a3)),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ boost::asio::ip::address)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::three_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const boost::asio::ip::address*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const boost::asio::ip::address>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "ComposedConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "BufferedHandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext_local.hpp
new file mode 100644
index 0000000..717eb6e
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/handler_type_requirements_ext_local.hpp
@@ -0,0 +1,536 @@
+//
+// detail/handler_type_requirements_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/handler_type.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// Newer gcc, clang need special treatment to suppress unused typedef warnings.
+#if defined(__clang__)
+# if defined(__apple_build_version__)
+# if (__clang_major__ >= 7)
+# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif
+# endif // (__clang_major__ >= 7)
+# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
+ || (__clang_major__ > 3)
+# if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif
+# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
+ // || (__clang_major__ > 3)
+#elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
+#endif // defined(__GNUC__)
+#if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+# define BOOST_ASIO_UNUSED_TYPEDEF
+#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1, *a2, *a3)),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)(*a1, *a2, *a3, *a4)),
+ char(0));
+
+template <typename Handler>
+char (&four_arg_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ std::uint32_t, \
+ std::uint32_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::four_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const std::uint32_t*>(0), \
+ static_cast<const std::uint32_t*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "ComposedConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "BufferedHandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
index 57f983c..3b4a4a8 100644
--- a/implementation/helper/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
+++ b/implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
@@ -1,270 +1,270 @@
-//
-// detail/reactive_socket_service_base_ext.ipp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
-#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-#if !defined(BOOST_ASIO_HAS_IOCP) \
- && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
-
-#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-reactive_socket_service_base_ext::reactive_socket_service_base_ext(
- boost::asio::io_service& io_service)
- : reactor_(use_service<reactor>(io_service))
-{
- reactor_.init_task();
-}
-
-void reactive_socket_service_base_ext::shutdown_service()
-{
-}
-
-void reactive_socket_service_base_ext::construct(
- reactive_socket_service_base_ext::base_implementation_type& impl)
-{
- impl.socket_ = invalid_socket;
- impl.state_ = 0;
-}
-
-void reactive_socket_service_base_ext::base_move_construct(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- reactive_socket_service_base_ext::base_implementation_type& other_impl)
-{
- impl.socket_ = other_impl.socket_;
- other_impl.socket_ = invalid_socket;
-
- impl.state_ = other_impl.state_;
- other_impl.state_ = 0;
-
- reactor_.move_descriptor(impl.socket_,
- impl.reactor_data_, other_impl.reactor_data_);
-}
-
-void reactive_socket_service_base_ext::base_move_assign(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- reactive_socket_service_base_ext& other_service,
- reactive_socket_service_base_ext::base_implementation_type& other_impl)
-{
- destroy(impl);
-
- impl.socket_ = other_impl.socket_;
- other_impl.socket_ = invalid_socket;
-
- impl.state_ = other_impl.state_;
- other_impl.state_ = 0;
-
- other_service.reactor_.move_descriptor(impl.socket_,
- impl.reactor_data_, other_impl.reactor_data_);
-}
-
-void reactive_socket_service_base_ext::destroy(
- reactive_socket_service_base_ext::base_implementation_type& impl)
-{
- if (impl.socket_ != invalid_socket)
- {
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
-
- reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
- (impl.state_ & socket_ops::possible_dup) == 0);
-
- boost::system::error_code ignored_ec;
- socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
- }
-}
-
-boost::system::error_code reactive_socket_service_base_ext::close(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- boost::system::error_code& ec)
-{
- if (is_open(impl))
- {
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
-
- reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
- (impl.state_ & socket_ops::possible_dup) == 0);
- }
-
- socket_ops::close(impl.socket_, impl.state_, false, ec);
-
- // The descriptor is closed by the OS even if close() returns an error.
- //
- // (Actually, POSIX says the state of the descriptor is unspecified. On
- // Linux the descriptor is apparently closed anyway; e.g. see
- // http://lkml.org/lkml/2005/9/10/129
- // We'll just have to assume that other OSes follow the same behaviour. The
- // known exception is when Windows's closesocket() function fails with
- // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
- construct(impl);
-
- return ec;
-}
-
-boost::system::error_code reactive_socket_service_base_ext::cancel(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- boost::system::error_code& ec)
-{
- if (!is_open(impl))
- {
- ec = boost::asio::error::bad_descriptor;
- return ec;
- }
-
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
-
- reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
- ec = boost::system::error_code();
- return ec;
-}
-
-boost::system::error_code reactive_socket_service_base_ext::do_open(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- int af, int type, int protocol, boost::system::error_code& ec)
-{
- if (is_open(impl))
- {
- ec = boost::asio::error::already_open;
- return ec;
- }
-
- socket_holder sock(socket_ops::socket(af, type, protocol, ec));
- if (sock.get() == invalid_socket)
- return ec;
-
- if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
- {
- ec = boost::system::error_code(err,
- boost::asio::error::get_system_category());
- return ec;
- }
-
- impl.socket_ = sock.release();
- switch (type)
- {
- case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
- case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
- default: impl.state_ = 0; break;
- }
- ec = boost::system::error_code();
- return ec;
-}
-
-boost::system::error_code reactive_socket_service_base_ext::do_assign(
- reactive_socket_service_base_ext::base_implementation_type& impl, int type,
- const reactive_socket_service_base_ext::native_handle_type& native_socket,
- boost::system::error_code& ec)
-{
- if (is_open(impl))
- {
- ec = boost::asio::error::already_open;
- return ec;
- }
-
- if (int err = reactor_.register_descriptor(
- native_socket, impl.reactor_data_))
- {
- ec = boost::system::error_code(err,
- boost::asio::error::get_system_category());
- return ec;
- }
-
- impl.socket_ = native_socket;
- switch (type)
- {
- case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
- case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
- default: impl.state_ = 0; break;
- }
- impl.state_ |= socket_ops::possible_dup;
- ec = boost::system::error_code();
- return ec;
-}
-
-void reactive_socket_service_base_ext::start_op(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- int op_type, reactor_op* op, bool is_continuation,
- bool is_non_blocking, bool noop)
-{
- if (!noop)
- {
- if ((impl.state_ & socket_ops::non_blocking)
- || socket_ops::set_internal_non_blocking(
- impl.socket_, impl.state_, true, op->ec_))
- {
- reactor_.start_op(op_type, impl.socket_,
- impl.reactor_data_, op, is_continuation, is_non_blocking);
- return;
- }
- }
-
- reactor_.post_immediate_completion(op, is_continuation);
-}
-
-void reactive_socket_service_base_ext::start_accept_op(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- reactor_op* op, bool is_continuation, bool peer_is_open)
-{
- if (!peer_is_open)
- start_op(impl, reactor::read_op, op, true, is_continuation, false);
- else
- {
- op->ec_ = boost::asio::error::already_open;
- reactor_.post_immediate_completion(op, is_continuation);
- }
-}
-
-void reactive_socket_service_base_ext::start_connect_op(
- reactive_socket_service_base_ext::base_implementation_type& impl,
- reactor_op* op, bool is_continuation,
- const socket_addr_type* addr, size_t addrlen)
-{
- if ((impl.state_ & socket_ops::non_blocking)
- || socket_ops::set_internal_non_blocking(
- impl.socket_, impl.state_, true, op->ec_))
- {
- if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
- {
- if (op->ec_ == boost::asio::error::in_progress
- || op->ec_ == boost::asio::error::would_block)
- {
- op->ec_ = boost::system::error_code();
- reactor_.start_op(reactor::connect_op, impl.socket_,
- impl.reactor_data_, op, is_continuation, false);
- return;
- }
- }
- }
-
- reactor_.post_immediate_completion(op, is_continuation);
-}
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // !defined(BOOST_ASIO_HAS_IOCP)
- // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
-
-#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+//
+// detail/reactive_socket_service_base_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext::reactive_socket_service_base_ext(
+ boost::asio::io_service& io_service)
+ : reactor_(use_service<reactor>(io_service))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext::shutdown_service()
+{
+}
+
+void reactive_socket_service_base_ext::construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext::base_move_construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::base_move_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::destroy(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext::close(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+ }
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::cancel(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_open(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext::start_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext::start_accept_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, true, is_continuation, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext::start_connect_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
diff --git a/implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
new file mode 100644
index 0000000..26521cf
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
@@ -0,0 +1,270 @@
+//
+// detail/reactive_socket_service_base_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local(
+ boost::asio::io_service& io_service)
+ : reactor_(use_service<reactor>(io_service))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext_local::shutdown_service()
+{
+}
+
+void reactive_socket_service_base_ext_local::construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext_local::base_move_construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::base_move_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::destroy(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::close(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+ }
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::cancel(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_open(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext_local::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext_local::start_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext_local::start_accept_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, true, is_continuation, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext_local::start_connect_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
diff --git a/implementation/helper/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext.ipp
index 6772b77..fe90e83 100644
--- a/implementation/helper/boost/asio/detail/impl/socket_ops_ext.ipp
+++ b/implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext.ipp
@@ -1,210 +1,210 @@
-//
-// detail/impl/socket_ops_ext.ipp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
-#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
-
-#include <boost/asio/detail/impl/socket_ops.ipp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-namespace socket_ops {
-
-signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
- int flags, socket_addr_type* addr, std::size_t* addrlen,
- boost::system::error_code& ec, boost::asio::ip::address& da)
-{
- clear_last_error();
-#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
- GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
- LPFN_WSARECVMSG WSARecvMsg;
- DWORD NumberOfBytes;
-
- error_wrapper(WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
- &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
- &WSARecvMsg, sizeof WSARecvMsg,
- &NumberOfBytes, NULL, NULL), ec);
- if (ec.value() == SOCKET_ERROR) {
- WSARecvMsg = NULL;
- return 0;
- }
-
- WSABUF wsaBuf;
- WSAMSG msg;
- char controlBuffer[1024];
- msg.name = addr;
- msg.namelen = *addrlen;
- wsaBuf.buf = bufs->buf;
- wsaBuf.len = bufs->len;
- msg.lpBuffers = &wsaBuf;
- msg.dwBufferCount = count;
- msg.Control.len = sizeof controlBuffer;
- msg.Control.buf = controlBuffer;
- msg.dwFlags = flags;
-
- DWORD dwNumberOfBytesRecvd;
- signed_size_type result = error_wrapper(WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL), ec);
-
- if (result >= 0) {
- ec = boost::system::error_code();
-
- // Find destination address
- for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg);
- cmsg != NULL;
- cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
- {
- if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
- continue;
-
- struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg);
- if (pi)
- {
- da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
- }
- }
- } else {
- dwNumberOfBytesRecvd = -1;
- }
- return dwNumberOfBytesRecvd;
-#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
- char cmbuf[0x100];
- msghdr msg = msghdr();
- init_msghdr_msg_name(msg.msg_name, addr);
- msg.msg_namelen = static_cast<int>(*addrlen);
- msg.msg_iov = bufs;
- msg.msg_iovlen = static_cast<int>(count);
- msg.msg_control = cmbuf;
- msg.msg_controllen = sizeof(cmbuf);
- signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
- *addrlen = msg.msg_namelen;
- if (result >= 0) {
- ec = boost::system::error_code();
-
- // Find destination address
- for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
- cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg))
- {
- if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
- continue;
-
- struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
- if (pi)
- {
- da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
- }
- }
- }
- return result;
-#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
-}
-
-size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
- size_t count, int flags, socket_addr_type* addr,
- std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da)
-{
- if (s == invalid_socket)
- {
- ec = boost::asio::error::bad_descriptor;
- return 0;
- }
-
- // Read some data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- signed_size_type bytes = socket_ops::recvfrom(
- s, bufs, count, flags, addr, addrlen, ec, da);
-
- // Check if operation succeeded.
- if (bytes >= 0)
- return bytes;
-
- // Operation failed.
- if ((state & user_set_non_blocking)
- || (ec != boost::asio::error::would_block
- && ec != boost::asio::error::try_again))
- return 0;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_read(s, 0, ec) < 0)
- return 0;
- }
-}
-
-#if defined(BOOST_ASIO_HAS_IOCP)
-
-void complete_iocp_recvfrom(
- const weak_cancel_token_type& cancel_token,
- boost::system::error_code& ec, boost::asio::ip::address& da)
-{
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- if (cancel_token.expired())
- ec = boost::asio::error::operation_aborted;
- else
- ec = boost::asio::error::connection_reset;
- }
- else if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = boost::asio::error::connection_refused;
- }
-}
-
-#else // defined(BOOST_ASIO_HAS_IOCP)
-
-bool non_blocking_recvfrom(socket_type s,
- buf* bufs, size_t count, int flags,
- socket_addr_type* addr, std::size_t* addrlen,
- boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da)
-{
- for (;;)
- {
- // Read some data.
- signed_size_type bytes = socket_ops::recvfrom(
- s, bufs, count, flags, addr, addrlen, ec, da);
-
- // Retry operation if interrupted by signal.
- if (ec == boost::asio::error::interrupted)
- continue;
-
- // Check if we need to run the operation again.
- if (ec == boost::asio::error::would_block
- || ec == boost::asio::error::try_again)
- return false;
-
- // Operation is complete.
- if (bytes >= 0)
- {
- ec = boost::system::error_code();
- bytes_transferred = bytes;
- }
- else
- bytes_transferred = 0;
-
- return true;
- }
-}
-
-#endif // defined(BOOST_ASIO_HAS_IOCP)
-
-} // namespace socket_ops
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+//
+// detail/impl/socket_ops_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
+ LPFN_WSARECVMSG WSARecvMsg;
+ DWORD NumberOfBytes;
+
+ error_wrapper(WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
+ &WSARecvMsg, sizeof WSARecvMsg,
+ &NumberOfBytes, NULL, NULL), ec);
+ if (ec.value() == SOCKET_ERROR) {
+ WSARecvMsg = NULL;
+ return 0;
+ }
+
+ WSABUF wsaBuf;
+ WSAMSG msg;
+ char controlBuffer[1024];
+ msg.name = addr;
+ msg.namelen = *addrlen;
+ wsaBuf.buf = bufs->buf;
+ wsaBuf.len = bufs->len;
+ msg.lpBuffers = &wsaBuf;
+ msg.dwBufferCount = count;
+ msg.Control.len = sizeof controlBuffer;
+ msg.Control.buf = controlBuffer;
+ msg.dwFlags = flags;
+
+ DWORD dwNumberOfBytesRecvd;
+ signed_size_type result = error_wrapper(WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL), ec);
+
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ } else {
+ dwNumberOfBytesRecvd = -1;
+ }
+ return dwNumberOfBytesRecvd;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ char cmbuf[0x100];
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+ msg.msg_control = cmbuf;
+ msg.msg_controllen = sizeof(cmbuf);
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
diff --git a/implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext_local.ipp
new file mode 100644
index 0000000..b601e11
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/impl/socket_ops_ext_local.ipp
@@ -0,0 +1,302 @@
+//
+// detail/impl/socket_ops_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recv(socket_type s, buf* bufs, size_t count,
+ int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = error_wrapper(::WSARecv(s, bufs,
+ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int tmp_addrlen = (int)*addrlen;
+ int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+ *addrlen = (std::size_t)tmp_addrlen;
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid);
+
+ // Check for end of stream.
+ if (is_stream && bytes == 0)
+ {
+ ec = boost::asio::error::eof;
+ return true;
+ }
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
diff --git a/implementation/helper/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext.hpp
index b51ce24..531ad21 100644
--- a/implementation/helper/boost/asio/detail/reactive_socket_recv_op_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext.hpp
@@ -1,126 +1,126 @@
-//
-// detail/reactive_socket_recv_op_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/detail/fenced_block.hpp>
-#include <boost/asio/detail/reactor_op_ext.hpp>
-#include <boost/asio/detail/socket_ops_ext.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-template <typename MutableBufferSequence>
-class reactive_socket_recv_op_base_ext : public reactor_op_ext
-{
-public:
- reactive_socket_recv_op_base_ext(socket_type socket,
- socket_ops::state_type state, const MutableBufferSequence& buffers,
- socket_base::message_flags flags, func_type complete_func)
- : reactor_op_ext(&reactive_socket_recv_op_base_ext::do_perform, complete_func),
- socket_(socket),
- state_(state),
- buffers_(buffers),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- reactive_socket_recv_op_base_ext* o(
- static_cast<reactive_socket_recv_op_base_ext*>(base));
-
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- return socket_ops::non_blocking_recv(o->socket_,
- bufs.buffers(), bufs.count(), o->flags_,
- (o->state_ & socket_ops::stream_oriented) != 0,
- o->ec_, o->bytes_transferred_);
- }
-
-private:
- socket_type socket_;
- socket_ops::state_type state_;
- MutableBufferSequence buffers_;
- socket_base::message_flags flags_;
-};
-
-template <typename MutableBufferSequence, typename Handler>
-class reactive_socket_recv_op_ext :
- public reactive_socket_recv_op_base_ext<MutableBufferSequence>
-{
-public:
- BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext);
-
- reactive_socket_recv_op_ext(socket_type socket,
- socket_ops::state_type state, const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler& handler)
- : reactive_socket_recv_op_base_ext<MutableBufferSequence>(socket, state,
- buffers, flags, &reactive_socket_recv_op_ext::do_complete),
- handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- static void do_complete(io_service_impl* owner, operation* base,
- const boost::system::error_code& /*ec*/,
- std::size_t /*bytes_transferred*/)
- {
- // Take ownership of the handler object.
- reactive_socket_recv_op_ext* o(static_cast<reactive_socket_recv_op_ext*>(base));
- ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
-
- BOOST_ASIO_HANDLER_COMPLETION((o));
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made. Even if we're not about to make an upcall, a
- // sub-object of the handler may be the true owner of the memory associated
- // with the handler. Consequently, a local copy of the handler is required
- // to ensure that any owning sub-object remains valid until after we have
- // deallocated the memory here.
- detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
- handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
- p.h = boost::asio::detail::addressof(handler.handler_);
- p.reset();
-
- // Make the upcall if required.
- if (owner)
- {
- fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
- BOOST_ASIO_HANDLER_INVOCATION_END;
- }
- }
-
-private:
- Handler handler_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+//
+// detail/reactive_socket_recv_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recv_op_base_ext(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recv_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext* o(
+ static_cast<reactive_socket_recv_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op_ext :
+ public reactive_socket_recv_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext);
+
+ reactive_socket_recv_op_ext(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recv_op_base_ext<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext* o(static_cast<reactive_socket_recv_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
new file mode 100644
index 0000000..6c151ca
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
@@ -0,0 +1,126 @@
+//
+// detail/reactive_socket_recv_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recv_op_base_ext_local(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recv_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext_local* o(
+ static_cast<reactive_socket_recv_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op_ext_local :
+ public reactive_socket_recv_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local);
+
+ reactive_socket_recv_op_ext_local(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recv_op_base_ext_local<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext_local* o(static_cast<reactive_socket_recv_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
index d8c7030..93bdf01 100644
--- a/implementation/helper/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
@@ -1,136 +1,136 @@
-//
-// detail/reactive_socket_recvfrom_op_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/detail/fenced_block.hpp>
-#include <boost/asio/detail/reactor_op_ext.hpp>
-#include <boost/asio/detail/socket_ops_ext.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-template <typename MutableBufferSequence, typename Endpoint>
-class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext
-{
-public:
- reactive_socket_recvfrom_op_base_ext(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers, Endpoint& endpoint,
- socket_base::message_flags flags, func_type complete_func)
- : reactor_op_ext(&reactive_socket_recvfrom_op_base_ext::do_perform, complete_func),
- socket_(socket),
- protocol_type_(protocol_type),
- buffers_(buffers),
- sender_endpoint_(endpoint),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- reactive_socket_recvfrom_op_base_ext* o(
- static_cast<reactive_socket_recvfrom_op_base_ext*>(base));
-
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- std::size_t addr_len = o->sender_endpoint_.capacity();
- bool result = socket_ops::non_blocking_recvfrom(o->socket_,
- bufs.buffers(), bufs.count(), o->flags_,
- o->sender_endpoint_.data(), &addr_len,
- o->ec_, o->bytes_transferred_, o->da_);
-
- if (result && !o->ec_)
- o->sender_endpoint_.resize(addr_len);
-
- return result;
- }
-
-private:
- socket_type socket_;
- int protocol_type_;
- MutableBufferSequence buffers_;
- Endpoint& sender_endpoint_;
- socket_base::message_flags flags_;
-};
-
-template <typename MutableBufferSequence, typename Endpoint, typename Handler>
-class reactive_socket_recvfrom_op_ext :
- public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
-{
-public:
- BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext);
-
- reactive_socket_recvfrom_op_ext(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers, Endpoint& endpoint,
- socket_base::message_flags flags, Handler& handler)
- : reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>(
- socket, protocol_type, buffers, endpoint, flags,
- &reactive_socket_recvfrom_op_ext::do_complete),
- handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- static void do_complete(io_service_impl* owner, operation* base,
- const boost::system::error_code& /*ec*/,
- std::size_t /*bytes_transferred*/)
- {
- // Take ownership of the handler object.
- reactive_socket_recvfrom_op_ext* o(
- static_cast<reactive_socket_recvfrom_op_ext*>(base));
- ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
-
- BOOST_ASIO_HANDLER_COMPLETION((o));
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made. Even if we're not about to make an upcall, a
- // sub-object of the handler may be the true owner of the memory associated
- // with the handler. Consequently, a local copy of the handler is required
- // to ensure that any owning sub-object remains valid until after we have
- // deallocated the memory here.
- detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
- handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
- p.h = boost::asio::detail::addressof(handler.handler_);
- p.reset();
-
- // Make the upcall if required.
- if (owner)
- {
- fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
- BOOST_ASIO_HANDLER_INVOCATION_END;
- }
- }
-
-private:
- Handler handler_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+//
+// detail/reactive_socket_recvfrom_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvfrom_op_base_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvfrom_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ bool result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->da_);
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op_ext :
+ public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext);
+
+ reactive_socket_recvfrom_op_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext* o(
+ static_cast<reactive_socket_recvfrom_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
new file mode 100644
index 0000000..a38844d
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
@@ -0,0 +1,136 @@
+//
+// detail/reactive_socket_recvfrom_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ bool result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op_ext_local :
+ public reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local);
+
+ reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
index 3186464..b28572b 100644
--- a/implementation/helper/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
@@ -1,128 +1,128 @@
-//
-// detail/reactive_socket_recvmsg_op_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/detail/fenced_block.hpp>
-#include <boost/asio/detail/reactor_op_ext.hpp>
-#include <boost/asio/detail/socket_ops_ext.hpp>
-#include <boost/asio/socket_base.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-template <typename MutableBufferSequence>
-class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext
-{
-public:
- reactive_socket_recvmsg_op_base_ext(socket_type socket,
- const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
- socket_base::message_flags& out_flags, func_type complete_func)
- : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func),
- socket_(socket),
- buffers_(buffers),
- in_flags_(in_flags),
- out_flags_(out_flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- reactive_socket_recvmsg_op_base_ext* o(
- static_cast<reactive_socket_recvmsg_op_base_ext*>(base));
-
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- return socket_ops::non_blocking_recvmsg(o->socket_,
- bufs.buffers(), bufs.count(),
- o->in_flags_, o->out_flags_,
- o->ec_, o->bytes_transferred_);
- }
-
-private:
- socket_type socket_;
- MutableBufferSequence buffers_;
- socket_base::message_flags in_flags_;
- socket_base::message_flags& out_flags_;
-};
-
-template <typename MutableBufferSequence, typename Handler>
-class reactive_socket_recvmsg_op_ext :
- public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
-{
-public:
- BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext);
-
- reactive_socket_recvmsg_op_ext(socket_type socket,
- const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
- socket_base::message_flags& out_flags, Handler& handler)
- : reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>(socket, buffers,
- in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete),
- handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
- {
- }
-
- static void do_complete(io_service_impl* owner, operation* base,
- const boost::system::error_code& /*ec*/,
- std::size_t /*bytes_transferred*/)
- {
- // Take ownership of the handler object.
- reactive_socket_recvmsg_op_ext* o(
- static_cast<reactive_socket_recvmsg_op_ext*>(base));
- ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
-
- BOOST_ASIO_HANDLER_COMPLETION((o));
-
- // Make a copy of the handler so that the memory can be deallocated before
- // the upcall is made. Even if we're not about to make an upcall, a
- // sub-object of the handler may be the true owner of the memory associated
- // with the handler. Consequently, a local copy of the handler is required
- // to ensure that any owning sub-object remains valid until after we have
- // deallocated the memory here.
- detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
- handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
- p.h = boost::asio::detail::addressof(handler.handler_);
- p.reset();
-
- // Make the upcall if required.
- if (owner)
- {
- fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
- BOOST_ASIO_HANDLER_INVOCATION_END;
- }
- }
-
-private:
- Handler handler_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+//
+// detail/reactive_socket_recvmsg_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvmsg_op_base_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recvmsg_op_ext :
+ public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext);
+
+ reactive_socket_recvmsg_op_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ : reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext* o(
+ static_cast<reactive_socket_recvmsg_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
new file mode 100644
index 0000000..7b5bc53
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
@@ -0,0 +1,128 @@
+//
+// detail/reactive_socket_recvmsg_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvmsg_op_base_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recvmsg_op_ext_local :
+ public reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local);
+
+ reactive_socket_recvmsg_op_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ : reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext.hpp
index 6c13114..3c0107c 100644
--- a/implementation/helper/boost/asio/detail/reactive_socket_service_base_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext.hpp
@@ -1,455 +1,455 @@
-//
-// detail/reactive_socket_service_base_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <iostream>
-
-#include <boost/asio/detail/config.hpp>
-
-#if !defined(BOOST_ASIO_HAS_IOCP) \
- && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
-
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/detail/reactive_null_buffers_op.hpp>
-#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
-#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
-#include <boost/asio/detail/reactive_socket_send_op.hpp>
-#include <boost/asio/detail/reactor.hpp>
-#include <boost/asio/detail/reactor_op.hpp>
-#include <boost/asio/detail/socket_holder.hpp>
-#include <boost/asio/detail/socket_ops_ext.hpp>
-#include <boost/asio/detail/socket_types.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-class reactive_socket_service_base_ext
-{
-public:
- // The native type of a socket.
- typedef socket_type native_handle_type;
-
- // The implementation type of the socket.
- struct base_implementation_type
- {
- // The native socket representation.
- socket_type socket_;
-
- // The current state of the socket.
- socket_ops::state_type state_;
-
- // Per-descriptor data used by the reactor.
- reactor::per_descriptor_data reactor_data_;
- };
-
- // Constructor.
- BOOST_ASIO_DECL reactive_socket_service_base_ext(
- boost::asio::io_service& io_service);
-
- // Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
-
- // Construct a new socket implementation.
- BOOST_ASIO_DECL void construct(base_implementation_type& impl);
-
- // Move-construct a new socket implementation.
- BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
- base_implementation_type& other_impl);
-
- // Move-assign from another socket implementation.
- BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
- reactive_socket_service_base_ext& other_service,
- base_implementation_type& other_impl);
-
- // Destroy a socket implementation.
- BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
-
- // Determine whether the socket is open.
- bool is_open(const base_implementation_type& impl) const
- {
- return impl.socket_ != invalid_socket;
- }
-
- // Destroy a socket implementation.
- BOOST_ASIO_DECL boost::system::error_code close(
- base_implementation_type& impl, boost::system::error_code& ec);
-
- // Get the native socket representation.
- native_handle_type native_handle(base_implementation_type& impl)
- {
- return impl.socket_;
- }
-
- // Cancel all operations associated with the socket.
- BOOST_ASIO_DECL boost::system::error_code cancel(
- base_implementation_type& impl, boost::system::error_code& ec);
-
- // Determine whether the socket is at the out-of-band data mark.
- bool at_mark(const base_implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return socket_ops::sockatmark(impl.socket_, ec);
- }
-
- // Determine the number of bytes available for reading.
- std::size_t available(const base_implementation_type& impl,
- boost::system::error_code& ec) const
- {
- return socket_ops::available(impl.socket_, ec);
- }
-
- // Place the socket into the state where it will listen for new connections.
- boost::system::error_code listen(base_implementation_type& impl,
- int backlog, boost::system::error_code& ec)
- {
- socket_ops::listen(impl.socket_, backlog, ec);
- return ec;
- }
-
- // Perform an IO control command on the socket.
- template <typename IO_Control_Command>
- boost::system::error_code io_control(base_implementation_type& impl,
- IO_Control_Command& command, boost::system::error_code& ec)
- {
- socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
- static_cast<ioctl_arg_type*>(command.data()), ec);
- return ec;
- }
-
- // Gets the non-blocking mode of the socket.
- bool non_blocking(const base_implementation_type& impl) const
- {
- return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
- }
-
- // Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(base_implementation_type& impl,
- bool mode, boost::system::error_code& ec)
- {
- socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
- return ec;
- }
-
- // Gets the non-blocking mode of the native socket implementation.
- bool native_non_blocking(const base_implementation_type& impl) const
- {
- return (impl.state_ & socket_ops::internal_non_blocking) != 0;
- }
-
- // Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(base_implementation_type& impl,
- bool mode, boost::system::error_code& ec)
- {
- socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
- return ec;
- }
-
- // Disable sends or receives on the socket.
- boost::system::error_code shutdown(base_implementation_type& impl,
- socket_base::shutdown_type what, boost::system::error_code& ec)
- {
- socket_ops::shutdown(impl.socket_, what, ec);
- return ec;
- }
-
- // Send the given data to the peer.
- template <typename ConstBufferSequence>
- size_t send(base_implementation_type& impl,
- const ConstBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- buffer_sequence_adapter<boost::asio::const_buffer,
- ConstBufferSequence> bufs(buffers);
-
- return socket_ops::sync_send(impl.socket_, impl.state_,
- bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
- }
-
- // Wait until data can be sent without blocking.
- size_t send(base_implementation_type& impl, const null_buffers&,
- socket_base::message_flags, boost::system::error_code& ec)
- {
- // Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
-
- return 0;
- }
-
- // Start an asynchronous send. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
- void async_send(base_implementation_type& impl,
- const ConstBufferSequence& buffers,
- socket_base::message_flags flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
-
- start_op(impl, reactor::write_op, p.p, is_continuation, true,
- ((impl.state_ & socket_ops::stream_oriented)
- && buffer_sequence_adapter<boost::asio::const_buffer,
- ConstBufferSequence>::all_empty(buffers)));
- p.v = p.p = 0;
- }
-
- // Start an asynchronous wait until data can be sent without blocking.
- template <typename Handler>
- void async_send(base_implementation_type& impl, const null_buffers&,
- socket_base::message_flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_null_buffers_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send(null_buffers)"));
-
- start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
- p.v = p.p = 0;
- }
-
- // Receive some data from the peer. Returns the number of bytes received.
- template <typename MutableBufferSequence>
- size_t receive(base_implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, boost::system::error_code& ec)
- {
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
-
- return socket_ops::sync_recv(impl.socket_, impl.state_,
- bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
- }
-
- // Wait until data can be received without blocking.
- size_t receive(base_implementation_type& impl, const null_buffers&,
- socket_base::message_flags, boost::system::error_code& ec)
- {
- // Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
-
- return 0;
- }
-
- // Start an asynchronous receive. The buffer for the data being received
- // must be valid for the lifetime of the asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_receive(base_implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_recv_op_ext<MutableBufferSequence, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation,
- (flags & socket_base::message_out_of_band) == 0,
- ((impl.state_ & socket_ops::stream_oriented)
- && buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence>::all_empty(buffers)));
- p.v = p.p = 0;
- }
-
- // Wait until data can be received without blocking.
- template <typename Handler>
- void async_receive(base_implementation_type& impl, const null_buffers&,
- socket_base::message_flags flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_null_buffers_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive(null_buffers)"));
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation, false, false);
- p.v = p.p = 0;
- }
-
- // Receive some data with associated flags. Returns the number of bytes
- // received.
- template <typename MutableBufferSequence>
- size_t receive_with_flags(base_implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags in_flags,
- socket_base::message_flags& out_flags, boost::system::error_code& ec)
- {
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
-
- return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
- bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
- }
-
- // Wait until data can be received without blocking.
- size_t receive_with_flags(base_implementation_type& impl,
- const null_buffers&, socket_base::message_flags,
- socket_base::message_flags& out_flags, boost::system::error_code& ec)
- {
- // Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
-
- // Clear out_flags, since we cannot give it any other sensible value when
- // performing a null_buffers operation.
- out_flags = 0;
-
- return 0;
- }
-
- // Start an asynchronous receive. The buffer for the data being received
- // must be valid for the lifetime of the asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_receive_with_flags(base_implementation_type& impl,
- const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
- socket_base::message_flags& out_flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_recvmsg_op_ext<MutableBufferSequence, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_with_flags"));
-
- start_op(impl,
- (in_flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation,
- (in_flags & socket_base::message_out_of_band) == 0, false);
- p.v = p.p = 0;
- }
-
- // Wait until data can be received without blocking.
- template <typename Handler>
- void async_receive_with_flags(base_implementation_type& impl,
- const null_buffers&, socket_base::message_flags in_flags,
- socket_base::message_flags& out_flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_null_buffers_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
- "async_receive_with_flags(null_buffers)"));
-
- // Clear out_flags, since we cannot give it any other sensible value when
- // performing a null_buffers operation.
- out_flags = 0;
-
- start_op(impl,
- (in_flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation, false, false);
- p.v = p.p = 0;
- }
-
-protected:
- // Open a new socket implementation.
- BOOST_ASIO_DECL boost::system::error_code do_open(
- base_implementation_type& impl, int af,
- int type, int protocol, boost::system::error_code& ec);
-
- // Assign a native socket to a socket implementation.
- BOOST_ASIO_DECL boost::system::error_code do_assign(
- base_implementation_type& impl, int type,
- const native_handle_type& native_socket, boost::system::error_code& ec);
-
- // Start the asynchronous read or write operation.
- BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
- reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
-
- // Start the asynchronous accept operation.
- BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
- reactor_op* op, bool is_continuation, bool peer_is_open);
-
- // Start the asynchronous connect operation.
- BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
- reactor_op* op, bool is_continuation,
- const socket_addr_type* addr, size_t addrlen);
-
- // The selector that performs event demultiplexing for the service.
- reactor& reactor_;
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#if defined(BOOST_ASIO_HEADER_ONLY)
-# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
-#endif // defined(BOOST_ASIO_HEADER_ONLY)
-
-#endif // !defined(BOOST_ASIO_HAS_IOCP)
- // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
-
-#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+//
+// detail/reactive_socket_service_base_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext(
+ boost::asio::io_service& io_service);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void shutdown_service();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
new file mode 100644
index 0000000..e97fca2
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
@@ -0,0 +1,454 @@
+//
+// detail/reactive_socket_service_base_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext_local
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext_local(
+ boost::asio::io_service& io_service);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void shutdown_service();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext_local<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext_local<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext.hpp
index 39aa0cc..133301c 100644
--- a/implementation/helper/boost/asio/detail/reactive_socket_service_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext.hpp
@@ -1,462 +1,462 @@
-//
-// detail/reactive_socket_service_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <iostream>
-
-#include <boost/asio/detail/config.hpp>
-
-#if !defined(BOOST_ASIO_HAS_IOCP)
-
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/reactive_null_buffers_op.hpp>
-#include <boost/asio/detail/reactive_socket_accept_op.hpp>
-#include <boost/asio/detail/reactive_socket_connect_op.hpp>
-#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
-#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
-#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
-#include <boost/asio/detail/reactor.hpp>
-#include <boost/asio/detail/reactor_op.hpp>
-#include <boost/asio/detail/socket_holder.hpp>
-#include <boost/asio/detail/socket_ops.hpp>
-#include <boost/asio/detail/socket_types.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-template <typename Protocol>
-class reactive_socket_service_ext :
- public reactive_socket_service_base_ext
-{
-public:
- // The protocol type.
- typedef Protocol protocol_type;
-
- // The endpoint type.
- typedef typename Protocol::endpoint endpoint_type;
-
- // The native type of a socket.
- typedef socket_type native_handle_type;
-
- // The implementation type of the socket.
- struct implementation_type :
- reactive_socket_service_base_ext::base_implementation_type
- {
- // Default constructor.
- implementation_type()
- : protocol_(endpoint_type().protocol())
- {
- }
-
- // The protocol associated with the socket.
- protocol_type protocol_;
- };
-
- // Constructor.
- reactive_socket_service_ext(boost::asio::io_service& io_service)
- : reactive_socket_service_base_ext(io_service)
- {
- }
-
- // Move-construct a new socket implementation.
- void move_construct(implementation_type& impl,
- implementation_type& other_impl)
- {
- this->base_move_construct(impl, other_impl);
-
- impl.protocol_ = other_impl.protocol_;
- other_impl.protocol_ = endpoint_type().protocol();
- }
-
- // Move-assign from another socket implementation.
- void move_assign(implementation_type& impl,
- reactive_socket_service_base_ext& other_service,
- implementation_type& other_impl)
- {
- this->base_move_assign(impl, other_service, other_impl);
-
- impl.protocol_ = other_impl.protocol_;
- other_impl.protocol_ = endpoint_type().protocol();
- }
-
- // Move-construct a new socket implementation from another protocol type.
- template <typename Protocol1>
- void converting_move_construct(implementation_type& impl,
- typename reactive_socket_service_ext<
- Protocol1>::implementation_type& other_impl)
- {
- this->base_move_construct(impl, other_impl);
-
- impl.protocol_ = protocol_type(other_impl.protocol_);
- other_impl.protocol_ = typename Protocol1::endpoint().protocol();
- }
-
- // Open a new socket implementation.
- boost::system::error_code open(implementation_type& impl,
- const protocol_type& protocol, boost::system::error_code& ec)
- {
- if (!do_open(impl, protocol.family(),
- protocol.type(), protocol.protocol(), ec))
- impl.protocol_ = protocol;
- return ec;
- }
-
- // Assign a native socket to a socket implementation.
- boost::system::error_code assign(implementation_type& impl,
- const protocol_type& protocol, const native_handle_type& native_socket,
- boost::system::error_code& ec)
- {
- if (!do_assign(impl, protocol.type(), native_socket, ec))
- impl.protocol_ = protocol;
- return ec;
- }
-
- // Get the native socket representation.
- native_handle_type native_handle(implementation_type& impl)
- {
- return impl.socket_;
- }
-
- // Bind the socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
- const endpoint_type& endpoint, boost::system::error_code& ec)
- {
- socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
- return ec;
- }
-
- // Set a socket option.
- template <typename Option>
- boost::system::error_code set_option(implementation_type& impl,
- const Option& option, boost::system::error_code& ec)
- {
- socket_ops::setsockopt(impl.socket_, impl.state_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), option.size(impl.protocol_), ec);
- return ec;
- }
-
- // Set a socket option.
- template <typename Option>
- boost::system::error_code get_option(const implementation_type& impl,
- Option& option, boost::system::error_code& ec) const
- {
- std::size_t size = option.size(impl.protocol_);
- socket_ops::getsockopt(impl.socket_, impl.state_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), &size, ec);
- if (!ec)
- option.resize(impl.protocol_, size);
- return ec;
- }
-
- // Get the local endpoint.
- endpoint_type local_endpoint(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- endpoint_type endpoint;
- std::size_t addr_len = endpoint.capacity();
- if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
- return endpoint_type();
- endpoint.resize(addr_len);
- return endpoint;
- }
-
- // Get the remote endpoint.
- endpoint_type remote_endpoint(const implementation_type& impl,
- boost::system::error_code& ec) const
- {
- endpoint_type endpoint;
- std::size_t addr_len = endpoint.capacity();
- if (socket_ops::getpeername(impl.socket_,
- endpoint.data(), &addr_len, false, ec))
- return endpoint_type();
- endpoint.resize(addr_len);
- return endpoint;
- }
-
- // Send a datagram to the specified endpoint. Returns the number of bytes
- // sent.
- template <typename ConstBufferSequence>
- size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
- const endpoint_type& destination, socket_base::message_flags flags,
- boost::system::error_code& ec)
- {
- buffer_sequence_adapter<boost::asio::const_buffer,
- ConstBufferSequence> bufs(buffers);
-
- return socket_ops::sync_sendto(impl.socket_, impl.state_,
- bufs.buffers(), bufs.count(), flags,
- destination.data(), destination.size(), ec);
- }
-
- // Wait until data can be sent without blocking.
- size_t send_to(implementation_type& impl, const null_buffers&,
- const endpoint_type&, socket_base::message_flags,
- boost::system::error_code& ec)
- {
- // Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
-
- return 0;
- }
-
- // Start an asynchronous send. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
- void async_send_to(implementation_type& impl,
- const ConstBufferSequence& buffers,
- const endpoint_type& destination, socket_base::message_flags flags,
- Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_sendto_op<ConstBufferSequence,
- endpoint_type, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
-
- start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
- p.v = p.p = 0;
- }
-
- // Start an asynchronous wait until data can be sent without blocking.
- template <typename Handler>
- void async_send_to(implementation_type& impl, const null_buffers&,
- const endpoint_type&, socket_base::message_flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_null_buffers_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send_to(null_buffers)"));
-
- start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
- p.v = p.p = 0;
- }
-
- // Receive a datagram with the endpoint of the sender. Returns the number of
- // bytes received.
- template <typename MutableBufferSequence>
- size_t receive_from(implementation_type& impl,
- const MutableBufferSequence& buffers,
- endpoint_type& sender_endpoint, socket_base::message_flags flags,
- boost::system::error_code& ec)
- {
- buffer_sequence_adapter<boost::asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
-
- std::size_t addr_len = sender_endpoint.capacity();
- std::size_t bytes_recvd = socket_ops::sync_recvfrom(
- impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
- flags, sender_endpoint.data(), &addr_len, ec);
-
- if (!ec)
- sender_endpoint.resize(addr_len);
-
- return bytes_recvd;
- }
-
- // Wait until data can be received without blocking.
- size_t receive_from(implementation_type& impl, const null_buffers&,
- endpoint_type& sender_endpoint, socket_base::message_flags,
- boost::system::error_code& ec)
- {
- // Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
-
- // Reset endpoint since it can be given no sensible value at this time.
- sender_endpoint = endpoint_type();
-
- return 0;
- }
-
- // Start an asynchronous receive. The buffer for the data being received and
- // the sender_endpoint object must both be valid for the lifetime of the
- // asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_receive_from(implementation_type& impl,
- const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
- socket_base::message_flags flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_recvfrom_op_ext<MutableBufferSequence,
- endpoint_type, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- int protocol = impl.protocol_.type();
- p.p = new (p.v) op(impl.socket_, protocol,
- buffers, sender_endpoint, flags, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_from"));
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation, true, false);
- p.v = p.p = 0;
- }
-
- // Wait until data can be received without blocking.
- template <typename Handler>
- void async_receive_from(implementation_type& impl,
- const null_buffers&, endpoint_type& sender_endpoint,
- socket_base::message_flags flags, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_null_buffers_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_from(null_buffers)"));
-
- // Reset endpoint since it can be given no sensible value at this time.
- sender_endpoint = endpoint_type();
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- p.p, is_continuation, false, false);
- p.v = p.p = 0;
- }
-
- // Accept a new connection.
- template <typename Socket>
- boost::system::error_code accept(implementation_type& impl,
- Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
- {
- // We cannot accept a socket that is already open.
- if (peer.is_open())
- {
- ec = boost::asio::error::already_open;
- return ec;
- }
-
- std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
- socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
- impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
- peer_endpoint ? &addr_len : 0, ec));
-
- // On success, assign new connection to peer socket object.
- if (new_socket.get() != invalid_socket)
- {
- if (peer_endpoint)
- peer_endpoint->resize(addr_len);
- if (!peer.assign(impl.protocol_, new_socket.get(), ec))
- new_socket.release();
- }
-
- return ec;
- }
-
- // Start an asynchronous accept. The peer and peer_endpoint objects
- // must be valid until the accept's handler is invoked.
- template <typename Socket, typename Handler>
- void async_accept(implementation_type& impl, Socket& peer,
- endpoint_type* peer_endpoint, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, impl.state_, peer,
- impl.protocol_, peer_endpoint, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
-
- start_accept_op(impl, p.p, is_continuation, peer.is_open());
- p.v = p.p = 0;
- }
-
- // Connect the socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
- const endpoint_type& peer_endpoint, boost::system::error_code& ec)
- {
- socket_ops::sync_connect(impl.socket_,
- peer_endpoint.data(), peer_endpoint.size(), ec);
- return ec;
- }
-
- // Start an asynchronous connect.
- template <typename Handler>
- void async_connect(implementation_type& impl,
- const endpoint_type& peer_endpoint, Handler& handler)
- {
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef reactive_socket_connect_op<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
-
- start_connect_op(impl, p.p, is_continuation,
- peer_endpoint.data(), peer_endpoint.size());
- p.v = p.p = 0;
- }
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // !defined(BOOST_ASIO_HAS_IOCP)
-
-#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+//
+// detail/reactive_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext :
+ public reactive_socket_service_base_ext
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext(boost::asio::io_service& io_service)
+ : reactive_socket_service_base_ext(io_service)
+ {
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ typename reactive_socket_service_ext<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext<MutableBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol,
+ buffers, sender_endpoint, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects
+ // must be valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext_local.hpp
new file mode 100644
index 0000000..7b444b3
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactive_socket_service_ext_local.hpp
@@ -0,0 +1,462 @@
+//
+// detail/reactive_socket_service_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext_local :
+ public reactive_socket_service_base_ext_local
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext_local::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext_local(boost::asio::io_service& io_service)
+ : reactive_socket_service_base_ext_local(io_service)
+ {
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ typename reactive_socket_service_ext_local<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext_local<MutableBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol,
+ buffers, sender_endpoint, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
+ &impl, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects
+ // must be valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.55/boost/asio/detail/reactor_op_ext.hpp
index c463679..948e016 100644
--- a/implementation/helper/boost/asio/detail/reactor_op_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/reactor_op_ext.hpp
@@ -1,42 +1,42 @@
-//
-// detail/reactor_op_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
-#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/reactor_op.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-class reactor_op_ext
- : public reactor_op
-{
-public:
- // The destination address
- boost::asio::ip::address da_;
-
- reactor_op_ext(perform_func_type perform_func, func_type complete_func)
- : reactor_op(perform_func, complete_func)
- {
- }
-};
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+//
+// detail/reactor_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext
+ : public reactor_op
+{
+public:
+ // The destination address
+ boost::asio::ip::address da_;
+
+ reactor_op_ext(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/reactor_op_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/reactor_op_ext_local.hpp
new file mode 100644
index 0000000..a10d876
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/reactor_op_ext_local.hpp
@@ -0,0 +1,43 @@
+//
+// detail/reactor_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext_local
+ : public reactor_op
+{
+public:
+ // The passed credentials
+ std::uint32_t uid_;
+ std::uint32_t gid_;
+
+ reactor_op_ext_local(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/1.55/boost/asio/detail/socket_ops_ext.hpp
index 30db4f9..65b8ad8 100644
--- a/implementation/helper/boost/asio/detail/socket_ops_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/detail/socket_ops_ext.hpp
@@ -1,62 +1,62 @@
-//
-// detail/socket_ops_ext.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
-#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/socket_ops.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-namespace socket_ops {
-
-BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
- size_t count, int flags, socket_addr_type* addr,
- std::size_t* addrlen, boost::system::error_code& ec,
- boost::asio::ip::address& da);
-
-BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
- buf* bufs, size_t count, int flags, socket_addr_type* addr,
- std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da);
-
-#if defined(BOOST_ASIO_HAS_IOCP)
-
-BOOST_ASIO_DECL void complete_iocp_recvfrom(
- const weak_cancel_token_type& cancel_token,
- boost::system::error_code& ec,
- boost::asio::ip::address& da);
-
-#else // defined(BOOST_ASIO_HAS_IOCP)
-
-BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
- buf* bufs, size_t count, int flags,
- socket_addr_type* addr, std::size_t* addrlen,
- boost::system::error_code& ec, size_t& bytes_transferred,
- boost::asio::ip::address& da);
-
-#endif // defined(BOOST_ASIO_HAS_IOCP)
-
-} // namespace socket_ops
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-
-#if defined(BOOST_ASIO_HEADER_ONLY)
-# include <boost/asio/detail/impl/socket_ops_ext.ipp>
-#endif // defined(BOOST_ASIO_HEADER_ONLY)
-
-#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
+//
+// detail/socket_ops_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/socket_ops.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ boost::asio::ip::address& da);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/implementation/helper/1.55/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.55/boost/asio/detail/socket_ops_ext_local.hpp
new file mode 100644
index 0000000..77fd563
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/detail/socket_ops_ext_local.hpp
@@ -0,0 +1,72 @@
+//
+// detail/socket_ops_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/socket_ops.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs,
+ size_t count, int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/implementation/helper/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.55/boost/asio/ip/udp_ext.hpp
index 7ceadce..c622ff9 100644
--- a/implementation/helper/boost/asio/ip/udp_ext.hpp
+++ b/implementation/helper/1.55/boost/asio/ip/udp_ext.hpp
@@ -1,115 +1,115 @@
-//
-// ip/udp_ext.hpp
-// ~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-#ifndef BOOST_ASIO_IP_UDP_EXT_HPP
-#define BOOST_ASIO_IP_UDP_EXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/asio/basic_datagram_socket_ext.hpp>
-#include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/ip/basic_endpoint.hpp>
-#include <boost/asio/ip/basic_resolver.hpp>
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
-#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/ip/udp.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ip {
-
-/// Encapsulates the flags needed for UDP.
-/**
- * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets.
- *
- * @par Thread Safety
- * @e Distinct @e objects: Safe.@n
- * @e Shared @e objects: Safe.
- *
- * @par Concepts:
- * Protocol, InternetProtocol.
- */
-class udp_ext
-{
-public:
- /// The type of a UDP endpoint.
- typedef basic_endpoint<udp> endpoint;
-
- /// Construct to represent the IPv4 UDP protocol.
- static udp_ext v4()
- {
- return udp_ext(BOOST_ASIO_OS_DEF(AF_INET));
- }
-
- /// Construct to represent the IPv6 UDP protocol.
- static udp_ext v6()
- {
- return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6));
- }
-
- /// Obtain an identifier for the type of the protocol.
- int type() const
- {
- return BOOST_ASIO_OS_DEF(SOCK_DGRAM);
- }
-
- /// Obtain an identifier for the protocol.
- int protocol() const
- {
- return BOOST_ASIO_OS_DEF(IPPROTO_UDP);
- }
-
- /// Obtain an identifier for the protocol family.
- int family() const
- {
- return family_;
- }
-
- /// The UDP socket type.
- typedef basic_datagram_socket_ext<udp> socket;
-
- /// The UDP resolver type.
- typedef basic_resolver<udp> resolver;
-
- /// Compare two protocols for equality.
- friend bool operator==(const udp_ext& p1, const udp_ext& p2)
- {
- return p1.family_ == p2.family_;
- }
-
- /// Compare two protocols for inequality.
- friend bool operator!=(const udp_ext& p1, const udp_ext& p2)
- {
- return p1.family_ != p2.family_;
- }
-
-private:
- // Construct with a specific family.
- explicit udp_ext(int protocol_family)
- : family_(protocol_family)
- {
- }
-
- int family_;
-};
-
-} // namespace ip
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_IP_UDP_EXT_HPP
+//
+// ip/udp_ext.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_UDP_EXT_HPP
+#define BOOST_ASIO_IP_UDP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_datagram_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/udp.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for UDP.
+/**
+ * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class udp_ext
+{
+public:
+ /// The type of a UDP endpoint.
+ typedef basic_endpoint<udp> endpoint;
+
+ /// Construct to represent the IPv4 UDP protocol.
+ static udp_ext v4()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET));
+ }
+
+ /// Construct to represent the IPv6 UDP protocol.
+ static udp_ext v6()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6));
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return BOOST_ASIO_OS_DEF(SOCK_DGRAM);
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return BOOST_ASIO_OS_DEF(IPPROTO_UDP);
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The UDP socket type.
+ typedef basic_datagram_socket_ext<udp> socket;
+
+ /// The UDP resolver type.
+ typedef basic_resolver<udp> resolver;
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit udp_ext(int protocol_family)
+ : family_(protocol_family)
+ {
+ }
+
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_UDP_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.55/boost/asio/local/stream_protocol_ext.hpp
new file mode 100644
index 0000000..6ccd0ad
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/local/stream_protocol_ext.hpp
@@ -0,0 +1,93 @@
+//
+// local/stream_protocol_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/basic_socket_acceptor_ext.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_stream_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Encapsulates the flags needed for stream-oriented UNIX sockets.
+/**
+ * The boost::asio::local::stream_protocol class contains flags necessary for
+ * stream-oriented UNIX domain sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol.
+ */
+class stream_protocol_ext
+{
+public:
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_STREAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return 0;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return AF_UNIX;
+ }
+
+ /// The type of a UNIX domain endpoint.
+ typedef basic_endpoint<stream_protocol_ext> endpoint;
+
+ /// The UNIX domain socket type.
+ typedef basic_stream_socket_ext<stream_protocol_ext> socket;
+
+ /// The UNIX domain acceptor type.
+ typedef basic_socket_acceptor_ext<stream_protocol_ext> acceptor;
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+ /// The UNIX domain iostream type.
+ typedef basic_socket_iostream<stream_protocol_ext> iostream;
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+};
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/socket_acceptor_service_ext.hpp b/implementation/helper/1.55/boost/asio/socket_acceptor_service_ext.hpp
new file mode 100644
index 0000000..19a3bde
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/socket_acceptor_service_ext.hpp
@@ -0,0 +1,305 @@
+//
+// socket_acceptor_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_EXT_HPP
+#define BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a socket acceptor.
+template <typename Protocol>
+class socket_acceptor_service_ext
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<socket_acceptor_service_ext<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename protocol_type::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef detail::null_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#else
+ typedef detail::reactive_socket_service_ext<Protocol> service_impl_type;
+#endif
+
+public:
+ /// The native type of the socket acceptor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// (Deprecated: Use native_handle_type.) The native acceptor type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_type;
+#endif
+
+ /// The native acceptor type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_handle_type;
+#endif
+
+ /// Construct a new socket acceptor service for the specified io_service.
+ explicit socket_acceptor_service_ext(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ socket_acceptor_service_ext<Protocol> >(io_service),
+ service_impl_(io_service)
+ {
+ }
+
+ /// Construct a new socket acceptor implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new socket acceptor implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another socket acceptor implementation.
+ void move_assign(implementation_type& impl,
+ socket_acceptor_service_ext& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+
+ /// Move-construct a new socket acceptor implementation from another protocol
+ /// type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ typename socket_acceptor_service_ext<
+ Protocol1>::implementation_type& other_impl,
+ typename enable_if<is_convertible<
+ Protocol1, Protocol>::value>::type* = 0)
+ {
+ service_impl_.template converting_move_construct<Protocol1>(
+ impl, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroy a socket acceptor implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a new socket acceptor implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ return service_impl_.open(impl, protocol, ec);
+ }
+
+ /// Assign an existing native acceptor to a socket acceptor.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_acceptor,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_acceptor, ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Bind the socket acceptor to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Place the socket acceptor into the state where it will listen for new
+ /// connections.
+ boost::system::error_code listen(implementation_type& impl, int backlog,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.listen(impl, backlog, ec);
+ }
+
+ /// Close a socket acceptor implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// (Deprecated: Use native_handle().) Get the native acceptor implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Get the native acceptor implementation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Gets the non-blocking mode of the acceptor.
+ bool non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ boost::system::error_code non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.non_blocking(impl, mode, ec);
+ }
+
+ /// Gets the non-blocking mode of the native acceptor implementation.
+ bool native_non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.native_non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ boost::system::error_code native_non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.native_non_blocking(impl, mode, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Accept a new connection.
+ template <typename Protocol1, typename SocketService>
+ boost::system::error_code accept(implementation_type& impl,
+ basic_socket<Protocol1, SocketService>& peer,
+ endpoint_type* peer_endpoint, boost::system::error_code& ec,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+ {
+ return service_impl_.accept(impl, peer, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ template <typename Protocol1, typename SocketService, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(implementation_type& impl,
+ basic_socket<Protocol1, SocketService>& peer,
+ endpoint_type* peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+ {
+ detail::async_result_init<
+ AcceptHandler, void (boost::system::error_code)> init(
+ BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+
+ service_impl_.async_accept(impl, peer, peer_endpoint, init.handler);
+
+ return init.result.get();
+ }
+
+private:
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ service_impl_.shutdown_service();
+ }
+
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.55/boost/asio/stream_socket_service_ext.hpp b/implementation/helper/1.55/boost/asio/stream_socket_service_ext.hpp
new file mode 100644
index 0000000..aaa13b3
--- /dev/null
+++ b/implementation/helper/1.55/boost/asio/stream_socket_service_ext.hpp
@@ -0,0 +1,379 @@
+//
+// stream_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
+#define BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_ssocket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a stream socket.
+template <typename Protocol>
+class stream_socket_service_ext
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<stream_socket_service_ext<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef detail::winrt_ssocket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#else
+ typedef detail::reactive_socket_service_ext_local<Protocol> service_impl_type;
+#endif
+
+public:
+ /// The type of a stream socket implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// (Deprecated: Use native_handle_type.) The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_handle_type;
+#endif
+
+ /// Construct a new stream socket service for the specified io_service.
+ explicit stream_socket_service_ext(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ stream_socket_service_ext<Protocol> >(io_service),
+ service_impl_(io_service)
+ {
+ }
+
+ /// Construct a new stream socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new stream socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another stream socket implementation.
+ void move_assign(implementation_type& impl,
+ stream_socket_service_ext& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+
+ /// Move-construct a new stream socket implementation from another protocol
+ /// type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ typename stream_socket_service_ext<
+ Protocol1>::implementation_type& other_impl,
+ typename enable_if<is_convertible<
+ Protocol1, Protocol>::value>::type* = 0)
+ {
+ service_impl_.template converting_move_construct<Protocol1>(
+ impl, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroy a stream socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a stream socket.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_STREAM))
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ /// Assign an existing native socket to a stream socket.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a stream socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// (Deprecated: Use native_handle().) Get the native socket implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Get the native socket implementation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ /// Bind the stream socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Connect the stream socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.connect(impl, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ detail::async_result_init<
+ ConnectHandler, void (boost::system::error_code)> init(
+ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+
+ service_impl_.async_connect(impl, peer_endpoint, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ bool non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.non_blocking(impl, mode, ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.native_non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ return service_impl_.native_non_blocking(impl, mode, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, what, ec);
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ detail::async_result_init<
+ WriteHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+
+ service_impl_.async_send(impl, buffers, flags, init.handler);
+
+ return init.result.get();
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ detail::async_result_init<
+ ReadHandler, void (boost::system::error_code, std::size_t)> init(
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+
+ service_impl_.async_receive(impl, buffers, flags, init.handler);
+
+ return init.result.get();
+ }
+
+private:
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ service_impl_.shutdown_service();
+ }
+
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/basic_datagram_socket_ext.hpp b/implementation/helper/1.66/boost/asio/basic_datagram_socket_ext.hpp
new file mode 100644
index 0000000..2820f81
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/basic_datagram_socket_ext.hpp
@@ -0,0 +1,1043 @@
+//
+// basic_datagram_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/basic_socket_ext.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#include <boost/asio/detail/datagram_socket_service_ext.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides datagram-oriented socket functionality.
+/**
+ * The basic_datagram_socket class template provides asynchronous and blocking
+ * datagram-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= datagram_socket_service_ext<Protocol>)>
+class basic_datagram_socket_ext
+ : public basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>
+{
+public:
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket_ext<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_datagram_socket without opening it.
+ /**
+ * This constructor creates a datagram socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param io_context The io_context object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ */
+ explicit basic_datagram_socket_ext(boost::asio::io_context& io_context)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(io_context)
+ {
+ }
+
+ /// Construct and open a basic_datagram_socket.
+ /**
+ * This constructor creates and opens a datagram socket.
+ *
+ * @param io_context The io_context object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
+ {
+ }
+
+ /// Construct a basic_datagram_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a datagram socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_context The io_context object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the datagram
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_context& io_context,
+ const endpoint_type& endpoint)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
+ {
+ }
+
+ /// Construct a basic_datagram_socket on an existing native socket.
+ /**
+ * This constructor creates a datagram socket object to hold an existing
+ * native socket.
+ *
+ * @param io_context The io_context object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_datagram_socket from another.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
+ */
+ basic_datagram_socket_ext(basic_datagram_socket_ext&& other)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from another.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
+ */
+ basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other)
+ {
+ basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_datagram_socket_ext(
+ basic_datagram_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_datagram_socket_ext>::type& operator=(
+ basic_datagram_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
+ {
+ basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the socket
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_datagram_socket_ext()
+ {
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code socket.send(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.send_to(boost::asio::buffer(data, size), destination);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send_to(
+ this->get_implementation(), buffers, destination, 0, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send_to(
+ this->get_implementation(), buffers, destination, flags, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().send_to(this->get_implementation(),
+ buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_send_to(
+ * boost::asio::buffer(data, size), destination, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, 0,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, flags,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.receive(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * boost::asio::ip::udp::endpoint sender_endpoint;
+ * socket.receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().receive_from(this->get_implementation(),
+ buffers, sender_endpoint, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.async_receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0,
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags,
+ BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
diff --git a/implementation/helper/1.66/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.66/boost/asio/basic_socket_acceptor_ext.hpp
new file mode 100644
index 0000000..92d71e3
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/basic_socket_acceptor_ext.hpp
@@ -0,0 +1,1989 @@
+//
+// basic_socket_acceptor_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/basic_socket_ext_local.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/socket_acceptor_service_ext.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::null_socket_service<Protocol>
+# elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol>
+# else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_socket_service_ext_local<Protocol>
+# endif
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides the ability to accept new connections.
+/**
+ * The basic_socket_acceptor_ext class template is used for accepting new socket
+ * connections.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= socket_acceptor_service<Protocol>)>
+class basic_socket_acceptor_ext
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of an acceptor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct an acceptor without opening it.
+ /**
+ * This constructor creates an acceptor without opening it to listen for new
+ * connections. The open() function must be called before the acceptor can
+ * accept new socket connections.
+ *
+ * @param io_context The io_context object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ */
+ explicit basic_socket_acceptor_ext(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct an open acceptor.
+ /**
+ * This constructor creates an acceptor and automatically opens it.
+ *
+ * @param io_context The io_context object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct an acceptor opened on the given endpoint.
+ /**
+ * This constructor creates an acceptor and automatically opens it to listen
+ * for new connections on the specified endpoint.
+ *
+ * @param io_context The io_context object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param endpoint An endpoint on the local machine on which the acceptor
+ * will listen for new connections.
+ *
+ * @param reuse_addr Whether the constructor should set the socket option
+ * socket_base::reuse_address.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This constructor is equivalent to the following code:
+ * @code
+ * basic_socket_acceptor_ext<Protocol> acceptor(io_context);
+ * acceptor.open(endpoint.protocol());
+ * if (reuse_addr)
+ * acceptor.set_option(socket_base::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen(listen_backlog);
+ * @endcode
+ */
+ basic_socket_acceptor_ext(boost::asio::io_context& io_context,
+ const endpoint_type& endpoint, bool reuse_addr = true)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ if (reuse_addr)
+ {
+ this->get_service().set_option(this->get_implementation(),
+ socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ this->get_service().listen(this->get_implementation(),
+ socket_base::max_listen_connections, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Construct a basic_socket_acceptor_ext on an existing native acceptor.
+ /**
+ * This constructor creates an acceptor object to hold an existing native
+ * acceptor.
+ *
+ * @param io_context The io_context object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol, const native_handle_type& native_acceptor)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket_acceptor_ext from another.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor_ext(io_context&) constructor.
+ */
+ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_socket_acceptor_ext from another.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor_ext(io_context&) constructor.
+ */
+ basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+
+ // All socket acceptors have access to each other's implementations.
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ friend class basic_socket_acceptor_ext;
+
+ /// Move-construct a basic_socket_acceptor_ext from an acceptor of another
+ /// protocol type.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_ext_local(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_socket_acceptor_ext(
+ basic_socket_acceptor_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_io_object<BOOST_ASIO_SVC_T>(
+ other.get_service(), other.get_implementation())
+ {
+ }
+
+ /// Move-assign a basic_socket_acceptor_ext from an acceptor of another protocol
+ /// type.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_ext_local(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_socket_acceptor_ext>::type& operator=(
+ basic_socket_acceptor_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
+ {
+ basic_socket_acceptor_ext tmp(std::move(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the acceptor.
+ /**
+ * This function destroys the acceptor, cancelling any outstanding
+ * asynchronous operations associated with the acceptor as if by calling
+ * @c cancel.
+ */
+ ~basic_socket_acceptor_ext()
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * boost::system::error_code ec;
+ * acceptor.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor, boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_acceptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.bind(endpoint);
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * boost::system::error_code ec;
+ * acceptor.bind(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void listen(int backlog = socket_base::max_listen_connections)
+ {
+ boost::system::error_code ec;
+ this->get_service().listen(this->get_implementation(), backlog, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec)
+ {
+ this->get_service().listen(this->get_implementation(), backlog, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native acceptor.
+ /**
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = this->get_service().release(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native acceptor.
+ /**
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return this->get_service().release(this->get_implementation(), ec);
+ }
+
+ /// Get the native acceptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * acceptor. This is intended to allow access to native acceptor functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * boost::system::error_code ec;
+ * acceptor.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * acceptor.get_option(option);
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * boost::system::error_code ec;
+ * acceptor.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * socket.io_control(command);
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the acceptor.
+ /**
+ * @returns @c true if the acceptor's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return this->get_service().non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native acceptor. This mode has no effect on the behaviour of the acceptor
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying acceptor is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the acceptor object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native acceptor.
+ */
+ bool native_non_blocking() const
+ {
+ return this->get_service().native_non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().local_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ * Returns a default-constructed endpoint object if an error occurred and the
+ * error handler did not throw an exception.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().local_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the acceptor to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for an acceptor to
+ * enter a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_wait(
+ * boost::asio::ip::tcp::acceptor::wait_read,
+ * wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ w, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * acceptor.accept(socket);
+ * @endcode
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1, typename SocketService>
+ void accept(basic_socket_ext_local<Protocol1, SocketService>& peer,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1>
+ void accept(basic_socket_ext_local<Protocol1>& peer,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ boost::system::error_code ec;
+ this->get_service().accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1, typename SocketService>
+ BOOST_ASIO_SYNC_OP_VOID accept(
+ basic_socket_ext_local<Protocol1, SocketService>& peer,
+ boost::system::error_code& ec,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1>
+ BOOST_ASIO_SYNC_OP_VOID accept(
+ basic_socket_ext_local<Protocol1>& peer, boost::system::error_code& ec,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ this->get_service().accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket. The function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * acceptor.async_accept(socket, accept_handler);
+ * @endcode
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1, typename SocketService, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<Protocol1, SocketService>& peer,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<Protocol1>& peer,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a AcceptHandler.
+ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<AcceptHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.accept(socket, endpoint);
+ * @endcode
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename SocketService>
+ void accept(basic_socket_ext_local<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ void accept(basic_socket_ext_local<protocol_type>& peer, endpoint_type& peer_endpoint)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ boost::system::error_code ec;
+ this->get_service().accept(this->get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename SocketService>
+ BOOST_ASIO_SYNC_OP_VOID accept(
+ basic_socket_ext_local<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local<protocol_type>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ this->get_service().accept(
+ this->get_implementation(), peer, &peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket, and additionally obtain the endpoint of the remote peer. The
+ * function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename SocketService, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<protocol_type>& peer,
+ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a AcceptHandler.
+ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(), peer,
+ &peer_endpoint, BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<AcceptHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ peer, &peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ typename Protocol::socket accept()
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(
+ this->get_implementation(), 0, 0, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(), 0, 0, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_accept(accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(
+ this->get_implementation(), static_cast<boost::asio::io_context*>(0),
+ static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(
+ this->get_implementation(), static_cast<boost::asio::io_context*>(0),
+ static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::asio::io_context& io_context)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(io_context2, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ boost::asio::io_context& io_context, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_accept(io_context2, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(boost::asio::io_context& io_context,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint));
+ * @endcode
+ */
+ typename Protocol::socket accept(endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint,
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(io_context2, endpoint));
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ boost::asio::io_context& io_context, endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ &io_context, &peer_endpoint, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(io_context2, endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::asio::io_context& io_context,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ &io_context, &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(io_context2, endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(boost::asio::io_context& io_context,
+ endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(
+ this->get_implementation(), &io_context, &peer_endpoint,
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ &io_context, &peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/basic_socket_ext.hpp b/implementation/helper/1.66/boost/asio/basic_socket_ext.hpp
new file mode 100644
index 0000000..cdf4029
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/basic_socket_ext.hpp
@@ -0,0 +1,1760 @@
+//
+// basic_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_ssocket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol>
+# elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol>
+# else
+# include <boost/asio/detail/reactive_socket_service_ext.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_socket_service_ext<Protocol>
+# endif
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides socket functionality.
+/**
+ * The basic_socket class template provides functionality that is common to both
+ * stream-oriented and datagram-oriented sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_socket_ext
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// A basic_socket is always the lowest layer.
+ typedef basic_socket_ext<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_socket_ext(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(boost::asio::io_context& io_context,
+ const endpoint_type& endpoint)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket from another.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ basic_socket_ext(basic_socket_ext&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_socket from another.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ basic_socket_ext& operator=(basic_socket_ext&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+
+ // All sockets have access to each other's implementations.
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ friend class basic_socket;
+
+ /// Move-construct a basic_socket from a socket of another protocol type.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_socket_ext(basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_io_object<BOOST_ASIO_SVC_T>(
+ other.get_service(), other.get_implementation())
+ {
+ }
+
+ /// Move-assign a basic_socket from a socket of another protocol type.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_socket_ext>::type& operator=(
+ basic_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
+ {
+ basic_socket_ext tmp(std::move(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Get a const reference to the lowest layer.
+ /**
+ * This function returns a const reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A const reference to the lowest layer in the stack of layers.
+ * Ownership is not transferred to the caller.
+ */
+ const lowest_layer_type& lowest_layer() const
+ {
+ return *this;
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::system::error_code ec;
+ * socket.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_socket, boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = this->get_service().release(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return this->get_service().release(this->get_implementation(), ec);
+ }
+
+ /// Get the native socket representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * socket. This is intended to allow access to native socket functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ bool at_mark() const
+ {
+ boost::system::error_code ec;
+ bool b = this->get_service().at_mark(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "at_mark");
+ return b;
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ */
+ bool at_mark(boost::system::error_code& ec) const
+ {
+ return this->get_service().at_mark(this->get_implementation(), ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t available() const
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().available(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "available");
+ return s;
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ */
+ std::size_t available(boost::system::error_code& ec) const
+ {
+ return this->get_service().available(this->get_implementation(), ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.connect(endpoint);
+ * @endcode
+ */
+ void connect(const endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ if (!is_open())
+ {
+ this->get_service().open(this->get_implementation(),
+ peer_endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+ this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * boost::system::error_code ec;
+ * socket.connect(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ if (!is_open())
+ {
+ this->get_service().open(this->get_implementation(),
+ peer_endpoint.protocol(), ec);
+ if (ec)
+ {
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+ }
+
+ this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous connect.
+ /**
+ * This function is used to asynchronously connect a socket to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected. Copies will be made of the endpoint object as required.
+ *
+ * @param handler The handler to be called when the connection operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void connect_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Connect succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_connect(endpoint, connect_handler);
+ * @endcode
+ */
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ConnectHandler.
+ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
+
+ if (!is_open())
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = peer_endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ if (ec)
+ {
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ boost::asio::post(this->get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(
+ ConnectHandler, void (boost::system::error_code)))(
+ init.completion_handler), ec));
+
+ return init.result.get();
+ }
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_connect(this->get_implementation(),
+ peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_connect(
+ this->get_implementation(), peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * boost::system::error_code ec;
+ * socket.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * boost::system::error_code ec;
+ * socket.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ /**
+ * @returns @c true if the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return this->get_service().non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native socket. This mode has no effect on the behaviour of the socket
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying socket is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the socket object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native socket.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ bool native_non_blocking() const
+ {
+ return this->get_service().native_non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().local_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().local_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
+ * @endcode
+ */
+ endpoint_type remote_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().remote_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "remote_endpoint");
+ return ep;
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type remote_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().remote_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
+ * @endcode
+ */
+ void shutdown(shutdown_type what)
+ {
+ boost::system::error_code ec;
+ this->get_service().shutdown(this->get_implementation(), what, ec);
+ boost::asio::detail::throw_error(ec, "shutdown");
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
+ boost::system::error_code& ec)
+ {
+ this->get_service().shutdown(this->get_implementation(), what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ w, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_socket_ext()
+ {
+ }
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED;
+ basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/basic_socket_ext_local.hpp b/implementation/helper/1.66/boost/asio/basic_socket_ext_local.hpp
new file mode 100644
index 0000000..e13154c
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/basic_socket_ext_local.hpp
@@ -0,0 +1,1760 @@
+//
+// basic_socket_ext_local.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
+#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_ssocket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol>
+# elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol>
+# else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_socket_service_ext_local<Protocol>
+# endif
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides socket functionality.
+/**
+ * The basic_socket class template provides functionality that is common to both
+ * stream-oriented and datagram-oriented sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_socket_ext_local
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// A basic_socket is always the lowest layer.
+ typedef basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_socket_ext_local(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(boost::asio::io_context& io_context,
+ const protocol_type& protocol)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(boost::asio::io_context& io_context,
+ const endpoint_type& endpoint)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param io_context The io_context object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(boost::asio::io_context& io_context,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket from another.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ basic_socket_ext_local(basic_socket_ext_local&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_socket from another.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ basic_socket_ext_local& operator=(basic_socket_ext_local&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+
+ // All sockets have access to each other's implementations.
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ friend class basic_socket;
+
+ /// Move-construct a basic_socket from a socket of another protocol type.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_socket_ext_local(basic_socket_ext_local<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_io_object<BOOST_ASIO_SVC_T>(
+ other.get_service(), other.get_implementation())
+ {
+ }
+
+ /// Move-assign a basic_socket from a socket of another protocol type.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_socket_ext_local>::type& operator=(
+ basic_socket_ext_local<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
+ {
+ basic_socket_ext_local tmp(std::move(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Get a const reference to the lowest layer.
+ /**
+ * This function returns a const reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A const reference to the lowest layer in the stack of layers.
+ * Ownership is not transferred to the caller.
+ */
+ const lowest_layer_type& lowest_layer() const
+ {
+ return *this;
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::system::error_code ec;
+ * socket.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_socket, boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(),
+ protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = this->get_service().release(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return this->get_service().release(this->get_implementation(), ec);
+ }
+
+ /// Get the native socket representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * socket. This is intended to allow access to native socket functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ bool at_mark() const
+ {
+ boost::system::error_code ec;
+ bool b = this->get_service().at_mark(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "at_mark");
+ return b;
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ */
+ bool at_mark(boost::system::error_code& ec) const
+ {
+ return this->get_service().at_mark(this->get_implementation(), ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t available() const
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().available(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "available");
+ return s;
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ */
+ std::size_t available(boost::system::error_code& ec) const
+ {
+ return this->get_service().available(this->get_implementation(), ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.connect(endpoint);
+ * @endcode
+ */
+ void connect(const endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ if (!is_open())
+ {
+ this->get_service().open(this->get_implementation(),
+ peer_endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+ this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * boost::system::error_code ec;
+ * socket.connect(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ if (!is_open())
+ {
+ this->get_service().open(this->get_implementation(),
+ peer_endpoint.protocol(), ec);
+ if (ec)
+ {
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+ }
+
+ this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous connect.
+ /**
+ * This function is used to asynchronously connect a socket to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected. Copies will be made of the endpoint object as required.
+ *
+ * @param handler The handler to be called when the connection operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void connect_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Connect succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_connect(endpoint, connect_handler);
+ * @endcode
+ */
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ConnectHandler.
+ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
+
+ if (!is_open())
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = peer_endpoint.protocol();
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ if (ec)
+ {
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ boost::asio::post(this->get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(
+ ConnectHandler, void (boost::system::error_code)))(
+ init.completion_handler), ec));
+
+ return init.result.get();
+ }
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_connect(this->get_implementation(),
+ peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_connect(
+ this->get_implementation(), peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * boost::system::error_code ec;
+ * socket.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * boost::system::error_code ec;
+ * socket.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ /**
+ * @returns @c true if the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return this->get_service().non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native socket. This mode has no effect on the behaviour of the socket
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying socket is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the socket object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native socket.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ bool native_non_blocking() const
+ {
+ return this->get_service().native_non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().local_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().local_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
+ * @endcode
+ */
+ endpoint_type remote_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->get_service().remote_endpoint(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "remote_endpoint");
+ return ep;
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type remote_endpoint(boost::system::error_code& ec) const
+ {
+ return this->get_service().remote_endpoint(this->get_implementation(), ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
+ * @endcode
+ */
+ void shutdown(shutdown_type what)
+ {
+ boost::system::error_code ec;
+ this->get_service().shutdown(this->get_implementation(), what, ec);
+ boost::asio::detail::throw_error(ec, "shutdown");
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
+ boost::system::error_code& ec)
+ {
+ this->get_service().shutdown(this->get_implementation(), what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ w, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_socket_ext_local()
+ {
+ }
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_ext_local(const basic_socket_ext_local&) BOOST_ASIO_DELETED;
+ basic_socket_ext_local& operator=(const basic_socket_ext_local&) BOOST_ASIO_DELETED;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.66/boost/asio/basic_stream_socket_ext.hpp
new file mode 100644
index 0000000..99d29c3
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/basic_stream_socket_ext.hpp
@@ -0,0 +1,924 @@
+//
+// basic_stream_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_socket_ext_local.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/stream_socket_service_ext.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides stream-oriented socket functionality.
+/**
+ * The basic_stream_socket_ext class template provides asynchronous and blocking
+ * stream-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service_ext<Protocol>)>
+class basic_stream_socket_ext
+ : public basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>
+{
+public:
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket_ext_local<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_stream_socket_ext without opening it.
+ /**
+ * This constructor creates a stream socket without opening it. The socket
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param io_context The io_context object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_stream_socket_ext(boost::asio::io_context& io_context)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(io_context)
+ {
+ }
+
+ /// Construct and open a basic_stream_socket_ext.
+ /**
+ * This constructor creates and opens a stream socket. The socket needs to be
+ * connected or accepted before data can be sent or received on it.
+ *
+ * @param io_context The io_context object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
+ {
+ }
+
+ /// Construct a basic_stream_socket_ext, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a stream socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_context The io_context object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the stream
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_context& io_context,
+ const endpoint_type& endpoint)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
+ {
+ }
+
+ /// Construct a basic_stream_socket_ext on an existing native socket.
+ /**
+ * This constructor creates a stream socket object to hold an existing native
+ * socket.
+ *
+ * @param io_context The io_context object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(boost::asio::io_context& io_context,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_stream_socket_ext from another.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_context&) constructor.
+ */
+ basic_stream_socket_ext(basic_stream_socket_ext&& other)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket_ext from another.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_context&) constructor.
+ */
+ basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other)
+ {
+ basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_stream_socket_ext from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_stream_socket_ext(
+ basic_stream_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
+ typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
+ : basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket_ext from a socket of another protocol type.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket_ext object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket_ext(io_context&) constructor.
+ */
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ typename enable_if<is_convertible<Protocol1, Protocol>::value,
+ basic_stream_socket_ext>::type& operator=(
+ basic_stream_socket_ext<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
+ {
+ basic_socket_ext_local<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_stream_socket_ext()
+ {
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent. Returns 0 if an error occurred.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().send(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send(
+ this->get_implementation(), buffers, 0,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(
+ this->get_implementation(), buffers, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send(
+ this->get_implementation(), buffers, flags,
+ BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(
+ this->get_implementation(), buffers, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received. Returns 0 if an error occurred.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().send(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().send(this->get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_send(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().receive(
+ this->get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext.hpp
new file mode 100644
index 0000000..89f1594
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext.hpp
@@ -0,0 +1,565 @@
+//
+// detail/handler_type_requirements_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/async_result.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_copyable_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_copyable_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2, *a3)),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3 *a3)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3))),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_move_handler_test(Handler, ...))[2];
+
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+#if defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> T rvref();
+template <typename T> T rvref(T);
+#else // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> const T& rvref();
+template <typename T> const T& rvref(T);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ boost::asio::ip::address)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::three_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const boost::asio::ip::address*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const boost::asio::ip::address>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#if 0
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, socket_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_move_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<socket_type*>(0))) == 1, \
+ "MoveAcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::rvref<socket_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+#endif
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, endpoint_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, endpoint_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const endpoint_type*>(0))) == 1, \
+ "RangeConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const endpoint_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "IteratorConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, range_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, range_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const range_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const range_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext_local.hpp
new file mode 100644
index 0000000..e12b1ca
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/handler_type_requirements_ext_local.hpp
@@ -0,0 +1,592 @@
+//
+// detail/handler_type_requirements_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/async_result.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_copyable_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_copyable_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2, *a3, *a4)),
+ char(0));
+
+template <typename Handler>
+char (&four_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+auto four_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3), BOOST_ASIO_MOVE_CAST(Arg4)(*a4))),
+ char(0));
+
+template <typename Handler>
+char (&four_arg_move_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+#if defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> T rvref();
+template <typename T> T rvref(T);
+#else // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> const T& rvref();
+template <typename T> const T& rvref(T);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ std::uint32_t, \
+ std::uint32_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::four_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const std::uint32_t*>(0), \
+ static_cast<const std::uint32_t*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, socket_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_move_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<socket_type*>(0))) == 1, \
+ "MoveAcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::rvref<socket_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, endpoint_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, endpoint_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const endpoint_type*>(0))) == 1, \
+ "RangeConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const endpoint_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "IteratorConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, range_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, range_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const range_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const range_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "BufferedHandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
new file mode 100644
index 0000000..6219e1f
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
@@ -0,0 +1,302 @@
+//
+// detail/reactive_socket_service_base_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext::reactive_socket_service_base_ext(
+ boost::asio::io_context& io_context)
+ : io_context_(io_context), reactor_(use_service<reactor>(io_context))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext::base_shutdown()
+{
+}
+
+void reactive_socket_service_base_ext::construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext::base_move_construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::base_move_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::destroy(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext::close(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+/*
+socket_type reactive_socket_service_base::release(
+ reactive_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "release"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ socket_type sock = impl.socket_;
+ construct(impl);
+ ec = boost::system::error_code();
+ return sock;
+}
+*/
+boost::system::error_code reactive_socket_service_base_ext::cancel(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_open(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext::start_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext::start_accept_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, is_continuation, true, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext::start_connect_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
diff --git a/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
new file mode 100644
index 0000000..02a628b
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
@@ -0,0 +1,302 @@
+//
+// detail/reactive_socket_service_base_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local(
+ boost::asio::io_context& io_context)
+ : io_context_(io_context), reactor_(use_service<reactor>(io_context))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext_local::base_shutdown()
+{
+}
+
+void reactive_socket_service_base_ext_local::construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext_local::base_move_construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::base_move_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::destroy(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::close(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+/*
+socket_type reactive_socket_service_base::release(
+ reactive_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "release"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ socket_type sock = impl.socket_;
+ construct(impl);
+ ec = boost::system::error_code();
+ return sock;
+}
+*/
+boost::system::error_code reactive_socket_service_base_ext_local::cancel(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_open(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext_local::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext_local::start_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext_local::start_accept_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, is_continuation, true, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext_local::start_connect_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
diff --git a/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext.ipp
new file mode 100644
index 0000000..633d24e
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext.ipp
@@ -0,0 +1,210 @@
+//
+// detail/impl/socket_ops_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
+ LPFN_WSARECVMSG WSARecvMsg;
+ DWORD NumberOfBytes;
+
+ error_wrapper(WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
+ &WSARecvMsg, sizeof WSARecvMsg,
+ &NumberOfBytes, NULL, NULL), ec);
+ if (ec.value() == SOCKET_ERROR) {
+ WSARecvMsg = NULL;
+ return 0;
+ }
+
+ WSABUF wsaBuf;
+ WSAMSG msg;
+ char controlBuffer[1024];
+ msg.name = addr;
+ msg.namelen = *addrlen;
+ wsaBuf.buf = bufs->buf;
+ wsaBuf.len = bufs->len;
+ msg.lpBuffers = &wsaBuf;
+ msg.dwBufferCount = count;
+ msg.Control.len = sizeof controlBuffer;
+ msg.Control.buf = controlBuffer;
+ msg.dwFlags = flags;
+
+ DWORD dwNumberOfBytesRecvd;
+ signed_size_type result = error_wrapper(WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL), ec);
+
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ } else {
+ dwNumberOfBytesRecvd = -1;
+ }
+ return dwNumberOfBytesRecvd;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ char cmbuf[0x100];
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+ msg.msg_control = cmbuf;
+ msg.msg_controllen = sizeof(cmbuf);
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
diff --git a/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext_local.ipp
new file mode 100644
index 0000000..2a066b8
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/impl/socket_ops_ext_local.ipp
@@ -0,0 +1,302 @@
+//
+// detail/impl/socket_ops_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recv(socket_type s, buf* bufs, size_t count,
+ int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = error_wrapper(::WSARecv(s, bufs,
+ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int tmp_addrlen = (int)*addrlen;
+ int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+ *addrlen = (std::size_t)tmp_addrlen;
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid);
+
+ // Check for end of stream.
+ if (is_stream && bytes == 0)
+ {
+ ec = boost::asio::error::eof;
+ return true;
+ }
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext.hpp
new file mode 100644
index 0000000..4f78284
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext.hpp
@@ -0,0 +1,138 @@
+//
+// detail/reactive_socket_recv_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recv_op_base_ext(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recv_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext* o(
+ static_cast<reactive_socket_recv_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ == 0)
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op_ext :
+ public reactive_socket_recv_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext);
+
+ reactive_socket_recv_op_ext(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recv_op_base_ext<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext* o(static_cast<reactive_socket_recv_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
new file mode 100644
index 0000000..994a495
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
@@ -0,0 +1,138 @@
+//
+// detail/reactive_socket_recv_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recv_op_base_ext_local(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recv_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext_local* o(
+ static_cast<reactive_socket_recv_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ == 0)
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op_ext_local :
+ public reactive_socket_recv_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local);
+
+ reactive_socket_recv_op_ext_local(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recv_op_base_ext_local<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext_local* o(static_cast<reactive_socket_recv_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
new file mode 100644
index 0000000..969e8ab
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
@@ -0,0 +1,141 @@
+//
+// detail/reactive_socket_recvfrom_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvfrom_op_base_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvfrom_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ status result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->da_) ? done : not_done;
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op_ext :
+ public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext);
+
+ reactive_socket_recvfrom_op_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext* o(
+ static_cast<reactive_socket_recvfrom_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
new file mode 100644
index 0000000..a8a2af7
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
@@ -0,0 +1,141 @@
+//
+// detail/reactive_socket_recvfrom_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ status result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done;
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op_ext_local :
+ public reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local);
+
+ reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ : reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
new file mode 100644
index 0000000..0efd6c3
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
@@ -0,0 +1,135 @@
+//
+// detail/reactive_socket_recvmsg_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvmsg_op_base_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recvmsg_op_ext :
+ public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext);
+
+ reactive_socket_recvmsg_op_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ : reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext* o(
+ static_cast<reactive_socket_recvmsg_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
new file mode 100644
index 0000000..c992283
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
@@ -0,0 +1,135 @@
+//
+// detail/reactive_socket_recvmsg_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvmsg_op_base_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recvmsg_op_ext_local :
+ public reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local);
+
+ reactive_socket_recvmsg_op_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ : reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext.hpp
new file mode 100644
index 0000000..b6a80bd
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext.hpp
@@ -0,0 +1,517 @@
+//
+// detail/reactive_socket_service_base_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext(
+ boost::asio::io_context& io_context);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void base_shutdown();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ switch (w)
+ {
+ case socket_base::wait_read:
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_write:
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_error:
+ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
+ break;
+ default:
+ ec = boost::asio::error::invalid_argument;
+ break;
+ }
+
+ return ec;
+ }
+
+ // Asynchronously wait for the socket to become ready to read, ready to
+ // write, or to have pending error conditions.
+ template <typename Handler>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ int op_type;
+ switch (w)
+ {
+ case socket_base::wait_read:
+ op_type = reactor::read_op;
+ break;
+ case socket_base::wait_write:
+ op_type = reactor::write_op;
+ break;
+ case socket_base::wait_error:
+ op_type = reactor::except_op;
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ boost_asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
+ "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The io_context that owns this socket service
+ io_context& io_context_;
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
new file mode 100644
index 0000000..e233574
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
@@ -0,0 +1,514 @@
+//
+// detail/reactive_socket_service_base_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext_local
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext_local(
+ boost::asio::io_context& io_context);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void base_shutdown();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ switch (w)
+ {
+ case socket_base::wait_read:
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_write:
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_error:
+ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
+ break;
+ default:
+ ec = boost::asio::error::invalid_argument;
+ break;
+ }
+
+ return ec;
+ }
+
+ // Asynchronously wait for the socket to become ready to read, ready to
+ // write, or to have pending error conditions.
+ template <typename Handler>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ int op_type;
+ switch (w)
+ {
+ case socket_base::wait_read:
+ op_type = reactor::read_op;
+ break;
+ case socket_base::wait_write:
+ op_type = reactor::write_op;
+ break;
+ case socket_base::wait_error:
+ op_type = reactor::except_op;
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext_local<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext_local<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The io_context that owns this socket service.
+ io_context& io_context_;
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext.hpp
new file mode 100644
index 0000000..761f2bb
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext.hpp
@@ -0,0 +1,531 @@
+//
+// detail/reactive_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <iostream>
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext :
+ public service_base<reactive_socket_service_ext<Protocol> >,
+ public reactive_socket_service_base_ext
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext(boost::asio::io_context& io_context)
+ : service_base<reactive_socket_service_ext<Protocol> >(io_context),
+ reactive_socket_service_base_ext(io_context)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service
+ void shutdown()
+ {
+ this->base_shutdown();
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ reactive_socket_service_ext<Protocol>&,
+ typename reactive_socket_service_ext<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext<MutableBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol,
+ buffers, sender_endpoint, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Accept a new connection.
+ typename Protocol::socket accept(implementation_type& impl,
+ io_context* peer_io_context, endpoint_type* peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(
+ peer_io_context ? *peer_io_context : io_context_);
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return peer;
+ }
+ #endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects must be
+ // valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer_endpoint object must be valid until
+ // the accept's handler is invoked.
+ template <typename Handler>
+ void async_accept(implementation_type& impl,
+ boost::asio::io_context* peer_io_context,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_move_accept_op<Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_,
+ impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, false);
+ p.v = p.p = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext_local.hpp
new file mode 100644
index 0000000..a946851
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactive_socket_service_ext_local.hpp
@@ -0,0 +1,529 @@
+//
+// detail/reactive_socket_service_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext_local :
+ public service_base<reactive_socket_service_ext_local<Protocol> >,
+ public reactive_socket_service_base_ext_local
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext_local::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext_local(boost::asio::io_context& io_context)
+ : service_base<reactive_socket_service_ext_local<Protocol> >(io_context),
+ reactive_socket_service_base_ext_local(io_context)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown()
+ {
+ this->base_shutdown();
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ reactive_socket_service_ext_local<Protocol1>&,
+ typename reactive_socket_service_ext_local<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext_local<MutableBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol,
+ buffers, sender_endpoint, flags, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Accept a new connection.
+ typename Protocol::socket accept(implementation_type& impl,
+ io_context* peer_io_context, endpoint_type* peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(
+ peer_io_context ? *peer_io_context : io_context_);
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return peer;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects must be
+ // valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer_endpoint object must be valid until
+ // the accept's handler is invoked.
+ template <typename Handler>
+ void async_accept(implementation_type& impl,
+ boost::asio::io_context* peer_io_context,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_move_accept_op<Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_,
+ impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, false);
+ p.v = p.p = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.66/boost/asio/detail/reactor_op_ext.hpp
new file mode 100644
index 0000000..04c2c70
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactor_op_ext.hpp
@@ -0,0 +1,42 @@
+//
+// detail/reactor_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext
+ : public reactor_op
+{
+public:
+ // The destination address
+ boost::asio::ip::address da_;
+
+ reactor_op_ext(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/reactor_op_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/reactor_op_ext_local.hpp
new file mode 100644
index 0000000..3a27272
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/reactor_op_ext_local.hpp
@@ -0,0 +1,47 @@
+//
+// detail/reactor_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext_local
+ : public reactor_op
+{
+public:
+
+ // The passed credentials
+ std::uint32_t uid_;
+ std::uint32_t gid_;
+
+ reactor_op_ext_local(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/1.66/boost/asio/detail/socket_ops_ext.hpp
new file mode 100644
index 0000000..cc28d9c
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/socket_ops_ext.hpp
@@ -0,0 +1,62 @@
+//
+// detail/socket_ops_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/socket_ops.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ boost::asio::ip::address& da);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/implementation/helper/1.66/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.66/boost/asio/detail/socket_ops_ext_local.hpp
new file mode 100644
index 0000000..e08a643
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/detail/socket_ops_ext_local.hpp
@@ -0,0 +1,95 @@
+//
+// detail/socket_ops_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs,
+ size_t count, int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, bool all_empty, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recv(state_type state,
+ const weak_cancel_token_type& cancel_token, bool all_empty,
+ boost::system::error_code& ec, size_t bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.66/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.66/boost/asio/ip/udp_ext.hpp
new file mode 100644
index 0000000..6ce2ac4
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/ip/udp_ext.hpp
@@ -0,0 +1,115 @@
+//
+// ip/udp_ext.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_UDP_EXT_HPP
+#define BOOST_ASIO_IP_UDP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_datagram_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/udp.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for UDP.
+/**
+ * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class udp_ext
+{
+public:
+ /// The type of a UDP endpoint.
+ typedef basic_endpoint<udp> endpoint;
+
+ /// Construct to represent the IPv4 UDP protocol.
+ static udp_ext v4()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET));
+ }
+
+ /// Construct to represent the IPv6 UDP protocol.
+ static udp_ext v6()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6));
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return BOOST_ASIO_OS_DEF(SOCK_DGRAM);
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return BOOST_ASIO_OS_DEF(IPPROTO_UDP);
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The UDP socket type.
+ typedef basic_datagram_socket_ext<udp> socket;
+
+ /// The UDP resolver type.
+ typedef basic_resolver<udp> resolver;
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit udp_ext(int protocol_family)
+ : family_(protocol_family)
+ {
+ }
+
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_UDP_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.66/boost/asio/local/stream_protocol_ext.hpp
new file mode 100644
index 0000000..6ccd0ad
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/local/stream_protocol_ext.hpp
@@ -0,0 +1,93 @@
+//
+// local/stream_protocol_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/basic_socket_acceptor_ext.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_stream_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Encapsulates the flags needed for stream-oriented UNIX sockets.
+/**
+ * The boost::asio::local::stream_protocol class contains flags necessary for
+ * stream-oriented UNIX domain sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol.
+ */
+class stream_protocol_ext
+{
+public:
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_STREAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return 0;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return AF_UNIX;
+ }
+
+ /// The type of a UNIX domain endpoint.
+ typedef basic_endpoint<stream_protocol_ext> endpoint;
+
+ /// The UNIX domain socket type.
+ typedef basic_stream_socket_ext<stream_protocol_ext> socket;
+
+ /// The UNIX domain acceptor type.
+ typedef basic_socket_acceptor_ext<stream_protocol_ext> acceptor;
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+ /// The UNIX domain iostream type.
+ typedef basic_socket_iostream<stream_protocol_ext> iostream;
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+};
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
diff --git a/implementation/helper/1.66/boost/asio/stream_socket_service_ext.hpp b/implementation/helper/1.66/boost/asio/stream_socket_service_ext.hpp
new file mode 100644
index 0000000..ff5c5f8
--- /dev/null
+++ b/implementation/helper/1.66/boost/asio/stream_socket_service_ext.hpp
@@ -0,0 +1,415 @@
+//
+// stream_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
+#define BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_ssocket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a stream socket.
+template <typename Protocol>
+class stream_socket_service_ext
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_context::service
+#else
+ : public boost::asio::detail::service_base<stream_socket_service_ext<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_context::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef detail::winrt_ssocket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#else
+ typedef detail::reactive_socket_service_ext_local<Protocol> service_impl_type;
+#endif
+
+public:
+ /// The type of a stream socket implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename service_impl_type::native_handle_type native_handle_type;
+#endif
+
+ /// Construct a new stream socket service for the specified io_context.
+ explicit stream_socket_service_ext(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<
+ stream_socket_service_ext<Protocol> >(io_context),
+ service_impl_(io_context)
+ {
+ }
+
+ /// Construct a new stream socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new stream socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another stream socket implementation.
+ void move_assign(implementation_type& impl,
+ stream_socket_service_ext& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+
+ // All socket services have access to each other's implementations.
+ template <typename Protocol1> friend class stream_socket_service_ext;
+
+ /// Move-construct a new stream socket implementation from another protocol
+ /// type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ stream_socket_service_ext<Protocol1>& other_service,
+ typename stream_socket_service_ext<
+ Protocol1>::implementation_type& other_impl,
+ typename enable_if<is_convertible<
+ Protocol1, Protocol>::value>::type* = 0)
+ {
+ service_impl_.template converting_move_construct<Protocol1>(
+ impl, other_service.service_impl_, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroy a stream socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a stream socket.
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_STREAM))
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native socket to a stream socket.
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ service_impl_.assign(impl, protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a stream socket implementation.
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying socket.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.release(impl, ec);
+ }
+
+ /// Get the native socket implementation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return service_impl_.native_handle(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ /// Bind the stream socket to the specified local endpoint.
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Connect the stream socket to the specified endpoint.
+ BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ service_impl_.connect(impl, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ bool non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const implementation_type& impl) const
+ {
+ return service_impl_.native_non_blocking(impl);
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ service_impl_.shutdown(impl, what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ service_impl_.async_send(impl, buffers, flags, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ service_impl_.async_receive(impl, buffers, flags, init.completion_handler);
+
+ return init.result.get();
+ }
+
+private:
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown()
+ {
+ service_impl_.shutdown();
+ }
+
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/basic_datagram_socket_ext.hpp b/implementation/helper/1.70/boost/asio/basic_datagram_socket_ext.hpp
new file mode 100644
index 0000000..58a553f
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/basic_datagram_socket_ext.hpp
@@ -0,0 +1,1118 @@
+//
+// basic_datagram_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/basic_socket_ext.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL)
+#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol, typename Executor = executor>
+class basic_datagram_socket_ext;
+
+#endif // !defined(BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_FWD_DECL)
+
+/// Provides datagram-oriented socket functionality.
+/**
+ * The basic_datagram_socket class template provides asynchronous and blocking
+ * datagram-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol, typename Executor>
+class basic_datagram_socket_ext
+ : public basic_socket_ext<Protocol, Executor>
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef Executor executor_type;
+
+ /// Rebinds the socket type to another executor.
+ template <typename Executor1>
+ struct rebind_executor
+ {
+ /// The socket type when rebound to the specified executor.
+ typedef basic_datagram_socket_ext<Protocol, Executor1> other;
+ };
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket_ext<Protocol,
+ Executor>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_datagram_socket without opening it.
+ /**
+ * This constructor creates a datagram socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_datagram_socket_ext(const executor_type& ex)
+ : basic_socket_ext<Protocol, Executor>(ex)
+ {
+ }
+
+ /// Construct a basic_datagram_socket without opening it.
+ /**
+ * This constructor creates a datagram socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ */
+ template <typename ExecutionContext>
+ explicit basic_datagram_socket_ext(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext<Protocol, Executor>(context)
+ {
+ }
+
+ /// Construct and open a basic_datagram_socket.
+ /**
+ * This constructor creates and opens a datagram socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(const executor_type& ex, const protocol_type& protocol)
+ : basic_socket_ext<Protocol, Executor>(ex, protocol)
+ {
+ }
+
+ /// Construct and open a basic_datagram_socket.
+ /**
+ * This constructor creates and opens a datagram socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_datagram_socket_ext(ExecutionContext& context,
+ const protocol_type& protocol,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext<Protocol, Executor>(context, protocol)
+ {
+ }
+
+ /// Construct a basic_datagram_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a datagram socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the datagram
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(const executor_type& ex, const endpoint_type& endpoint)
+ : basic_socket_ext<Protocol, Executor>(ex, endpoint)
+ {
+ }
+
+ /// Construct a basic_datagram_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a datagram socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the datagram
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_datagram_socket_ext(ExecutionContext& context,
+ const endpoint_type& endpoint,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext<Protocol, Executor>(context, endpoint)
+ {
+ }
+
+ /// Construct a basic_datagram_socket on an existing native socket.
+ /**
+ * This constructor creates a datagram socket object to hold an existing
+ * native socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket_ext(const executor_type& ex,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket_ext<Protocol, Executor>(ex, protocol, native_socket)
+ {
+ }
+
+ /// Construct a basic_datagram_socket on an existing native socket.
+ /**
+ * This constructor creates a datagram socket object to hold an existing
+ * native socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_datagram_socket_ext(ExecutionContext& context,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext<Protocol, Executor>(context, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_datagram_socket from another.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(const executor_type&)
+ * constructor.
+ */
+ basic_datagram_socket_ext(basic_datagram_socket_ext&& other)
+ : basic_socket_ext<Protocol, Executor>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from another.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(const executor_type&)
+ * constructor.
+ */
+ basic_datagram_socket_ext& operator=(basic_datagram_socket_ext&& other)
+ {
+ basic_socket_ext<Protocol, Executor>::operator=(std::move(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a datagram socket from one object to another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ basic_datagram_socket_ext(basic_datagram_socket_ext<Protocol1, Executor1>&& other,
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value
+ >::type* = 0)
+ : basic_socket_ext<Protocol, Executor>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_datagram_socket from a socket of another protocol
+ /// type.
+ /**
+ * This assignment operator moves a datagram socket from one object to
+ * another.
+ *
+ * @param other The other basic_datagram_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_datagram_socket(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value,
+ basic_datagram_socket_ext&
+ >::type operator=(basic_datagram_socket_ext<Protocol1, Executor1>&& other)
+ {
+ basic_socket_ext<Protocol, Executor>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_datagram_socket_ext()
+ {
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code socket.send(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to asynchronously send data on the datagram socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send(), handler, this, buffers, flags);
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.send_to(boost::asio::buffer(data, size), destination);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send_to(
+ this->impl_.get_implementation(), buffers, destination, 0, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send_to(
+ this->impl_.get_implementation(), buffers, destination, flags, ec);
+ boost::asio::detail::throw_error(ec, "send_to");
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().send_to(this->impl_.get_implementation(),
+ buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_send_to(
+ * boost::asio::buffer(data, size), destination, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send_to(), handler, this, buffers,
+ destination, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send_to(), handler, this, buffers, destination, flags);
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.receive(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
+ initiate_async_receive(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
+ initiate_async_receive(), handler, this, buffers, flags);
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * boost::asio::ip::udp::endpoint sender_endpoint;
+ * socket.receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive_from(
+ this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive_from(
+ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive_from");
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().receive_from(
+ this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.async_receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
+ initiate_async_receive_from(), handler, this, buffers,
+ &sender_endpoint, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address))
+ async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, boost::asio::ip::address)>(
+ initiate_async_receive_from(), handler,
+ this, buffers, &sender_endpoint, flags);
+ }
+
+private:
+ struct initiate_async_send
+ {
+ template <typename WriteHandler, typename ConstBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ detail::non_const_lvalue<WriteHandler> handler2(handler);
+ self->impl_.get_service().async_send(
+ self->impl_.get_implementation(), buffers, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_send_to
+ {
+ template <typename WriteHandler, typename ConstBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ basic_datagram_socket_ext* self, const ConstBufferSequence& buffers,
+ const endpoint_type& destination,
+ socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ detail::non_const_lvalue<WriteHandler> handler2(handler);
+ self->impl_.get_service().async_send_to(
+ self->impl_.get_implementation(), buffers, destination, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_receive
+ {
+ template <typename ReadHandler, typename MutableBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ detail::non_const_lvalue<ReadHandler> handler2(handler);
+ self->impl_.get_service().async_receive(
+ self->impl_.get_implementation(), buffers, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_receive_from
+ {
+ template <typename ReadHandler, typename MutableBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ basic_datagram_socket_ext* self, const MutableBufferSequence& buffers,
+ endpoint_type* sender_endpoint, socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT(ReadHandler, handler) type_check;
+
+ detail::non_const_lvalue<ReadHandler> handler2(handler);
+ self->impl_.get_service().async_receive_from(
+ self->impl_.get_implementation(), buffers, *sender_endpoint, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/basic_socket_acceptor_ext.hpp b/implementation/helper/1.70/boost/asio/basic_socket_acceptor_ext.hpp
new file mode 100644
index 0000000..e3e2966
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/basic_socket_acceptor_ext.hpp
@@ -0,0 +1,2381 @@
+//
+// basic_socket_acceptor_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_socket_ext_local.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext.hpp>
+#include <boost/asio/detail/io_object_impl.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+#endif
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol, typename Executor = executor>
+class basic_socket_acceptor_ext;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_FWD_DECL)
+
+/// Provides the ability to accept new connections.
+/**
+ * The basic_socket_acceptor_ext class template is used for accepting new socket
+ * connections.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+template <typename Protocol, typename Executor>
+class basic_socket_acceptor_ext
+ : public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef Executor executor_type;
+
+ /// The native representation of an acceptor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef typename detail::null_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef typename detail::win_iocp_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#else
+ typedef typename detail::reactive_socket_service_ext_local<
+ Protocol>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct an acceptor without opening it.
+ /**
+ * This constructor creates an acceptor without opening it to listen for new
+ * connections. The open() function must be called before the acceptor can
+ * accept new socket connections.
+ *
+ * @param ex The I/O executor that the acceptor will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ */
+ explicit basic_socket_acceptor_ext(const executor_type& ex)
+ : impl_(ex)
+ {
+ }
+
+ /// Construct an acceptor without opening it.
+ /**
+ * This constructor creates an acceptor without opening it to listen for new
+ * connections. The open() function must be called before the acceptor can
+ * accept new socket connections.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the acceptor will use, by default, to dispatch handlers for any
+ * asynchronous operations performed on the acceptor.
+ */
+ template <typename ExecutionContext>
+ explicit basic_socket_acceptor_ext(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ }
+
+ /// Construct an open acceptor.
+ /**
+ * This constructor creates an acceptor and automatically opens it.
+ *
+ * @param ex The I/O executor that the acceptor will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(const executor_type& ex, const protocol_type& protocol)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct an open acceptor.
+ /**
+ * This constructor creates an acceptor and automatically opens it.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the acceptor will use, by default, to dispatch handlers for any
+ * asynchronous operations performed on the acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_acceptor_ext(ExecutionContext& context,
+ const protocol_type& protocol,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct an acceptor opened on the given endpoint.
+ /**
+ * This constructor creates an acceptor and automatically opens it to listen
+ * for new connections on the specified endpoint.
+ *
+ * @param ex The I/O executor that the acceptor will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param endpoint An endpoint on the local machine on which the acceptor
+ * will listen for new connections.
+ *
+ * @param reuse_addr Whether the constructor should set the socket option
+ * socket_base::reuse_address.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This constructor is equivalent to the following code:
+ * @code
+ * basic_socket_acceptor<Protocol> acceptor(my_context);
+ * acceptor.open(endpoint.protocol());
+ * if (reuse_addr)
+ * acceptor.set_option(socket_base::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+ basic_socket_acceptor_ext(const executor_type& ex,
+ const endpoint_type& endpoint, bool reuse_addr = true)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ if (reuse_addr)
+ {
+ impl_.get_service().set_option(impl_.get_implementation(),
+ socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ impl_.get_service().listen(impl_.get_implementation(),
+ socket_base::max_listen_connections, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Construct an acceptor opened on the given endpoint.
+ /**
+ * This constructor creates an acceptor and automatically opens it to listen
+ * for new connections on the specified endpoint.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the acceptor will use, by default, to dispatch handlers for any
+ * asynchronous operations performed on the acceptor.
+ *
+ * @param endpoint An endpoint on the local machine on which the acceptor
+ * will listen for new connections.
+ *
+ * @param reuse_addr Whether the constructor should set the socket option
+ * socket_base::reuse_address.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This constructor is equivalent to the following code:
+ * @code
+ * basic_socket_acceptor<Protocol> acceptor(my_context);
+ * acceptor.open(endpoint.protocol());
+ * if (reuse_addr)
+ * acceptor.set_option(socket_base::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+ template <typename ExecutionContext>
+ basic_socket_acceptor_ext(ExecutionContext& context,
+ const endpoint_type& endpoint, bool reuse_addr = true,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ if (reuse_addr)
+ {
+ impl_.get_service().set_option(impl_.get_implementation(),
+ socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ impl_.get_service().listen(impl_.get_implementation(),
+ socket_base::max_listen_connections, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Construct a basic_socket_acceptor on an existing native acceptor.
+ /**
+ * This constructor creates an acceptor object to hold an existing native
+ * acceptor.
+ *
+ * @param ex The I/O executor that the acceptor will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor_ext(const executor_type& ex,
+ const protocol_type& protocol, const native_handle_type& native_acceptor)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Construct a basic_socket_acceptor on an existing native acceptor.
+ /**
+ * This constructor creates an acceptor object to hold an existing native
+ * acceptor.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the acceptor will use, by default, to dispatch handlers for any
+ * asynchronous operations performed on the acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_acceptor_ext(ExecutionContext& context,
+ const protocol_type& protocol, const native_handle_type& native_acceptor,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket_acceptor from another.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor(const executor_type&)
+ * constructor.
+ */
+ basic_socket_acceptor_ext(basic_socket_acceptor_ext&& other)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket_acceptor from another.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor(const executor_type&)
+ * constructor.
+ */
+ basic_socket_acceptor_ext& operator=(basic_socket_acceptor_ext&& other)
+ {
+ impl_ = std::move(other.impl_);
+ return *this;
+ }
+
+ // All socket acceptors have access to each other's implementations.
+ template <typename Protocol1, typename Executor1>
+ friend class basic_socket_acceptor_ext;
+
+ /// Move-construct a basic_socket_acceptor from an acceptor of another
+ /// protocol type.
+ /**
+ * This constructor moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ basic_socket_acceptor_ext(basic_socket_acceptor_ext<Protocol1, Executor1>&& other,
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value
+ >::type* = 0)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket_acceptor from an acceptor of another protocol
+ /// type.
+ /**
+ * This assignment operator moves an acceptor from one object to another.
+ *
+ * @param other The other basic_socket_acceptor object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket_acceptor(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value,
+ basic_socket_acceptor_ext&
+ >::type operator=(basic_socket_acceptor_ext<Protocol1, Executor1>&& other)
+ {
+ basic_socket_acceptor_ext tmp(std::move(other));
+ impl_ = std::move(tmp.impl_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the acceptor.
+ /**
+ * This function destroys the acceptor, cancelling any outstanding
+ * asynchronous operations associated with the acceptor as if by calling
+ * @c cancel.
+ */
+ ~basic_socket_acceptor_ext()
+ {
+ }
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return impl_.get_executor();
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * boost::system::error_code ec;
+ * acceptor.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_acceptor, boost::system::error_code& ec)
+ {
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_acceptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open() const
+ {
+ return impl_.get_service().is_open(impl_.get_implementation());
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.bind(endpoint);
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
+ * acceptor.open(endpoint.protocol());
+ * boost::system::error_code ec;
+ * acceptor.bind(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void listen(int backlog = socket_base::max_listen_connections)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().listen(impl_.get_implementation(), backlog, ec);
+ boost::asio::detail::throw_error(ec, "listen");
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec)
+ {
+ impl_.get_service().listen(impl_.get_implementation(), backlog, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native acceptor.
+ /**
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = impl_.get_service().release(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native acceptor.
+ /**
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return impl_.get_service().release(impl_.get_implementation(), ec);
+ }
+
+ /// Get the native acceptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * acceptor. This is intended to allow access to native acceptor functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return impl_.get_service().native_handle(impl_.get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * boost::system::error_code ec;
+ * acceptor.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * acceptor.get_option(option);
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * boost::system::error_code ec;
+ * acceptor.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * socket.io_control(command);
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the acceptor.
+ /**
+ * This function is used to execute an IO control command on the acceptor.
+ *
+ * @param command The IO control command to be performed on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the acceptor.
+ /**
+ * @returns @c true if the acceptor's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return impl_.get_service().non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the acceptor.
+ /**
+ * @param mode If @c true, the acceptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native acceptor. This mode has no effect on the behaviour of the acceptor
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying acceptor is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the acceptor object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native acceptor.
+ */
+ bool native_non_blocking() const
+ {
+ return impl_.get_service().native_non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native acceptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native acceptor. It has no effect on the behaviour of the acceptor object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying acceptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = impl_.get_service().local_endpoint(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ * Returns a default-constructed endpoint object if an error occurred and the
+ * error handler did not throw an exception.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
+ }
+
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the acceptor to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for an acceptor to
+ * enter a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * acceptor.async_wait(
+ * boost::asio::ip::tcp::acceptor::wait_read,
+ * wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ return async_initiate<WaitHandler, void (boost::system::error_code)>(
+ initiate_async_wait(), handler, this, w);
+ }
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * acceptor.accept(socket);
+ * @endcode
+ */
+ template <typename Protocol1, typename Executor1>
+ void accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
+ typename enable_if<
+ is_convertible<Protocol, Protocol1>::value
+ >::type* = 0)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename Protocol1, typename Executor1>
+ BOOST_ASIO_SYNC_OP_VOID accept(
+ basic_socket_ext_local<Protocol1, Executor1>& peer, boost::system::error_code& ec,
+ typename enable_if<
+ is_convertible<Protocol, Protocol1>::value
+ >::type* = 0)
+ {
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, static_cast<endpoint_type*>(0), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket. The function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * acceptor.async_accept(socket, accept_handler);
+ * @endcode
+ */
+ template <typename Protocol1, typename Executor1, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<Protocol1, Executor1>& peer,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<
+ is_convertible<Protocol, Protocol1>::value
+ >::type* = 0)
+ {
+ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
+ initiate_async_accept(), handler, this,
+ &peer, static_cast<endpoint_type*>(0));
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.accept(socket, endpoint);
+ * @endcode
+ */
+ template <typename Executor1>
+ void accept(basic_socket_ext_local<protocol_type, Executor1>& peer,
+ endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename Executor1>
+ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket_ext_local<protocol_type, Executor1>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ impl_.get_service().accept(
+ impl_.get_implementation(), peer, &peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket, and additionally obtain the endpoint of the remote peer. The
+ * function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ */
+ template <typename Executor1, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket_ext_local<protocol_type, Executor1>& peer,
+ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+ {
+ return async_initiate<AcceptHandler, void (boost::system::error_code)>(
+ initiate_async_accept(), handler, this, &peer, &peer_endpoint);
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ typename Protocol::socket accept()
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(impl_.get_executor());
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(impl_.get_executor());
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ return peer;
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * acceptor.async_accept(accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket)>(
+ initiate_async_move_accept(), handler, this,
+ impl_.get_executor(), static_cast<endpoint_type*>(0),
+ static_cast<typename Protocol::socket*>(0));
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly
+ * accepted socket.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ template <typename Executor1>
+ typename Protocol::socket::template rebind_executor<Executor1>::other
+ accept(const Executor1& ex,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket::template
+ rebind_executor<Executor1>::other peer(ex);
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ template <typename ExecutionContext>
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other
+ accept(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other peer(context);
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly accepted
+ * socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename Executor1>
+ typename Protocol::socket::template rebind_executor<Executor1>::other
+ accept(const Executor1& ex, boost::system::error_code& ec,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ typename Protocol::socket::template
+ rebind_executor<Executor1>::other peer(ex);
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename ExecutionContext>
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other
+ accept(ExecutionContext& context, boost::system::error_code& ec,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other peer(context);
+ impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);
+ return peer;
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly accepted
+ * socket.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket::template rebind_executor<
+ * Executor1>::other peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * acceptor.async_accept(my_context2, accept_handler);
+ * @endcode
+ */
+ template <typename Executor1, typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket::template rebind_executor<
+ Executor1>::other))
+ async_accept(const Executor1& ex,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ typedef typename Protocol::socket::template rebind_executor<
+ Executor1>::other other_socket_type;
+
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, other_socket_type)>(
+ initiate_async_move_accept(), handler, this,
+ ex, static_cast<endpoint_type*>(0),
+ static_cast<other_socket_type*>(0));
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket::template rebind_executor<
+ * typename ExecutionContext::executor_type>::other peer
+ * // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * acceptor.async_accept(my_context2, accept_handler);
+ * @endcode
+ */
+ template <typename ExecutionContext, typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other))
+ async_accept(ExecutionContext& context,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ typedef typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other other_socket_type;
+
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, other_socket_type)>(
+ initiate_async_move_accept(), handler, this,
+ context.get_executor(), static_cast<endpoint_type*>(0),
+ static_cast<other_socket_type*>(0));
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint));
+ * @endcode
+ */
+ typename Protocol::socket accept(endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(impl_.get_executor());
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(impl_.get_executor());
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ return peer;
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket)>(
+ initiate_async_move_accept(), handler, this,
+ impl_.get_executor(), &peer_endpoint,
+ static_cast<typename Protocol::socket*>(0));
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(my_context2, endpoint));
+ * @endcode
+ */
+ template <typename Executor1>
+ typename Protocol::socket::template rebind_executor<Executor1>::other
+ accept(const Executor1& ex, endpoint_type& peer_endpoint,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket::template
+ rebind_executor<Executor1>::other peer(ex);
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(my_context2, endpoint));
+ * @endcode
+ */
+ template <typename ExecutionContext>
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other
+ accept(ExecutionContext& context, endpoint_type& peer_endpoint,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other peer(context);
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(my_context2, endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename Executor1>
+ typename Protocol::socket::template rebind_executor<Executor1>::other
+ accept(const executor_type& ex,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ typename Protocol::socket::template
+ rebind_executor<Executor1>::other peer(ex);
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(my_context2, endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename ExecutionContext>
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other
+ accept(ExecutionContext& context,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other peer(context);
+ impl_.get_service().accept(impl_.get_implementation(),
+ peer, &peer_endpoint, ec);
+ return peer;
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ex The I/O executor object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket::template rebind_executor<
+ * Executor1>::other peer // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(my_context2, endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename Executor1, typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket::template rebind_executor<
+ Executor1>::other))
+ async_accept(const Executor1& ex, endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler,
+ typename enable_if<
+ is_executor<Executor1>::value
+ >::type* = 0)
+ {
+ typedef typename Protocol::socket::template rebind_executor<
+ Executor1>::other other_socket_type;
+
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, other_socket_type)>(
+ initiate_async_move_accept(), handler, this,
+ ex, &peer_endpoint,
+ static_cast<other_socket_type*>(0));
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param context The I/O execution context object to be used for the newly
+ * accepted socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket::template rebind_executor<
+ * typename ExecutionContext::executor_type>::other peer
+ * // On success, the newly accepted socket.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(my_context2, endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename ExecutionContext, typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other))
+ async_accept(ExecutionContext& context,
+ endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ {
+ typedef typename Protocol::socket::template rebind_executor<
+ typename ExecutionContext::executor_type>::other other_socket_type;
+
+ return async_initiate<MoveAcceptHandler,
+ void (boost::system::error_code, other_socket_type)>(
+ initiate_async_move_accept(), handler, this,
+ context.get_executor(), &peer_endpoint,
+ static_cast<other_socket_type*>(0));
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_acceptor_ext(const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED;
+ basic_socket_acceptor_ext& operator=(
+ const basic_socket_acceptor_ext&) BOOST_ASIO_DELETED;
+
+ struct initiate_async_wait
+ {
+ template <typename WaitHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler,
+ basic_socket_acceptor_ext* self, wait_type w) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+ detail::non_const_lvalue<WaitHandler> handler2(handler);
+ self->impl_.get_service().async_wait(
+ self->impl_.get_implementation(), w, handler2.value,
+ self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_accept
+ {
+ template <typename AcceptHandler, typename Protocol1, typename Executor1>
+ void operator()(BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ basic_socket_acceptor_ext* self, basic_socket_ext_local<Protocol1, Executor1>* peer,
+ endpoint_type* peer_endpoint) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a AcceptHandler.
+ BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+
+ detail::non_const_lvalue<AcceptHandler> handler2(handler);
+ self->impl_.get_service().async_accept(
+ self->impl_.get_implementation(), *peer, peer_endpoint,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_move_accept
+ {
+ template <typename MoveAcceptHandler, typename Executor1, typename Socket>
+ void operator()(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler,
+ basic_socket_acceptor_ext* self, const Executor1& peer_ex,
+ endpoint_type* peer_endpoint, Socket*) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(
+ MoveAcceptHandler, handler, Socket) type_check;
+
+ detail::non_const_lvalue<MoveAcceptHandler> handler2(handler);
+ self->impl_.get_service().async_move_accept(
+ self->impl_.get_implementation(), peer_ex, peer_endpoint,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ detail::io_object_impl<
+ detail::null_socket_service<Protocol>, Executor> impl_;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ detail::io_object_impl<
+ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
+#else
+ detail::io_object_impl<
+ detail::reactive_socket_service_ext_local<Protocol>, Executor> impl_;
+#endif
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/basic_socket_ext.hpp b/implementation/helper/1.70/boost/asio/basic_socket_ext.hpp
new file mode 100644
index 0000000..523f97a
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/basic_socket_ext.hpp
@@ -0,0 +1,1859 @@
+//
+// basic_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2018,2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/io_object_impl.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext.hpp>
+#endif
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol, typename Executor = executor>
+class basic_socket_ext;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_FWD_DECL)
+
+/// Provides socket functionality.
+/**
+ * The basic_socket class template provides functionality that is common to both
+ * stream-oriented and datagram-oriented sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol, typename Executor>
+class basic_socket_ext
+ : public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef Executor executor_type;
+
+ /// Rebinds the socket type to another executor.
+ template <typename Executor1>
+ struct rebind_executor
+ {
+ /// The socket type when rebound to the specified executor.
+ typedef basic_socket_ext<Protocol, Executor1> other;
+ };
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef typename detail::null_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef typename detail::win_iocp_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#else
+ typedef typename detail::reactive_socket_service_ext<
+ Protocol>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// A basic_socket is always the lowest layer.
+ typedef basic_socket_ext<Protocol, Executor> lowest_layer_type;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_socket_ext(const executor_type& ex)
+ : impl_(ex)
+ {
+ }
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ */
+ template <typename ExecutionContext>
+ explicit basic_socket_ext(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(const executor_type& ex, const protocol_type& protocol)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(const executor_type& ex, const endpoint_type& endpoint)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext(const executor_type& ex, const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext(ExecutionContext& context, const protocol_type& protocol,
+ const native_handle_type& native_socket,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket from another.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ basic_socket_ext(basic_socket_ext&& other)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket from another.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ basic_socket_ext& operator=(basic_socket_ext&& other)
+ {
+ impl_ = std::move(other.impl_);
+ return *this;
+ }
+
+ // All sockets have access to each other's implementations.
+ template <typename Protocol1, typename Executor1>
+ friend class basic_socket_ext;
+
+ /// Move-construct a basic_socket from a socket of another protocol type.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ basic_socket_ext(basic_socket_ext<Protocol1, Executor1>&& other,
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value
+ >::type* = 0)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket from a socket of another protocol type.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value,
+ basic_socket_ext&
+ >::type operator=(basic_socket_ext<Protocol1, Executor1> && other)
+ {
+ basic_socket_ext tmp(std::move(other));
+ impl_ = std::move(tmp.impl_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return impl_.get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Get a const reference to the lowest layer.
+ /**
+ * This function returns a const reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A const reference to the lowest layer in the stack of layers.
+ * Ownership is not transferred to the caller.
+ */
+ const lowest_layer_type& lowest_layer() const
+ {
+ return *this;
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::system::error_code ec;
+ * socket.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_socket, boost::system::error_code& ec)
+ {
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open() const
+ {
+ return impl_.get_service().is_open(impl_.get_implementation());
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = impl_.get_service().release(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return impl_.get_service().release(impl_.get_implementation(), ec);
+ }
+
+ /// Get the native socket representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * socket. This is intended to allow access to native socket functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return impl_.get_service().native_handle(impl_.get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ void cancel()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ bool at_mark() const
+ {
+ boost::system::error_code ec;
+ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "at_mark");
+ return b;
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ */
+ bool at_mark(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().at_mark(impl_.get_implementation(), ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t available() const
+ {
+ boost::system::error_code ec;
+ std::size_t s = impl_.get_service().available(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "available");
+ return s;
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ */
+ std::size_t available(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().available(impl_.get_implementation(), ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.connect(endpoint);
+ * @endcode
+ */
+ void connect(const endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ if (!is_open())
+ {
+ impl_.get_service().open(impl_.get_implementation(),
+ peer_endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * boost::system::error_code ec;
+ * socket.connect(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ if (!is_open())
+ {
+ impl_.get_service().open(impl_.get_implementation(),
+ peer_endpoint.protocol(), ec);
+ if (ec)
+ {
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+ }
+
+ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous connect.
+ /**
+ * This function is used to asynchronously connect a socket to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected. Copies will be made of the endpoint object as required.
+ *
+ * @param handler The handler to be called when the connection operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void connect_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Connect succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_connect(endpoint, connect_handler);
+ * @endcode
+ */
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ boost::system::error_code open_ec;
+ if (!is_open())
+ {
+ const protocol_type protocol = peer_endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);
+ }
+
+ return async_initiate<ConnectHandler, void (boost::system::error_code)>(
+ initiate_async_connect(), handler, this, peer_endpoint, open_ec);
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * boost::system::error_code ec;
+ * socket.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * boost::system::error_code ec;
+ * socket.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ /**
+ * @returns @c true if the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return impl_.get_service().non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native socket. This mode has no effect on the behaviour of the socket
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying socket is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the socket object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native socket.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ bool native_non_blocking() const
+ {
+ return impl_.get_service().native_non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = impl_.get_service().local_endpoint(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
+ * @endcode
+ */
+ endpoint_type remote_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = impl_.get_service().remote_endpoint(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "remote_endpoint");
+ return ep;
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type remote_endpoint(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
+ * @endcode
+ */
+ void shutdown(shutdown_type what)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
+ boost::asio::detail::throw_error(ec, "shutdown");
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ return async_initiate<WaitHandler, void (boost::system::error_code)>(
+ initiate_async_wait(), handler, this, w);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_socket_ext()
+ {
+ }
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ detail::io_object_impl<
+ detail::null_socket_service<Protocol>, Executor> impl_;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ detail::io_object_impl<
+ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
+#else
+ detail::io_object_impl<
+ detail::reactive_socket_service_ext<Protocol>, Executor> impl_;
+#endif
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_ext(const basic_socket_ext&) BOOST_ASIO_DELETED;
+ basic_socket_ext& operator=(const basic_socket_ext&) BOOST_ASIO_DELETED;
+
+ struct initiate_async_connect
+ {
+ template <typename ConnectHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler,
+ basic_socket_ext* self, const endpoint_type& peer_endpoint,
+ const boost::system::error_code& open_ec) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ConnectHandler.
+ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
+
+ if (open_ec)
+ {
+ boost::asio::post(self->impl_.get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec));
+ }
+ else
+ {
+ detail::non_const_lvalue<ConnectHandler> handler2(handler);
+ self->impl_.get_service().async_connect(
+ self->impl_.get_implementation(), peer_endpoint,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ }
+ };
+
+ struct initiate_async_wait
+ {
+ template <typename WaitHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler,
+ basic_socket_ext* self, wait_type w) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+ detail::non_const_lvalue<WaitHandler> handler2(handler);
+ self->impl_.get_service().async_wait(
+ self->impl_.get_implementation(), w, handler2.value,
+ self->impl_.get_implementation_executor());
+ }
+ };
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/basic_socket_ext_local.hpp b/implementation/helper/1.70/boost/asio/basic_socket_ext_local.hpp
new file mode 100644
index 0000000..855d01c
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/basic_socket_ext_local.hpp
@@ -0,0 +1,1859 @@
+//
+// basic_socket_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2018,2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
+#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext.hpp>
+#include <boost/asio/detail/io_object_impl.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+#elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+#else
+# include <boost/asio/detail/reactive_socket_service_ext_local.hpp>
+#endif
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol, typename Executor = executor>
+class basic_socket_ext_local;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_FWD_DECL)
+
+/// Provides socket functionality.
+/**
+ * The basic_socket class template provides functionality that is common to both
+ * stream-oriented and datagram-oriented sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol, typename Executor>
+class basic_socket_ext_local
+ : public socket_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef Executor executor_type;
+
+ /// Rebinds the socket type to another executor.
+ template <typename Executor1>
+ struct rebind_executor
+ {
+ /// The socket type when rebound to the specified executor.
+ typedef basic_socket_ext_local<Protocol, Executor1> other;
+ };
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ typedef typename detail::null_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ typedef typename detail::win_iocp_socket_service<
+ Protocol>::native_handle_type native_handle_type;
+#else
+ typedef typename detail::reactive_socket_service_ext_local<
+ Protocol>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// A basic_socket is always the lowest layer.
+ typedef basic_socket_ext_local<Protocol, Executor> lowest_layer_type;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_socket_ext_local(const executor_type& ex)
+ : impl_(ex)
+ {
+ }
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ */
+ template <typename ExecutionContext>
+ explicit basic_socket_ext_local(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(const executor_type& ex, const endpoint_type& endpoint)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext_local(ExecutionContext& context, const endpoint_type& endpoint,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ const protocol_type protocol = endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_ext_local(const executor_type& ex, const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ : impl_(ex)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_socket_ext_local(ExecutionContext& context, const protocol_type& protocol,
+ const native_handle_type& native_socket,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : impl_(context)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket from another.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ basic_socket_ext_local(basic_socket_ext_local&& other)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket from another.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ basic_socket_ext_local& operator=(basic_socket_ext_local&& other)
+ {
+ impl_ = std::move(other.impl_);
+ return *this;
+ }
+
+ // All sockets have access to each other's implementations.
+ template <typename Protocol1, typename Executor1>
+ friend class basic_socket_ext_local;
+
+ /// Move-construct a basic_socket from a socket of another protocol type.
+ /**
+ * This constructor moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ basic_socket_ext_local(basic_socket_ext_local<Protocol1, Executor1>&& other,
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value
+ >::type* = 0)
+ : impl_(std::move(other.impl_))
+ {
+ }
+
+ /// Move-assign a basic_socket from a socket of another protocol type.
+ /**
+ * This assignment operator moves a socket from one object to another.
+ *
+ * @param other The other basic_socket object from which the move will
+ * occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_socket(const executor_type&) constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value,
+ basic_socket_ext_local&
+ >::type operator=(basic_socket_ext_local<Protocol1, Executor1> && other)
+ {
+ basic_socket_ext_local tmp(std::move(other));
+ impl_ = std::move(tmp.impl_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return impl_.get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Get a const reference to the lowest layer.
+ /**
+ * This function returns a const reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A const reference to the lowest layer in the stack of layers.
+ * Ownership is not transferred to the caller.
+ */
+ const lowest_layer_type& lowest_layer() const
+ {
+ return *this;
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::system::error_code ec;
+ * socket.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().open(impl_.get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol,
+ const native_handle_type& native_socket)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
+ const native_handle_type& native_socket, boost::system::error_code& ec)
+ {
+ impl_.get_service().assign(impl_.get_implementation(),
+ protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open() const
+ {
+ return impl_.get_service().is_open(impl_.get_implementation());
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ impl_.get_service().close(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = impl_.get_service().release(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)
+ __declspec(deprecated("This function always fails with "
+ "operation_not_supported when used on Windows versions "
+ "prior to Windows 8.1."))
+#endif
+ native_handle_type release(boost::system::error_code& ec)
+ {
+ return impl_.get_service().release(impl_.get_implementation(), ec);
+ }
+
+ /// Get the native socket representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * socket. This is intended to allow access to native socket functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return impl_.get_service().native_handle(impl_.get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ void cancel()
+ {
+ boost::system::error_code ec;
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ impl_.get_service().cancel(impl_.get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ bool at_mark() const
+ {
+ boost::system::error_code ec;
+ bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "at_mark");
+ return b;
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ */
+ bool at_mark(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().at_mark(impl_.get_implementation(), ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t available() const
+ {
+ boost::system::error_code ec;
+ std::size_t s = impl_.get_service().available(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "available");
+ return s;
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ */
+ std::size_t available(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().available(impl_.get_implementation(), ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ boost::asio::detail::throw_error(ec, "bind");
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.connect(endpoint);
+ * @endcode
+ */
+ void connect(const endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ if (!is_open())
+ {
+ impl_.get_service().open(impl_.get_implementation(),
+ peer_endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * boost::system::error_code ec;
+ * socket.connect(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ if (!is_open())
+ {
+ impl_.get_service().open(impl_.get_implementation(),
+ peer_endpoint.protocol(), ec);
+ if (ec)
+ {
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+ }
+
+ impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Start an asynchronous connect.
+ /**
+ * This function is used to asynchronously connect a socket to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * not returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected. Copies will be made of the endpoint object as required.
+ *
+ * @param handler The handler to be called when the connection operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void connect_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Connect succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_connect(endpoint, connect_handler);
+ * @endcode
+ */
+ template <typename ConnectHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
+ void (boost::system::error_code))
+ async_connect(const endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
+ {
+ boost::system::error_code open_ec;
+ if (!is_open())
+ {
+ const protocol_type protocol = peer_endpoint.protocol();
+ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);
+ }
+
+ return async_initiate<ConnectHandler, void (boost::system::error_code)>(
+ initiate_async_connect(), handler, this, peer_endpoint, open_ec);
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * boost::system::error_code ec;
+ * socket.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().set_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * boost::system::error_code ec;
+ * socket.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.value();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ impl_.get_service().get_option(impl_.get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().io_control(impl_.get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the socket.
+ /**
+ * @returns @c true if the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return impl_.get_service().non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the socket.
+ /**
+ * @param mode If @c true, the socket's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native socket. This mode has no effect on the behaviour of the socket
+ * object's synchronous operations.
+ *
+ * @returns @c true if the underlying socket is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the socket object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native socket.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ bool native_non_blocking() const
+ {
+ return impl_.get_service().native_non_blocking(impl_.get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native socket implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native socket. It has no effect on the behaviour of the socket object's
+ * synchronous operations.
+ *
+ * @param mode If @c true, the underlying socket is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ *
+ * @par Example
+ * This function is intended to allow the encapsulation of arbitrary
+ * non-blocking system calls as asynchronous operations, in a way that is
+ * transparent to the user of the socket object. The following example
+ * illustrates how Linux's @c sendfile system call might be encapsulated:
+ * @code template <typename Handler>
+ * struct sendfile_op
+ * {
+ * tcp::socket& sock_;
+ * int fd_;
+ * Handler handler_;
+ * off_t offset_;
+ * std::size_t total_bytes_transferred_;
+ *
+ * // Function call operator meeting WriteHandler requirements.
+ * // Used as the handler for the async_write_some operation.
+ * void operator()(boost::system::error_code ec, std::size_t)
+ * {
+ * // Put the underlying socket into non-blocking mode.
+ * if (!ec)
+ * if (!sock_.native_non_blocking())
+ * sock_.native_non_blocking(true, ec);
+ *
+ * if (!ec)
+ * {
+ * for (;;)
+ * {
+ * // Try the system call.
+ * errno = 0;
+ * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);
+ * ec = boost::system::error_code(n < 0 ? errno : 0,
+ * boost::asio::error::get_system_category());
+ * total_bytes_transferred_ += ec ? 0 : n;
+ *
+ * // Retry operation immediately if interrupted by signal.
+ * if (ec == boost::asio::error::interrupted)
+ * continue;
+ *
+ * // Check if we need to run the operation again.
+ * if (ec == boost::asio::error::would_block
+ * || ec == boost::asio::error::try_again)
+ * {
+ * // We have to wait for the socket to become ready again.
+ * sock_.async_wait(tcp::socket::wait_write, *this);
+ * return;
+ * }
+ *
+ * if (ec || n == 0)
+ * {
+ * // An error occurred, or we have reached the end of the file.
+ * // Either way we must exit the loop so we can call the handler.
+ * break;
+ * }
+ *
+ * // Loop around to try calling sendfile again.
+ * }
+ * }
+ *
+ * // Pass result back to user's handler.
+ * handler_(ec, total_bytes_transferred_);
+ * }
+ * };
+ *
+ * template <typename Handler>
+ * void async_sendfile(tcp::socket& sock, int fd, Handler h)
+ * {
+ * sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
+ * sock.async_wait(tcp::socket::wait_write, op);
+ * } @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ impl_.get_service().native_non_blocking(
+ impl_.get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = impl_.get_service().local_endpoint(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "local_endpoint");
+ return ep;
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
+ * @endcode
+ */
+ endpoint_type remote_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = impl_.get_service().remote_endpoint(
+ impl_.get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "remote_endpoint");
+ return ep;
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type remote_endpoint(boost::system::error_code& ec) const
+ {
+ return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
+ * @endcode
+ */
+ void shutdown(shutdown_type what)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
+ boost::asio::detail::throw_error(ec, "shutdown");
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
+ boost::system::error_code& ec)
+ {
+ impl_.get_service().shutdown(impl_.get_implementation(), what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ impl_.get_service().wait(impl_.get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ /**
+ * This function is used to perform an asynchronous wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param handler The handler to be called when the wait operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(my_context);
+ * ...
+ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ return async_initiate<WaitHandler, void (boost::system::error_code)>(
+ initiate_async_wait(), handler, this, w);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_socket_ext_local()
+ {
+ }
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ detail::io_object_impl<
+ detail::null_socket_service<Protocol>, Executor> impl_;
+#elif defined(BOOST_ASIO_HAS_IOCP)
+ detail::io_object_impl<
+ detail::win_iocp_socket_service<Protocol>, Executor> impl_;
+#else
+ detail::io_object_impl<
+ detail::reactive_socket_service_ext_local<Protocol>, Executor> impl_;
+#endif
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_ext_local(const basic_socket_ext_local&) BOOST_ASIO_DELETED;
+ basic_socket_ext_local& operator=(const basic_socket_ext_local&) BOOST_ASIO_DELETED;
+
+ struct initiate_async_connect
+ {
+ template <typename ConnectHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(ConnectHandler) handler,
+ basic_socket_ext_local* self, const endpoint_type& peer_endpoint,
+ const boost::system::error_code& open_ec) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ConnectHandler.
+ BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
+
+ if (open_ec)
+ {
+ boost::asio::post(self->impl_.get_executor(),
+ boost::asio::detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec));
+ }
+ else
+ {
+ detail::non_const_lvalue<ConnectHandler> handler2(handler);
+ self->impl_.get_service().async_connect(
+ self->impl_.get_implementation(), peer_endpoint,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ }
+ };
+
+ struct initiate_async_wait
+ {
+ template <typename WaitHandler>
+ void operator()(BOOST_ASIO_MOVE_ARG(WaitHandler) handler,
+ basic_socket_ext_local* self, wait_type w) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+ detail::non_const_lvalue<WaitHandler> handler2(handler);
+ self->impl_.get_service().async_wait(
+ self->impl_.get_implementation(), w, handler2.value,
+ self->impl_.get_implementation_executor());
+ }
+ };
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/basic_stream_socket_ext.hpp b/implementation/helper/1.70/boost/asio/basic_stream_socket_ext.hpp
new file mode 100644
index 0000000..325157a
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/basic_stream_socket_ext.hpp
@@ -0,0 +1,996 @@
+//
+// basic_stream_socket_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_socket_ext_local.hpp>
+#include <boost/asio/detail/handler_type_requirements_ext_local.hpp>
+#include <boost/asio/detail/non_const_lvalue.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL)
+#define BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol, typename Executor = executor>
+class basic_stream_socket_ext;
+
+#endif // !defined(BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_FWD_DECL)
+
+/// Provides stream-oriented socket functionality.
+/**
+ * The basic_stream_socket_ext class template provides asynchronous and blocking
+ * stream-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Protocol, typename Executor>
+class basic_stream_socket_ext
+ : public basic_socket_ext_local<Protocol, Executor>
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef Executor executor_type;
+
+ /// Rebinds the socket type to another executor.
+ template <typename Executor1>
+ struct rebind_executor
+ {
+ /// The socket type when rebound to the specified executor.
+ typedef basic_stream_socket_ext<Protocol, Executor1> other;
+ };
+
+ /// The native representation of a socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket<Protocol,
+ Executor>::native_handle_type native_handle_type;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_stream_socket without opening it.
+ /**
+ * This constructor creates a stream socket without opening it. The socket
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_stream_socket_ext(const executor_type& ex)
+ : basic_socket_ext_local<Protocol, Executor>(ex)
+ {
+ }
+
+ /// Construct a basic_stream_socket without opening it.
+ /**
+ * This constructor creates a stream socket without opening it. The socket
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ */
+ template <typename ExecutionContext>
+ explicit basic_stream_socket_ext(ExecutionContext& context,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext_local<Protocol, Executor>(context)
+ {
+ }
+
+ /// Construct and open a basic_stream_socket.
+ /**
+ * This constructor creates and opens a stream socket. The socket needs to be
+ * connected or accepted before data can be sent or received on it.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(const executor_type& ex, const protocol_type& protocol)
+ : basic_socket_ext_local<Protocol, Executor>(ex, protocol)
+ {
+ }
+
+ /// Construct and open a basic_stream_socket.
+ /**
+ * This constructor creates and opens a stream socket. The socket needs to be
+ * connected or accepted before data can be sent or received on it.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_stream_socket_ext(ExecutionContext& context, const protocol_type& protocol,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext_local<Protocol, Executor>(context, protocol)
+ {
+ }
+
+ /// Construct a basic_stream_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a stream socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the stream
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(const executor_type& ex, const endpoint_type& endpoint)
+ : basic_socket_ext_local<Protocol, Executor>(ex, endpoint)
+ {
+ }
+
+ /// Construct a basic_stream_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a stream socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the stream
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_stream_socket_ext(ExecutionContext& context, const endpoint_type& endpoint,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext_local<Protocol, Executor>(context, endpoint)
+ {
+ }
+
+ /// Construct a basic_stream_socket on an existing native socket.
+ /**
+ * This constructor creates a stream socket object to hold an existing native
+ * socket.
+ *
+ * @param ex The I/O executor that the socket will use, by default, to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket_ext(const executor_type& ex,
+ const protocol_type& protocol, const native_handle_type& native_socket)
+ : basic_socket_ext_local<Protocol, Executor>(ex, protocol, native_socket)
+ {
+ }
+
+ /// Construct a basic_stream_socket on an existing native socket.
+ /**
+ * This constructor creates a stream socket object to hold an existing native
+ * socket.
+ *
+ * @param context An execution context which provides the I/O executor that
+ * the socket will use, by default, to dispatch handlers for any asynchronous
+ * operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ExecutionContext>
+ basic_stream_socket_ext(ExecutionContext& context,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value
+ >::type* = 0)
+ : basic_socket_ext_local<Protocol, Executor>(context, protocol, native_socket)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_stream_socket from another.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket(const executor_type&)
+ * constructor.
+ */
+ basic_stream_socket_ext(basic_stream_socket_ext&& other)
+ : basic_socket_ext_local<Protocol, Executor>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket from another.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket(const executor_type&)
+ * constructor.
+ */
+ basic_stream_socket_ext& operator=(basic_stream_socket_ext&& other)
+ {
+ basic_socket_ext_local<Protocol, Executor>::operator=(std::move(other));
+ return *this;
+ }
+
+ /// Move-construct a basic_stream_socket from a socket of another protocol
+ /// type.
+ /**
+ * This constructor moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ basic_stream_socket_ext(basic_stream_socket_ext<Protocol1, Executor1>&& other,
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value
+ >::type* = 0)
+ : basic_socket_ext_local<Protocol, Executor>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_stream_socket from a socket of another protocol type.
+ /**
+ * This assignment operator moves a stream socket from one object to another.
+ *
+ * @param other The other basic_stream_socket object from which the move
+ * will occur.
+ *
+ * @note Following the move, the moved-from object is in the same state as if
+ * constructed using the @c basic_stream_socket(const executor_type&)
+ * constructor.
+ */
+ template <typename Protocol1, typename Executor1>
+ typename enable_if<
+ is_convertible<Protocol1, Protocol>::value
+ && is_convertible<Executor1, Executor>::value,
+ basic_stream_socket_ext&
+ >::type operator=(basic_stream_socket_ext<Protocol1, Executor1>&& other)
+ {
+ basic_socket_ext_local<Protocol, Executor>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_stream_socket_ext()
+ {
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "send");
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent. Returns 0 if an error occurred.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t)>(
+ initiate_async_send(), handler, this, buffers, flags);
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ boost::asio::detail::throw_error(ec, "receive");
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received. Returns 0 if an error occurred.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
+ initiate_async_receive(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
+ initiate_async_receive(), handler, this, buffers, flags);
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().send(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ return async_initiate<WriteHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
+ initiate_async_send(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->impl_.get_service().receive(
+ this->impl_.get_implementation(), buffers, 0, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. On
+ * immediate completion, invocation of the handler will be performed in a
+ * manner equivalent to using boost::asio::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ return async_initiate<ReadHandler,
+ void (boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t)>(
+ initiate_async_receive(), handler, this,
+ buffers, socket_base::message_flags(0));
+ }
+
+private:
+ struct initiate_async_send
+ {
+ template <typename WriteHandler, typename ConstBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ basic_stream_socket_ext* self, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ detail::non_const_lvalue<WriteHandler> handler2(handler);
+ self->impl_.get_service().async_send(
+ self->impl_.get_implementation(), buffers, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+
+ struct initiate_async_receive
+ {
+ template <typename ReadHandler, typename MutableBufferSequence>
+ void operator()(BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ basic_stream_socket_ext* self, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags) const
+ {
+ // If you get an error on the following line it means that your handler
+ // does not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL(ReadHandler, handler) type_check;
+
+ detail::non_const_lvalue<ReadHandler> handler2(handler);
+ self->impl_.get_service().async_receive(
+ self->impl_.get_implementation(), buffers, flags,
+ handler2.value, self->impl_.get_implementation_executor());
+ }
+ };
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext.hpp b/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext.hpp
new file mode 100644
index 0000000..67fe6bd
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext.hpp
@@ -0,0 +1,586 @@
+//
+// detail/handler_type_requirements_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/async_result.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_copyable_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_copyable_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2, *a3)),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+auto three_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3 *a3)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3))),
+ char(0));
+
+template <typename Handler>
+char (&three_arg_move_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+#if defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> T rvref();
+template <typename T> T rvref(T);
+#else // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> const T& rvref();
+template <typename T> const T& rvref(T);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ boost::asio::ip::address)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::three_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const boost::asio::ip::address*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const boost::asio::ip::address>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#if 0
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, socket_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_move_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<socket_type*>(0))) == 1, \
+ "MoveAcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::rvref<socket_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+#endif
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, endpoint_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, endpoint_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const endpoint_type*>(0))) == 1, \
+ "RangeConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const endpoint_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "IteratorConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, range_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, range_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const range_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const range_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "BufferedHandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext_local.hpp
new file mode 100644
index 0000000..65640ad
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/handler_type_requirements_ext_local.hpp
@@ -0,0 +1,588 @@
+//
+// detail/handler_type_requirements_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+// Older versions of gcc have difficulty compiling the sizeof expressions where
+// we test the handler type requirements. We'll disable checking of handler type
+// requirements for those compilers, but otherwise enable it by default.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+# if !defined(__GNUC__) || (__GNUC__ >= 4)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+// With C++0x we can use a combination of enhanced SFINAE and static_assert to
+// generate better template error messages. As this technique is not yet widely
+// portable, we'll only enable it for tested compilers.
+#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# if defined(__clang__)
+# if __has_feature(__cxx_static_assert__)
+# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
+# endif // __has_feature(cxx_static_assert)
+# endif // defined(__clang__)
+#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+# include <boost/asio/async_result.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename Handler>
+auto zero_arg_copyable_handler_test(Handler h, void*)
+ -> decltype(
+ sizeof(Handler(static_cast<const Handler&>(h))),
+ ((h)()),
+ char(0));
+
+template <typename Handler>
+char (&zero_arg_copyable_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1>
+auto one_arg_handler_test(Handler h, Arg1* a1)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1)),
+ char(0));
+
+template <typename Handler>
+char (&one_arg_handler_test(Handler h, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2)),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+auto four_arg_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, *a2, *a3, *a4)),
+ char(0));
+
+template <typename Handler>
+char (&four_arg_handler_test(Handler, ...))[2];
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+auto four_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2, Arg3* a3, Arg4* a4)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2), BOOST_ASIO_MOVE_CAST(Arg3)(*a3), BOOST_ASIO_MOVE_CAST(Arg4)(*a4))),
+ char(0));
+
+template <typename Handler>
+char (&four_arg_move_handler_test(Handler, ...))[2];
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
+ static_assert(expr, msg);
+
+# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
+
+# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
+
+template <typename T> T& lvref();
+template <typename T> T& lvref(T);
+template <typename T> const T& clvref();
+template <typename T> const T& clvref(T);
+#if defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> T rvref();
+template <typename T> T rvref(T);
+#else // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> const T& rvref();
+template <typename T> const T& rvref(T);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> char argbyv(T);
+
+#if 0
+template <int>
+struct handler_type_requirements
+{
+};
+#endif
+
+#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void()) asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), 0)) == 1, \
+ "CompletionHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()(), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK_EXT_LOCAL( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t, \
+ std::uint32_t, std::uint32_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::four_arg_handler_test( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0), \
+ static_cast<const std::uint32_t*>(0), \
+ static_cast<const std::uint32_t*>(0))) == 1, \
+ "ReadHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::clvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>(), \
+ boost::asio::detail::lvref<const std::uint32_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "WriteHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#if 0
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "AcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, socket_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_move_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<socket_type*>(0))) == 1, \
+ "MoveAcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::rvref<socket_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+#endif
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, endpoint_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, endpoint_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const endpoint_type*>(0))) == 1, \
+ "RangeConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const endpoint_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, iter_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const iter_type*>(0))) == 1, \
+ "IteratorConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const iter_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, range_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, range_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const range_type*>(0))) == 1, \
+ "ResolveHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const range_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "WaitHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, int)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const int*>(0))) == 1, \
+ "SignalHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const int>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "HandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, std::size_t)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const std::size_t*>(0))) == 1, \
+ "BufferedHandshakeHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const std::size_t>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::one_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0))) == 1, \
+ "ShutdownHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+#define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_READ_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
+ handler_type, handler) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp b/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
new file mode 100644
index 0000000..04036ad
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext.ipp
@@ -0,0 +1,302 @@
+//
+// detail/reactive_socket_service_base_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext::reactive_socket_service_base_ext(
+ execution_context& context)
+ : reactor_(use_service<reactor>(context))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext::base_shutdown()
+{
+}
+
+void reactive_socket_service_base_ext::construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext::base_move_construct(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::base_move_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ reactive_socket_service_base_ext::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext::destroy(
+ reactive_socket_service_base_ext::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext::close(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+/*
+socket_type reactive_socket_service_base::release(
+ reactive_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "release"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ socket_type sock = impl.socket_;
+ construct(impl);
+ ec = boost::system::error_code();
+ return sock;
+}
+*/
+boost::system::error_code reactive_socket_service_base_ext::cancel(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_open(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext::do_assign(
+ reactive_socket_service_base_ext::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext::start_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext::start_accept_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, is_continuation, true, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext::start_connect_op(
+ reactive_socket_service_base_ext::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_IPP
diff --git a/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp b/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
new file mode 100644
index 0000000..288cf19
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp
@@ -0,0 +1,302 @@
+//
+// detail/reactive_socket_service_base_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base_ext_local::reactive_socket_service_base_ext_local(
+ execution_context& context)
+ : reactor_(use_service<reactor>(context))
+{
+ reactor_.init_task();
+}
+
+void reactive_socket_service_base_ext_local::base_shutdown()
+{
+}
+
+void reactive_socket_service_base_ext_local::construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ impl.socket_ = invalid_socket;
+ impl.state_ = 0;
+}
+
+void reactive_socket_service_base_ext_local::base_move_construct(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::base_move_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ reactive_socket_service_base_ext_local::base_implementation_type& other_impl)
+{
+ destroy(impl);
+
+ impl.socket_ = other_impl.socket_;
+ other_impl.socket_ = invalid_socket;
+
+ impl.state_ = other_impl.state_;
+ other_impl.state_ = 0;
+
+ other_service.reactor_.move_descriptor(impl.socket_,
+ impl.reactor_data_, other_impl.reactor_data_);
+}
+
+void reactive_socket_service_base_ext_local::destroy(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl)
+{
+ if (impl.socket_ != invalid_socket)
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::close(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
+ (impl.state_ & socket_ops::possible_dup) == 0);
+
+ socket_ops::close(impl.socket_, impl.state_, false, ec);
+
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+
+ // The descriptor is closed by the OS even if close() returns an error.
+ //
+ // (Actually, POSIX says the state of the descriptor is unspecified. On
+ // Linux the descriptor is apparently closed anyway; e.g. see
+ // http://lkml.org/lkml/2005/9/10/129
+ // We'll just have to assume that other OSes follow the same behaviour. The
+ // known exception is when Windows's closesocket() function fails with
+ // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().
+ construct(impl);
+
+ return ec;
+}
+/*
+socket_type reactive_socket_service_base::release(
+ reactive_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "release"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ socket_type sock = impl.socket_;
+ construct(impl);
+ ec = boost::system::error_code();
+ return sock;
+}
+*/
+boost::system::error_code reactive_socket_service_base_ext_local::cancel(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_open(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int af, int type, int protocol, boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ ec = boost::system::error_code();
+ return ec;
+}
+
+boost::system::error_code reactive_socket_service_base_ext_local::do_assign(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl, int type,
+ const reactive_socket_service_base_ext_local::native_handle_type& native_socket,
+ boost::system::error_code& ec)
+{
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ switch (type)
+ {
+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+ default: impl.state_ = 0; break;
+ }
+ impl.state_ |= socket_ops::possible_dup;
+ ec = boost::system::error_code();
+ return ec;
+}
+
+void reactive_socket_service_base_ext_local::start_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ int op_type, reactor_op* op, bool is_continuation,
+ bool is_non_blocking, bool noop)
+{
+ if (!noop)
+ {
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ reactor_.start_op(op_type, impl.socket_,
+ impl.reactor_data_, op, is_continuation, is_non_blocking);
+ return;
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+void reactive_socket_service_base_ext_local::start_accept_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open)
+{
+ if (!peer_is_open)
+ start_op(impl, reactor::read_op, op, is_continuation, true, false);
+ else
+ {
+ op->ec_ = boost::asio::error::already_open;
+ reactor_.post_immediate_completion(op, is_continuation);
+ }
+}
+
+void reactive_socket_service_base_ext_local::start_connect_op(
+ reactive_socket_service_base_ext_local::base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen)
+{
+ if ((impl.state_ & socket_ops::non_blocking)
+ || socket_ops::set_internal_non_blocking(
+ impl.socket_, impl.state_, true, op->ec_))
+ {
+ if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+ {
+ if (op->ec_ == boost::asio::error::in_progress
+ || op->ec_ == boost::asio::error::would_block)
+ {
+ op->ec_ = boost::system::error_code();
+ reactor_.start_op(reactor::connect_op, impl.socket_,
+ impl.reactor_data_, op, is_continuation, false);
+ return;
+ }
+ }
+ }
+
+ reactor_.post_immediate_completion(op, is_continuation);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_IPP
diff --git a/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext.ipp b/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext.ipp
new file mode 100644
index 0000000..5825796
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext.ipp
@@ -0,0 +1,210 @@
+//
+// detail/impl/socket_ops_ext.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
+ LPFN_WSARECVMSG WSARecvMsg;
+ DWORD NumberOfBytes;
+
+ error_wrapper(WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &WSARecvMsg_GUID, sizeof WSARecvMsg_GUID,
+ &WSARecvMsg, sizeof WSARecvMsg,
+ &NumberOfBytes, NULL, NULL), ec);
+ if (ec.value() == SOCKET_ERROR) {
+ WSARecvMsg = NULL;
+ return 0;
+ }
+
+ WSABUF wsaBuf;
+ WSAMSG msg;
+ char controlBuffer[1024];
+ msg.name = addr;
+ msg.namelen = *addrlen;
+ wsaBuf.buf = bufs->buf;
+ wsaBuf.len = bufs->len;
+ msg.lpBuffers = &wsaBuf;
+ msg.dwBufferCount = count;
+ msg.Control.len = sizeof controlBuffer;
+ msg.Control.buf = controlBuffer;
+ msg.dwFlags = flags;
+
+ DWORD dwNumberOfBytesRecvd;
+ signed_size_type result = error_wrapper(WSARecvMsg(s, &msg, &dwNumberOfBytesRecvd, NULL, NULL), ec);
+
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (LPWSACMSGHDR cmsg = WSA_CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = WSA_CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) WSA_CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ } else {
+ dwNumberOfBytesRecvd = -1;
+ }
+ return dwNumberOfBytesRecvd;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ char cmbuf[0x100];
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+ msg.msg_control = cmbuf;
+ msg.msg_controllen = sizeof(cmbuf);
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find destination address
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != IPPROTO_IP || cmsg->cmsg_type != IP_PKTINFO)
+ continue;
+
+ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg);
+ if (pi)
+ {
+ da = boost::asio::ip::address_v4(ntohl(pi->ipi_addr.s_addr));
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec, boost::asio::ip::address& da)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred, boost::asio::ip::address& da)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, da);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_IPP
diff --git a/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext_local.ipp b/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext_local.ipp
new file mode 100644
index 0000000..5050f24
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/impl/socket_ops_ext_local.ipp
@@ -0,0 +1,303 @@
+//
+// detail/impl/socket_ops_ext_local.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
+
+#include <boost/asio/detail/impl/socket_ops.ipp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+signed_size_type recv(socket_type s, buf* bufs, size_t count,
+ int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = error_wrapper(::WSARecv(s, bufs,
+ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
+ int flags, socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ struct ucred *ucredp;
+ clear_last_error();
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int tmp_addrlen = (int)*addrlen;
+ int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+ *addrlen = (std::size_t)tmp_addrlen;
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = boost::asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = boost::asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = boost::system::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = static_cast<int>(*addrlen);
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = static_cast<int>(count);
+
+ union {
+ struct cmsghdr cmh;
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ } control_un;
+
+ // Set 'control_un' to describe ancillary data that we want to receive
+ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
+ control_un.cmh.cmsg_level = SOL_SOCKET;
+ control_un.cmh.cmsg_type = SCM_CREDENTIALS;
+
+ // Set 'msg' fields to describe 'control_un'
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0) {
+ ec = boost::system::error_code();
+
+ // Find UID / GID
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_CREDENTIALS
+ || cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred)))
+ continue;
+
+ ucredp = (struct ucred *) CMSG_DATA(cmsg);
+ if (ucredp) {
+ uid = ucredp->uid;
+ gid = ucredp->gid;
+ }
+ }
+ }
+ return result;
+#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Check if operation succeeded.
+ if (bytes >= 0)
+ return bytes;
+
+ // Operation failed.
+ if ((state & user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ uid = 0xFFFFFFFF;
+ gid = 0xFFFFFFFF;
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+}
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec, uid, gid);
+
+ // Check for end of stream.
+ if (is_stream && bytes == 0)
+ {
+ ec = boost::asio::error::eof;
+ return true;
+ }
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid)
+{
+ for (;;)
+ {
+ // Read some data.
+ signed_size_type bytes = socket_ops::recvfrom(
+ s, bufs, count, flags, addr, addrlen, ec, uid, gid);
+
+ // Retry operation if interrupted by signal.
+ if (ec == boost::asio::error::interrupted)
+ continue;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ // Operation is complete.
+ if (bytes >= 0)
+ {
+ ec = boost::system::error_code();
+ bytes_transferred = bytes;
+ }
+ else
+ bytes_transferred = 0;
+
+ return true;
+ }
+}
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_IPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext.hpp
new file mode 100644
index 0000000..da8cd83
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext.hpp
@@ -0,0 +1,140 @@
+//
+// detail/reactive_socket_recv_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recv_op_base_ext(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recv_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext* o(
+ static_cast<reactive_socket_recv_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ == 0)
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
+class reactive_socket_recv_op_ext :
+ public reactive_socket_recv_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext);
+
+ reactive_socket_recv_op_ext(socket_type socket, socket_ops::state_type state,
+ const MutableBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ : reactive_socket_recv_op_base_ext<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext* o(static_cast<reactive_socket_recv_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
new file mode 100644
index 0000000..ce5ca28
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recv_op_ext_local.hpp
@@ -0,0 +1,140 @@
+//
+// detail/reactive_socket_recv_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recv_op_base_ext_local(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recv_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base_ext_local* o(
+ static_cast<reactive_socket_recv_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented) != 0,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ == 0)
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
+class reactive_socket_recv_op_ext_local :
+ public reactive_socket_recv_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op_ext_local);
+
+ reactive_socket_recv_op_ext_local(socket_type socket, socket_ops::state_type state,
+ const MutableBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ : reactive_socket_recv_op_base_ext_local<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recv_op_ext_local* o(static_cast<reactive_socket_recv_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3, handler.arg4));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
new file mode 100644
index 0000000..6cc2443
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp
@@ -0,0 +1,145 @@
+//
+// detail/reactive_socket_recvfrom_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvfrom_op_base_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvfrom_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ status result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->da_) ? done : not_done;
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint,
+ typename Handler, typename IoExecutor>
+class reactive_socket_recvfrom_op_ext :
+ public reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext);
+
+ reactive_socket_recvfrom_op_ext(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler,
+ const IoExecutor& io_ex)
+ : reactive_socket_recvfrom_op_base_ext<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext* o(
+ static_cast<reactive_socket_recvfrom_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
new file mode 100644
index 0000000..fcf04c1
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp
@@ -0,0 +1,145 @@
+//
+// detail/reactive_socket_recvfrom_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvfrom_op_base_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&reactive_socket_recvfrom_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ status result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_, o->uid_, o->gid_) ? done : not_done;
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint,
+ typename Handler, typename IoExecutor>
+class reactive_socket_recvfrom_op_ext_local :
+ public reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op_ext_local);
+
+ reactive_socket_recvfrom_op_ext_local(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler& handler,
+ const IoExecutor& io_ex)
+ : reactive_socket_recvfrom_op_base_ext_local<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvfrom_op_ext_local* o(
+ static_cast<reactive_socket_recvfrom_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
new file mode 100644
index 0000000..cd02730
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp
@@ -0,0 +1,138 @@
+//
+// detail/reactive_socket_recvmsg_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext : public reactor_op_ext
+{
+public:
+ reactive_socket_recvmsg_op_base_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext(&reactive_socket_recvmsg_op_base_ext::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
+class reactive_socket_recvmsg_op_ext :
+ public reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext);
+
+ reactive_socket_recvmsg_op_ext(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ : reactive_socket_recvmsg_op_base_ext<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext* o(
+ static_cast<reactive_socket_recvmsg_op_ext*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder3<Handler, boost::system::error_code, std::size_t, boost::asio::ip::address>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->da_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
new file mode 100644
index 0000000..059cddb
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp
@@ -0,0 +1,138 @@
+//
+// detail/reactive_socket_recvmsg_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op_ext_local.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/socket_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recvmsg_op_base_ext_local : public reactor_op_ext_local
+{
+public:
+ reactive_socket_recvmsg_op_base_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, func_type complete_func)
+ : reactor_op_ext_local(&reactive_socket_recvmsg_op_base_ext_local::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ in_flags_(in_flags),
+ out_flags_(out_flags)
+ {
+ }
+
+ static status do_perform(reactor_op* base)
+ {
+ reactive_socket_recvmsg_op_base_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_base_ext_local*>(base));
+
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ status result = socket_ops::non_blocking_recvmsg(o->socket_,
+ bufs.buffers(), bufs.count(),
+ o->in_flags_, o->out_flags_,
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags in_flags_;
+ socket_base::message_flags& out_flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler, typename IoExecutor>
+class reactive_socket_recvmsg_op_ext_local :
+ public reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op_ext_local);
+
+ reactive_socket_recvmsg_op_ext_local(socket_type socket,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ : reactive_socket_recvmsg_op_base_ext_local<MutableBufferSequence>(socket, buffers,
+ in_flags, out_flags, &reactive_socket_recvmsg_op_ext_local::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ io_executor_(io_ex)
+ {
+ handler_work<Handler, IoExecutor>::start(handler_, io_executor_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_recvmsg_op_ext_local* o(
+ static_cast<reactive_socket_recvmsg_op_ext_local*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler, IoExecutor> w(o->handler_, o->io_executor_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made. Even if we're not about to make an upcall, a
+ // sub-object of the handler may be the true owner of the memory associated
+ // with the handler. Consequently, a local copy of the handler is required
+ // to ensure that any owning sub-object remains valid until after we have
+ // deallocated the memory here.
+ detail::binder4<Handler, boost::system::error_code, std::size_t, std::uint32_t, std::uint32_t>
+ handler(o->handler_, o->ec_, o->bytes_transferred_, o->uid_, o->gid_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_, handler.arg3_, handler.arg4_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ IoExecutor io_executor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext.hpp
new file mode 100644
index 0000000..3fc3a5a
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext.hpp
@@ -0,0 +1,521 @@
+//
+// detail/reactive_socket_service_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext(execution_context& context);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void base_shutdown();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ switch (w)
+ {
+ case socket_base::wait_read:
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_write:
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_error:
+ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
+ break;
+ default:
+ ec = boost::asio::error::invalid_argument;
+ break;
+ }
+
+ return ec;
+ }
+
+ // Asynchronously wait for the socket to become ready to read, ready to
+ // write, or to have pending error conditions.
+ template <typename Handler, typename IoExecutor>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ int op_type;
+ switch (w)
+ {
+ case socket_base::wait_read:
+ op_type = reactor::read_op;
+ break;
+ case socket_base::wait_write:
+ op_type = reactor::write_op;
+ break;
+ case socket_base::wait_error:
+ op_type = reactor::except_op;
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<
+ ConstBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_,
+ buffers, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext<
+ MutableBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_,
+ buffers, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext<
+ MutableBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers,
+ in_flags, out_flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
new file mode 100644
index 0000000..8c5503f
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_base_ext_local.hpp
@@ -0,0 +1,521 @@
+//
+// detail/reactive_socket_service_base_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP) \
+ && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_recv_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_recvmsg_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops_ext_local.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base_ext_local
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ BOOST_ASIO_DECL reactive_socket_service_base_ext_local(execution_context& context);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void base_shutdown();
+
+ // Construct a new socket implementation.
+ BOOST_ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Move-construct a new socket implementation.
+ BOOST_ASIO_DECL void base_move_construct(base_implementation_type& impl,
+ base_implementation_type& other_impl);
+
+ // Move-assign from another socket implementation.
+ BOOST_ASIO_DECL void base_move_assign(base_implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ base_implementation_type& other_impl);
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code close(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Get the native socket representation.
+ native_handle_type native_handle(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ BOOST_ASIO_DECL boost::system::error_code cancel(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(base_implementation_type& impl,
+ int backlog, boost::system::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the socket.
+ bool non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the socket.
+ boost::system::error_code non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Gets the non-blocking mode of the native socket implementation.
+ bool native_non_blocking(const base_implementation_type& impl) const
+ {
+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;
+ }
+
+ // Sets the non-blocking mode of the native socket implementation.
+ boost::system::error_code native_non_blocking(base_implementation_type& impl,
+ bool mode, boost::system::error_code& ec)
+ {
+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);
+ return ec;
+ }
+
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ switch (w)
+ {
+ case socket_base::wait_read:
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_write:
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+ break;
+ case socket_base::wait_error:
+ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);
+ break;
+ default:
+ ec = boost::asio::error::invalid_argument;
+ break;
+ }
+
+ return ec;
+ }
+
+ // Asynchronously wait for the socket to become ready to read, ready to
+ // write, or to have pending error conditions.
+ template <typename Handler, typename IoExecutor>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ int op_type;
+ switch (w)
+ {
+ case socket_base::wait_read:
+ op_type = reactor::read_op;
+ break;
+ case socket_base::wait_write:
+ op_type = reactor::write_op;
+ break;
+ case socket_base::wait_error:
+ op_type = reactor::except_op;
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<
+ ConstBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_,
+ buffers, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op_ext_local<
+ MutableBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_,
+ buffers, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive(null_buffers)"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data with associated flags. Returns the number of bytes
+ // received.
+ template <typename MutableBufferSequence>
+ size_t receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags,
+ socket_base::message_flags& out_flags, boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvmsg_op_ext_local<
+ MutableBufferSequence, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers,
+ in_flags, out_flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation,
+ (in_flags & socket_base::message_out_of_band) == 0, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive_with_flags(base_implementation_type& impl,
+ const null_buffers&, socket_base::message_flags in_flags,
+ socket_base::message_flags& out_flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
+
+ // Clear out_flags, since we cannot give it any other sensible value when
+ // performing a null_buffers operation.
+ out_flags = 0;
+
+ start_op(impl,
+ (in_flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, boost::system::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ BOOST_ASIO_DECL boost::system::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_handle_type& native_socket, boost::system::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ BOOST_ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ BOOST_ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ BOOST_ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, bool is_continuation,
+ const socket_addr_type* addr, size_t addrlen);
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/reactive_socket_service_base_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+ // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext.hpp
new file mode 100644
index 0000000..1eae357
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext.hpp
@@ -0,0 +1,508 @@
+//
+// detail/reactive_socket_service_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext :
+ public execution_context_service_base<reactive_socket_service_ext<Protocol> >,
+ public reactive_socket_service_base_ext
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext(execution_context& context)
+ : execution_context_service_base<
+ reactive_socket_service_ext<Protocol> >(context),
+ reactive_socket_service_base_ext(context)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown()
+ {
+ this->base_shutdown();
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ reactive_socket_service_ext<Protocol1>&,
+ typename reactive_socket_service_ext<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers,
+ destination, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext<MutableBufferSequence,
+ endpoint_type, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol, buffers,
+ sender_endpoint, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects must be
+ // valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler, typename IoExecutor>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer_endpoint object must be valid until
+ // the accept's handler is invoked.
+ template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
+ void async_move_accept(implementation_type& impl,
+ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_move_accept_op<Protocol,
+ PeerIoExecutor, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(peer_io_ex, impl.socket_, impl.state_,
+ impl.protocol_, peer_endpoint, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, false);
+ p.v = p.p = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler, typename IoExecutor>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext_local.hpp
new file mode 100644
index 0000000..e55cfb1
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactive_socket_service_ext_local.hpp
@@ -0,0 +1,508 @@
+//
+// detail/reactive_socket_service_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_socket_accept_op.hpp>
+#include <boost/asio/detail/reactive_socket_connect_op.hpp>
+#include <boost/asio/detail/reactive_socket_recvfrom_op_ext_local.hpp>
+#include <boost/asio/detail/reactive_socket_sendto_op.hpp>
+#include <boost/asio/detail/reactive_socket_service_base_ext_local.hpp>
+#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class reactive_socket_service_ext_local :
+ public execution_context_service_base<reactive_socket_service_ext_local<Protocol> >,
+ public reactive_socket_service_base_ext_local
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_handle_type;
+
+ // The implementation type of the socket.
+ struct implementation_type :
+ reactive_socket_service_base_ext_local::base_implementation_type
+ {
+ // Default constructor.
+ implementation_type()
+ : protocol_(endpoint_type().protocol())
+ {
+ }
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+ };
+
+ // Constructor.
+ reactive_socket_service_ext_local(execution_context& context)
+ : execution_context_service_base<
+ reactive_socket_service_ext_local<Protocol> >(context),
+ reactive_socket_service_base_ext_local(context)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown()
+ {
+ this->base_shutdown();
+ }
+
+ // Move-construct a new socket implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-assign from another socket implementation.
+ void move_assign(implementation_type& impl,
+ reactive_socket_service_base_ext_local& other_service,
+ implementation_type& other_impl)
+ {
+ this->base_move_assign(impl, other_service, other_impl);
+
+ impl.protocol_ = other_impl.protocol_;
+ other_impl.protocol_ = endpoint_type().protocol();
+ }
+
+ // Move-construct a new socket implementation from another protocol type.
+ template <typename Protocol1>
+ void converting_move_construct(implementation_type& impl,
+ reactive_socket_service_ext_local<Protocol1>&,
+ typename reactive_socket_service_ext_local<
+ Protocol1>::implementation_type& other_impl)
+ {
+ this->base_move_construct(impl, other_impl);
+
+ impl.protocol_ = protocol_type(other_impl.protocol_);
+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_handle_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_handle_type native_handle(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers,
+ destination, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ const endpoint_type&, socket_base::message_flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_send_to(null_buffers)"));
+
+ start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ buffer_sequence_adapter<boost::asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
+
+ if (!ec)
+ sender_endpoint.resize(addr_len);
+
+ return bytes_recvd;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler& handler,
+ const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recvfrom_op_ext_local<MutableBufferSequence,
+ endpoint_type, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ int protocol = impl.protocol_.type();
+ p.p = new (p.v) op(impl.socket_, protocol, buffers,
+ sender_endpoint, flags, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, true, false);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler, typename IoExecutor>
+ void async_receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from(null_buffers)"));
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return ec;
+ }
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects must be
+ // valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler, typename IoExecutor>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, peer.is_open());
+ p.v = p.p = 0;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer_endpoint object must be valid until
+ // the accept's handler is invoked.
+ template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
+ void async_move_accept(implementation_type& impl,
+ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_move_accept_op<Protocol,
+ PeerIoExecutor, Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(peer_io_ex, impl.socket_, impl.state_,
+ impl.protocol_, peer_endpoint, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ start_accept_op(impl, p.p, is_continuation, false);
+ p.v = p.p = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ socket_ops::sync_connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ // Start an asynchronous connect.
+ template <typename Handler, typename IoExecutor>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint,
+ Handler& handler, const IoExecutor& io_ex)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_connect_op<Handler, IoExecutor> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler, io_ex);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_connect"));
+
+ start_connect_op(impl, p.p, is_continuation,
+ peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactor_op_ext.hpp b/implementation/helper/1.70/boost/asio/detail/reactor_op_ext.hpp
new file mode 100644
index 0000000..b267cf6
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactor_op_ext.hpp
@@ -0,0 +1,42 @@
+//
+// detail/reactor_op_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext
+ : public reactor_op
+{
+public:
+ // The destination address
+ boost::asio::ip::address da_;
+
+ reactor_op_ext(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/reactor_op_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/reactor_op_ext_local.hpp
new file mode 100644
index 0000000..cd81ffb
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/reactor_op_ext_local.hpp
@@ -0,0 +1,43 @@
+//
+// detail/reactor_op_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/reactor_op.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class reactor_op_ext_local
+ : public reactor_op
+{
+public:
+ // Credentials
+ std::uint32_t uid_;
+ std::uint32_t gid_;
+
+ reactor_op_ext_local(perform_func_type perform_func, func_type complete_func)
+ : reactor_op(perform_func, complete_func)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/socket_ops_ext.hpp b/implementation/helper/1.70/boost/asio/detail/socket_ops_ext.hpp
new file mode 100644
index 0000000..9285fed
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/socket_ops_ext.hpp
@@ -0,0 +1,62 @@
+//
+// detail/socket_ops_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/socket_ops.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec, boost::asio::ip::address& da);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ boost::asio::ip::address& da);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ boost::asio::ip::address& da);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_EXT_ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/implementation/helper/1.70/boost/asio/detail/socket_ops_ext_local.hpp b/implementation/helper/1.70/boost/asio/detail/socket_ops_ext_local.hpp
new file mode 100644
index 0000000..f494d79
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/detail/socket_ops_ext_local.hpp
@@ -0,0 +1,95 @@
+//
+// detail/socket_ops_ext_local.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs,
+ size_t count, int flags, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, bool all_empty, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recv(state_type state,
+ const weak_cancel_token_type& cancel_token, bool all_empty,
+ boost::system::error_code& ec, size_t bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ boost::system::error_code& ec,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#else // defined(BOOST_ASIO_HAS_IOCP)
+
+BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec, size_t& bytes_transferred,
+ std::uint32_t& uid, std::uint32_t& gid);
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/socket_ops_ext_local.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_EXT_LOCAL_HPP
diff --git a/implementation/helper/1.70/boost/asio/ip/udp_ext.hpp b/implementation/helper/1.70/boost/asio/ip/udp_ext.hpp
new file mode 100644
index 0000000..6ce2ac4
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/ip/udp_ext.hpp
@@ -0,0 +1,115 @@
+//
+// ip/udp_ext.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (C) 2016-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_boost or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_UDP_EXT_HPP
+#define BOOST_ASIO_IP_UDP_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/basic_datagram_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/udp.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for UDP.
+/**
+ * The boost::asio::ip::udp_ext class contains flags necessary for UDP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class udp_ext
+{
+public:
+ /// The type of a UDP endpoint.
+ typedef basic_endpoint<udp> endpoint;
+
+ /// Construct to represent the IPv4 UDP protocol.
+ static udp_ext v4()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET));
+ }
+
+ /// Construct to represent the IPv6 UDP protocol.
+ static udp_ext v6()
+ {
+ return udp_ext(BOOST_ASIO_OS_DEF(AF_INET6));
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return BOOST_ASIO_OS_DEF(SOCK_DGRAM);
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return BOOST_ASIO_OS_DEF(IPPROTO_UDP);
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The UDP socket type.
+ typedef basic_datagram_socket_ext<udp> socket;
+
+ /// The UDP resolver type.
+ typedef basic_resolver<udp> resolver;
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const udp_ext& p1, const udp_ext& p2)
+ {
+ return p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit udp_ext(int protocol_family)
+ : family_(protocol_family)
+ {
+ }
+
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_UDP_EXT_HPP
diff --git a/implementation/helper/1.70/boost/asio/local/stream_protocol_ext.hpp b/implementation/helper/1.70/boost/asio/local/stream_protocol_ext.hpp
new file mode 100644
index 0000000..7c57c62
--- /dev/null
+++ b/implementation/helper/1.70/boost/asio/local/stream_protocol_ext.hpp
@@ -0,0 +1,93 @@
+//
+// local/stream_protocol_ext.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/basic_socket_acceptor_ext.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_stream_socket_ext.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Encapsulates the flags needed for stream-oriented UNIX sockets.
+/**
+ * The boost::asio::local::stream_protocol class contains flags necessary for
+ * stream-oriented UNIX domain sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol.
+ */
+class stream_protocol_ext
+{
+public:
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_STREAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return 0;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return AF_UNIX;
+ }
+
+ /// The type of a UNIX domain endpoint.
+ typedef basic_endpoint<stream_protocol_ext> endpoint;
+
+ /// The UNIX domain socket type.
+ typedef basic_stream_socket_ext<stream_protocol_ext> socket;
+
+ /// The UNIX domain acceptor type.
+ typedef basic_socket_acceptor_ext<stream_protocol_ext> acceptor;
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+ /// The UNIX domain iostream type.
+ typedef basic_socket_iostream<stream_protocol_ext> iostream;
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+};
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_EXT_HPP
diff --git a/implementation/logging/include/android_sink_backend.hpp b/implementation/logging/include/android_sink_backend.hpp
new file mode 100644
index 0000000..defda48
--- /dev/null
+++ b/implementation/logging/include/android_sink_backend.hpp
@@ -0,0 +1,33 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ANDROID_SINK_BACKEND_HPP_
+#define VSOMEIP_V3_ANDROID_SINK_BACKEND_HPP_
+
+#include <boost/log/core.hpp>
+#include <boost/log/sinks/basic_sink_backend.hpp>
+#include <boost/log/trivial.hpp>
+
+namespace logging = boost::log;
+namespace sinks = boost::log::sinks;
+
+namespace vsomeip_v3 {
+
+class android_sink_backend :
+ public sinks::basic_sink_backend<
+ sinks::combine_requirements<
+ sinks::synchronized_feeding
+ >::type
+ > {
+public:
+ android_sink_backend();
+ virtual ~android_sink_backend();
+
+ void consume(const logging::record_view &rec);
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ANDROID_SINK_BACKEND_HPP_
diff --git a/implementation/logging/include/defines.hpp b/implementation/logging/include/defines.hpp
index 1fbaa3c..de5142d 100644
--- a/implementation/logging/include/defines.hpp
+++ b/implementation/logging/include/defines.hpp
@@ -6,9 +6,6 @@
#ifndef LOGGING_DEFINES_HPP_
#define LOGGING_DEFINES_HPP_
-#define VSOMEIP_LOG_DEFAULT_APPLICATION_ID "VSIP"
-#define VSOMEIP_LOG_DEFAULT_APPLICATION_NAME "vSomeIP application|SysInfra|IPC"
-
#define VSOMEIP_LOG_DEFAULT_CONTEXT_ID "VSIP"
#define VSOMEIP_LOG_DEFAULT_CONTEXT_NAME "vSomeIP context"
diff --git a/implementation/logging/include/dlt_sink_backend.hpp b/implementation/logging/include/dlt_sink_backend.hpp
index 58983a6..73a9e79 100644
--- a/implementation/logging/include/dlt_sink_backend.hpp
+++ b/implementation/logging/include/dlt_sink_backend.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef LOGGING_INCLUDE_DLT_SINK_BACKEND_HPP_
-#define LOGGING_INCLUDE_DLT_SINK_BACKEND_HPP_
+#ifndef VSOMEIP_V3_DLT_SINK_BACKEND_HPP_
+#define VSOMEIP_V3_DLT_SINK_BACKEND_HPP_
#ifdef USE_DLT
#include <dlt/dlt.h>
@@ -17,8 +17,7 @@
namespace logging = boost::log;
namespace sinks = boost::log::sinks;
-namespace vsomeip
-{
+namespace vsomeip_v3 {
class dlt_sink_backend :
public sinks::basic_sink_backend<
@@ -41,6 +40,6 @@ private:
#endif
};
-} /* namespace vsomeip */
+} // namespace vsomeip_v3
-#endif /* LOGGING_INCLUDE_DLT_SINK_BACKEND_HPP_ */
+#endif // VSOMEIP_V3_DLT_SINK_BACKEND_HPP_
diff --git a/implementation/logging/include/logger_impl.hpp b/implementation/logging/include/logger_impl.hpp
index 4e628af..4556f0d 100644
--- a/implementation/logging/include/logger_impl.hpp
+++ b/implementation/logging/include/logger_impl.hpp
@@ -1,70 +1,77 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_LOGGER_IMPL_HPP
-#define VSOMEIP_LOGGER_IMPL_HPP
-
-#include <memory>
-#include <string>
-
-#include <boost/log/sinks/sync_frontend.hpp>
-#include <boost/log/sinks/text_ostream_backend.hpp>
-#include <boost/log/sources/severity_logger.hpp>
-#include <boost/log/trivial.hpp>
-
-#include "logger.hpp"
-#include "dlt_sink_backend.hpp"
-
-namespace vsomeip {
-
-class configuration;
-
-BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
-BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity",
- boost::log::trivial::severity_level)
-
-typedef boost::log::sinks::synchronous_sink<
- boost::log::sinks::text_ostream_backend> sink_t;
-typedef boost::log::sinks::synchronous_sink<
- dlt_sink_backend> dlt_sink_t;
-
-class logger_impl: public logger {
-public:
- static std::shared_ptr<logger_impl> & get();
- VSOMEIP_IMPORT_EXPORT static void init(const std::shared_ptr<configuration> &_configuration);
-
- logger_impl();
-
- boost::log::sources::severity_logger_mt<
- boost::log::trivial::severity_level> & get_internal();
-
-private:
- void enable_console();
- void disable_console();
-
- void enable_file(const std::string &_path);
- void disable_file();
-
- void enable_dlt(const std::string &_app_id,
- const std::string &_context_id);
- void disable_dlt();
-
-private:
- boost::log::sources::severity_logger_mt<
- boost::log::trivial::severity_level> logger_;
- boost::log::trivial::severity_level loglevel_;
-
- boost::shared_ptr<sink_t> console_sink_;
- boost::shared_ptr<sink_t> file_sink_;
- boost::shared_ptr<dlt_sink_t> dlt_sink_;
- boost::log::core_ptr log_core_;
-
-private:
- void use_null_logger();
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_LOG_OWNER_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_LOGGER_IMPL_HPP
+#define VSOMEIP_V3_LOGGER_IMPL_HPP
+
+#include <memory>
+#include <string>
+
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/trivial.hpp>
+
+#include <vsomeip/internal/logger.hpp>
+#include "dlt_sink_backend.hpp"
+#include "android_sink_backend.hpp"
+
+namespace vsomeip_v3 {
+
+class configuration;
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity",
+ boost::log::trivial::severity_level)
+
+typedef boost::log::sinks::synchronous_sink<
+ boost::log::sinks::text_ostream_backend> sink_t;
+typedef boost::log::sinks::synchronous_sink<
+ dlt_sink_backend> dlt_sink_t;
+typedef boost::log::sinks::synchronous_sink<
+ android_sink_backend> android_sink_t;
+
+class logger_impl: public logger {
+public:
+ static std::shared_ptr<logger_impl> & get();
+ VSOMEIP_IMPORT_EXPORT static void init(const std::shared_ptr<configuration> &_configuration);
+
+ logger_impl();
+
+ boost::log::sources::severity_logger_mt<
+ boost::log::trivial::severity_level> & get_internal();
+
+private:
+ void enable_console();
+ void disable_console();
+
+ void enable_file(const std::string &_path);
+ void disable_file();
+
+ void enable_dlt(const std::string &_app_id,
+ const std::string &_context_id);
+ void disable_dlt();
+
+ void enable_android();
+ void disable_android();
+
+private:
+ boost::log::sources::severity_logger_mt<
+ boost::log::trivial::severity_level> logger_;
+ boost::log::trivial::severity_level loglevel_;
+
+ boost::shared_ptr<sink_t> console_sink_;
+ boost::shared_ptr<sink_t> file_sink_;
+ boost::shared_ptr<dlt_sink_t> dlt_sink_;
+ boost::shared_ptr<android_sink_t> android_sink_;
+ boost::log::core_ptr log_core_;
+
+private:
+ void use_null_logger();
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_LOGGER_IMPL_HPP
diff --git a/implementation/logging/src/android_sink_backend.cpp b/implementation/logging/src/android_sink_backend.cpp
new file mode 100644
index 0000000..bde7afb
--- /dev/null
+++ b/implementation/logging/src/android_sink_backend.cpp
@@ -0,0 +1,66 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/android_sink_backend.hpp"
+
+#define LOG_TAG "vSomeIP"
+
+#ifdef ANDROID
+#include <utils/Log.h>
+#endif
+
+#include <boost/log/expressions.hpp>
+#include "../include/defines.hpp"
+
+namespace expressions = boost::log::expressions;
+
+namespace vsomeip_v3
+{
+
+android_sink_backend::android_sink_backend() {
+
+}
+
+android_sink_backend::~android_sink_backend() {
+
+}
+
+BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", logging::trivial::severity_level)
+
+void android_sink_backend::consume(const logging::record_view &rec) {
+#ifdef ANDROID
+ auto message = rec[expressions::smessage].get<std::string>().c_str();
+ auto severity_level = rec[severity];
+
+ switch (*severity_level) {
+ case logging::trivial::fatal:
+ ALOGE(message);
+ break;
+ case logging::trivial::error:
+ ALOGE(message);
+ break;
+ case logging::trivial::warning:
+ ALOGW(message);
+ break;
+ case logging::trivial::info:
+ ALOGI(message);
+ break;
+ case logging::trivial::debug:
+ ALOGD(message);
+ break;
+ case logging::trivial::trace:
+ ALOGV(message);
+ break;
+ default:
+ ALOGI(message);
+ break;
+ }
+
+#else
+ (void)rec;
+#endif
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/logging/src/dlt_sink_backend.cpp b/implementation/logging/src/dlt_sink_backend.cpp
index 5b140fd..d38039c 100644
--- a/implementation/logging/src/dlt_sink_backend.cpp
+++ b/implementation/logging/src/dlt_sink_backend.cpp
@@ -14,7 +14,7 @@
namespace expressions = boost::log::expressions;
-namespace vsomeip
+namespace vsomeip_v3
{
dlt_sink_backend::dlt_sink_backend(const std::string &_app_id,
@@ -67,4 +67,4 @@ DltLogLevelType dlt_sink_backend::level_as_dlt(logging::trivial::severity_level
}
#endif
-} /* namespace vsomeip */
+} // namespace vsomeip_v3
diff --git a/implementation/logging/src/logger.cpp b/implementation/logging/src/logger.cpp
index 630362d..9e22fd0 100644
--- a/implementation/logging/src/logger.cpp
+++ b/implementation/logging/src/logger.cpp
@@ -1,14 +1,14 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/logger_impl.hpp"
-
-namespace vsomeip {
-
-std::shared_ptr<logger> logger::get() {
- return logger_impl::get();
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/logger_impl.hpp"
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<logger> logger::get() {
+ return logger_impl::get();
+}
+
+} // namespace vsomeip_v3l
diff --git a/implementation/logging/src/logger_impl.cpp b/implementation/logging/src/logger_impl.cpp
index 023dccf..ec3aa9b 100644
--- a/implementation/logging/src/logger_impl.cpp
+++ b/implementation/logging/src/logger_impl.cpp
@@ -1,191 +1,211 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <fstream>
-
-#include <boost/log/core.hpp>
-#include <boost/log/expressions.hpp>
-#include <boost/log/sources/logger.hpp>
-#include <boost/log/support/date_time.hpp>
-#include <boost/log/utility/setup/console.hpp>
-#include <boost/log/utility/setup/file.hpp>
-#include <boost/log/utility/setup/common_attributes.hpp>
-#include <boost/log/utility/exception_handler.hpp>
-#include <boost/phoenix/bind/bind_member_function.hpp>
-#include <boost/shared_ptr.hpp>
-
-// The "empty_deleter"-struct was moved from the log-package
-// to the more generic "utility"-package in V1.55. If we'd
-// use the "old" include, we get a "deprecation" warning
-// when compiling with the newer boost version. Therefore a
-// version dependent include handling is done here, which
-// can/should be removed in case GPT is updating Boost to V1.55.
-#if BOOST_VERSION < 105500
-#include <boost/log/utility/empty_deleter.hpp>
-#elif BOOST_VERSION < 105600
-#include <boost/utility/empty_deleter.hpp>
-#else
-#include <boost/core/null_deleter.hpp>
-#endif
-
-#include <vsomeip/runtime.hpp>
-
-#include "../include/logger_impl.hpp"
-#include "../../configuration/include/configuration.hpp"
-#include "../include/defines.hpp"
-
-namespace logging = boost::log;
-namespace sources = boost::log::sources;
-namespace sinks = boost::log::sinks;
-namespace keywords = boost::log::keywords;
-namespace expressions = boost::log::expressions;
-namespace attributes = boost::log::attributes;
-
-using namespace boost::log::trivial;
-
-namespace vsomeip {
-
-std::shared_ptr<logger_impl> & logger_impl::get() {
- static std::shared_ptr<logger_impl> the_logger__ = std::make_shared<
- logger_impl>();
- return the_logger__;
-}
-
-logger_impl::logger_impl()
- : loglevel_(debug),
- log_core_(logging::core::get()) {
- logging::add_common_attributes();
-}
-
-boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> &
-logger_impl::get_internal() {
- return logger_;
-}
-
-void logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
- get()->loglevel_ = _configuration->get_loglevel();
- logging::core::get()->set_exception_handler(boost::log::make_exception_suppressor());
- logging::core::get()->set_filter(
- logging::trivial::severity >= get()->loglevel_);
-
- if (_configuration->has_console_log())
- get()->enable_console();
- else
- get()->disable_console();
-
- if (_configuration->has_file_log())
- get()->enable_file(_configuration->get_logfile());
- else
- get()->disable_file();
-
- if (_configuration->has_dlt_log()) {
- std::string app_id = runtime::get_property("LogApplication");
- if (app_id == "") app_id = VSOMEIP_LOG_DEFAULT_APPLICATION_ID;
- std::string context_id = runtime::get_property("LogContext");
- if (context_id == "") context_id = VSOMEIP_LOG_DEFAULT_CONTEXT_ID;
- get()->enable_dlt(app_id, context_id);
- } else
- get()->disable_dlt();
-
- if (!_configuration->has_console_log() &&
- !_configuration->has_file_log() &&
- !_configuration->has_dlt_log()) {
- get()->use_null_logger();
- }
-}
-
-void logger_impl::enable_console() {
- if (console_sink_)
- return;
-
- auto vsomeip_log_format = expressions::stream
- << expressions::format_date_time<boost::posix_time::ptime>(
- "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
- << expressions::attr<severity_level>("Severity") << "] "
- << expressions::smessage;
-
- boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
- sinks::text_ostream_backend>();
- backend->add_stream(boost::shared_ptr<std::ostream>(&std::clog,
-#if BOOST_VERSION < 105500
- boost::log::empty_deleter()
-#elif BOOST_VERSION < 105600
- boost::empty_deleter()
-#else
- boost::null_deleter()
-#endif
- ));
-
- console_sink_ = boost::make_shared<sink_t>(backend);
- console_sink_->set_formatter(vsomeip_log_format);
- logging::core::get()->add_sink(console_sink_);
-}
-
-void logger_impl::disable_console() {
- if (console_sink_)
- logging::core::get()->remove_sink(console_sink_);
-}
-
-void logger_impl::enable_file(const std::string &_path) {
- if (file_sink_)
- return;
-
- auto vsomeip_log_format = expressions::stream
- << expressions::format_date_time<boost::posix_time::ptime>(
- "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
- << expressions::attr<severity_level>("Severity") << "] "
- << expressions::smessage;
-
- boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
- sinks::text_ostream_backend>();
- backend->add_stream(
- boost::shared_ptr<std::ostream>(
- boost::make_shared<std::ofstream>(_path)));
-
- file_sink_ = boost::make_shared<sink_t>(backend);
- file_sink_->set_formatter(vsomeip_log_format);
- logging::core::get()->add_sink(file_sink_);
-}
-
-void logger_impl::disable_file() {
- if (file_sink_)
- logging::core::get()->remove_sink(file_sink_);
-}
-
-
-void logger_impl::enable_dlt(const std::string &_app_id,
- const std::string &_context_id) {
-#ifdef USE_DLT
- if (dlt_sink_)
- return;
-
- boost::shared_ptr<dlt_sink_backend> backend = boost::make_shared<dlt_sink_backend>(_app_id,
- _context_id);
- dlt_sink_ = boost::make_shared<dlt_sink_t>(backend);
- logging::core::get()->add_sink(dlt_sink_);
-#else
- (void)_app_id;
- (void)_context_id;
-#endif
-}
-
-void logger_impl::disable_dlt() {
- if (dlt_sink_)
- logging::core::get()->remove_sink(dlt_sink_);
-}
-
-void logger_impl::use_null_logger() {
- boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
- sinks::text_ostream_backend>();
- backend->add_stream(
- boost::shared_ptr<std::ostream>(new std::ofstream("/dev/null") // TODO: how to call this on windows
- ));
-
- file_sink_ = boost::make_shared<sink_t>(backend);
- logging::core::get()->add_sink(file_sink_);
-}
-
-} // namespace vsomeip
-
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <fstream>
+
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sources/logger.hpp>
+#include <boost/log/support/date_time.hpp>
+#include <boost/log/utility/setup/console.hpp>
+#include <boost/log/utility/setup/file.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
+#include <boost/log/utility/exception_handler.hpp>
+#include <boost/phoenix/bind/bind_member_function.hpp>
+#include <boost/shared_ptr.hpp>
+
+// The "empty_deleter"-struct was moved from the log-package
+// to the more generic "utility"-package in V1.55. If we'd
+// use the "old" include, we get a "deprecation" warning
+// when compiling with the newer boost version. Therefore a
+// version dependent include handling is done here, which
+// can/should be removed in case GPT is updating Boost to V1.55.
+#if BOOST_VERSION < 105500
+#include <boost/log/utility/empty_deleter.hpp>
+#elif BOOST_VERSION < 105600
+#include <boost/utility/empty_deleter.hpp>
+#else
+#include <boost/core/null_deleter.hpp>
+#endif
+
+#include <vsomeip/runtime.hpp>
+
+#include "../include/logger_impl.hpp"
+#include "../../configuration/include/configuration.hpp"
+#include "../include/defines.hpp"
+
+namespace logging = boost::log;
+namespace sources = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+namespace expressions = boost::log::expressions;
+namespace attributes = boost::log::attributes;
+
+using namespace boost::log::trivial;
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<logger_impl> & logger_impl::get() {
+ static std::shared_ptr<logger_impl> the_logger__ = std::make_shared<
+ logger_impl>();
+ return the_logger__;
+}
+
+logger_impl::logger_impl()
+ : loglevel_(debug),
+ log_core_(logging::core::get()) {
+ logging::add_common_attributes();
+}
+
+boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> &
+logger_impl::get_internal() {
+ return logger_;
+}
+
+void logger_impl::init(const std::shared_ptr<configuration> &_configuration) {
+ get()->loglevel_ = _configuration->get_loglevel();
+ logging::core::get()->set_exception_handler(boost::log::make_exception_suppressor());
+ logging::core::get()->set_filter(
+ logging::trivial::severity >= get()->loglevel_);
+
+ if (_configuration->has_console_log()) {
+ get()->enable_console();
+#ifdef ANDROID
+ get()->enable_android();
+#endif
+ } else {
+ get()->disable_console();
+ }
+
+ if (_configuration->has_file_log())
+ get()->enable_file(_configuration->get_logfile());
+ else
+ get()->disable_file();
+
+ if (_configuration->has_dlt_log()) {
+ std::string app_id = runtime::get_property("LogApplication");
+ if (app_id == "") app_id = VSOMEIP_LOG_DEFAULT_APPLICATION_ID;
+ std::string context_id = runtime::get_property("LogContext");
+ if (context_id == "") context_id = VSOMEIP_LOG_DEFAULT_CONTEXT_ID;
+ get()->enable_dlt(app_id, context_id);
+ } else
+ get()->disable_dlt();
+
+ if (!_configuration->has_console_log() &&
+ !_configuration->has_file_log() &&
+ !_configuration->has_dlt_log()) {
+ get()->use_null_logger();
+ }
+}
+
+void logger_impl::enable_console() {
+ if (console_sink_)
+ return;
+
+ auto vsomeip_log_format = expressions::stream
+ << expressions::format_date_time<boost::posix_time::ptime>(
+ "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
+ << expressions::attr<severity_level>("Severity") << "] "
+ << expressions::smessage;
+
+ boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
+ sinks::text_ostream_backend>();
+ backend->add_stream(boost::shared_ptr<std::ostream>(&std::clog,
+#if BOOST_VERSION < 105500
+ boost::log::empty_deleter()
+#elif BOOST_VERSION < 105600
+ boost::empty_deleter()
+#else
+ boost::null_deleter()
+#endif
+ ));
+
+ console_sink_ = boost::make_shared<sink_t>(backend);
+ console_sink_->set_formatter(vsomeip_log_format);
+ logging::core::get()->add_sink(console_sink_);
+}
+
+void logger_impl::disable_console() {
+ if (console_sink_)
+ logging::core::get()->remove_sink(console_sink_);
+}
+
+void logger_impl::enable_file(const std::string &_path) {
+ if (file_sink_)
+ return;
+
+ auto vsomeip_log_format = expressions::stream
+ << expressions::format_date_time<boost::posix_time::ptime>(
+ "TimeStamp", "%Y-%m-%d %H:%M:%S.%f") << " ["
+ << expressions::attr<severity_level>("Severity") << "] "
+ << expressions::smessage;
+
+ boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
+ sinks::text_ostream_backend>();
+ backend->add_stream(
+ boost::shared_ptr<std::ostream>(
+ boost::make_shared<std::ofstream>(_path)));
+
+ file_sink_ = boost::make_shared<sink_t>(backend);
+ file_sink_->set_formatter(vsomeip_log_format);
+ logging::core::get()->add_sink(file_sink_);
+}
+
+void logger_impl::disable_file() {
+ if (file_sink_)
+ logging::core::get()->remove_sink(file_sink_);
+}
+
+
+void logger_impl::enable_dlt(const std::string &_app_id,
+ const std::string &_context_id) {
+#ifdef USE_DLT
+ if (dlt_sink_)
+ return;
+
+ boost::shared_ptr<dlt_sink_backend> backend = boost::make_shared<dlt_sink_backend>(_app_id,
+ _context_id);
+ dlt_sink_ = boost::make_shared<dlt_sink_t>(backend);
+ logging::core::get()->add_sink(dlt_sink_);
+#else
+ (void)_app_id;
+ (void)_context_id;
+#endif
+}
+
+void logger_impl::disable_dlt() {
+ if (dlt_sink_)
+ logging::core::get()->remove_sink(dlt_sink_);
+}
+
+void logger_impl::enable_android() {
+#ifdef ANDROID
+ if (android_sink_)
+ return;
+
+ boost::shared_ptr<android_sink_backend> backend = boost::make_shared<android_sink_backend>();
+ android_sink_ = boost::make_shared<android_sink_t>(backend);
+ logging::core::get()->add_sink(android_sink_);
+#endif
+}
+
+void logger_impl::disable_android() {
+ if (android_sink_)
+ logging::core::get()->remove_sink(android_sink_);
+}
+
+void logger_impl::use_null_logger() {
+ boost::shared_ptr<sinks::text_ostream_backend> backend = boost::make_shared<
+ sinks::text_ostream_backend>();
+ backend->add_stream(
+ boost::shared_ptr<std::ostream>(new std::ofstream("/dev/null") // TODO: how to call this on windows
+ ));
+
+ file_sink_ = boost::make_shared<sink_t>(backend);
+ logging::core::get()->add_sink(file_sink_);
+}
+
+} // namespace vsomeip_v3
+
diff --git a/implementation/message/include/deserializer.hpp b/implementation/message/include/deserializer.hpp
index 4c01c79..058fe94 100644
--- a/implementation/message/include/deserializer.hpp
+++ b/implementation/message/include/deserializer.hpp
@@ -1,68 +1,68 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_DESERIALIZER_HPP
-#define VSOMEIP_DESERIALIZER_HPP
-
-#include <vector>
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/primitive_types.hpp>
-
-namespace vsomeip {
-
-class message;
-
-class deserializer {
-public:
- VSOMEIP_EXPORT deserializer(std::uint32_t _buffer_shrink_threshold);
- VSOMEIP_EXPORT deserializer(byte_t *_data, std::size_t _length,
- std::uint32_t _buffer_shrink_threshold);
- VSOMEIP_EXPORT deserializer(const deserializer& _other);
- VSOMEIP_EXPORT virtual ~deserializer();
-
- VSOMEIP_EXPORT void set_data(const byte_t *_data, std::size_t _length);
- VSOMEIP_EXPORT void append_data(const byte_t *_data, std::size_t _length);
- VSOMEIP_EXPORT void drop_data(std::size_t _length);
-
- VSOMEIP_EXPORT std::size_t get_available() const;
- VSOMEIP_EXPORT std::size_t get_remaining() const;
- VSOMEIP_EXPORT void set_remaining(std::size_t _remaining);
-
- // to be used by applications to deserialize a message
- VSOMEIP_EXPORT message * deserialize_message();
-
- // to be used (internally) by objects to deserialize their members
- // Note: this needs to be encapsulated!
- VSOMEIP_EXPORT bool deserialize(uint8_t& _value);
- VSOMEIP_EXPORT bool deserialize(uint16_t& _value);
- VSOMEIP_EXPORT bool deserialize(uint32_t& _value,
- bool _omit_last_byte = false);
- VSOMEIP_EXPORT bool deserialize(uint8_t *_data, std::size_t _length);
- VSOMEIP_EXPORT bool deserialize(std::string& _target, std::size_t _length);
- VSOMEIP_EXPORT bool deserialize(std::vector<uint8_t>& _value);
-
- VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint8_t &_value) const;
- VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint16_t &_value) const;
- VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint32_t &_value) const;
-
- VSOMEIP_EXPORT void reset();
-
-#ifdef VSOMEIP_DEBUGGING
- VSOMEIP_EXPORT void show() const;
-#endif
-protected:
- std::vector<byte_t> data_;
- std::vector<byte_t>::iterator position_;
- std::size_t remaining_;
-private:
- const std::uint32_t buffer_shrink_threshold_;
- std::uint32_t shrink_count_;
-
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_DESERIALIZER_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_DESERIALIZER_HPP
+#define VSOMEIP_V3_DESERIALIZER_HPP
+
+#include <vector>
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip_v3 {
+
+class message_impl;
+
+class deserializer {
+public:
+ VSOMEIP_EXPORT deserializer(std::uint32_t _buffer_shrink_threshold);
+ VSOMEIP_EXPORT deserializer(byte_t *_data, std::size_t _length,
+ std::uint32_t _buffer_shrink_threshold);
+ VSOMEIP_EXPORT deserializer(const deserializer& _other);
+ VSOMEIP_EXPORT virtual ~deserializer();
+
+ VSOMEIP_EXPORT void set_data(const byte_t *_data, std::size_t _length);
+ VSOMEIP_EXPORT void append_data(const byte_t *_data, std::size_t _length);
+ VSOMEIP_EXPORT void drop_data(std::size_t _length);
+
+ VSOMEIP_EXPORT std::size_t get_available() const;
+ VSOMEIP_EXPORT std::size_t get_remaining() const;
+ VSOMEIP_EXPORT void set_remaining(std::size_t _remaining);
+
+ // to be used by applications to deserialize a message
+ VSOMEIP_EXPORT message_impl *deserialize_message();
+
+ // to be used (internally) by objects to deserialize their members
+ // Note: this needs to be encapsulated!
+ VSOMEIP_EXPORT bool deserialize(uint8_t& _value);
+ VSOMEIP_EXPORT bool deserialize(uint16_t& _value);
+ VSOMEIP_EXPORT bool deserialize(uint32_t& _value,
+ bool _omit_last_byte = false);
+ VSOMEIP_EXPORT bool deserialize(uint8_t *_data, std::size_t _length);
+ VSOMEIP_EXPORT bool deserialize(std::string& _target, std::size_t _length);
+ VSOMEIP_EXPORT bool deserialize(std::vector<uint8_t>& _value);
+
+ VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint8_t &_value) const;
+ VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint16_t &_value) const;
+ VSOMEIP_EXPORT bool look_ahead(std::size_t _index, uint32_t &_value) const;
+
+ VSOMEIP_EXPORT void reset();
+
+#ifdef VSOMEIP_DEBUGGING
+ VSOMEIP_EXPORT void show() const;
+#endif
+protected:
+ std::vector<byte_t> data_;
+ std::vector<byte_t>::iterator position_;
+ std::size_t remaining_;
+private:
+ const std::uint32_t buffer_shrink_threshold_;
+ std::uint32_t shrink_count_;
+
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_DESERIALIZER_HPP
diff --git a/implementation/message/include/message_base_impl.hpp b/implementation/message/include/message_base_impl.hpp
index efd5ffe..216656b 100644
--- a/implementation/message/include/message_base_impl.hpp
+++ b/implementation/message/include/message_base_impl.hpp
@@ -1,77 +1,73 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_MESSAGE_BASE_IMPL_HPP
-#define VSOMEIP_MESSAGE_BASE_IMPL_HPP
-
-#include <boost/thread.hpp>
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/message.hpp>
-
-#include "message_header_impl.hpp"
-
-namespace vsomeip {
-
-class message_base_impl
- : virtual public message_base {
-public:
- VSOMEIP_EXPORT message_base_impl();
- VSOMEIP_EXPORT virtual ~message_base_impl();
-
- VSOMEIP_EXPORT message_t get_message() const;
- VSOMEIP_EXPORT void set_message(message_t _message);
-
- VSOMEIP_EXPORT service_t get_service() const;
- VSOMEIP_EXPORT void set_service(service_t _service);
-
- VSOMEIP_EXPORT instance_t get_instance() const;
- VSOMEIP_EXPORT void set_instance(instance_t _instance);
-
- VSOMEIP_EXPORT method_t get_method() const;
- VSOMEIP_EXPORT void set_method(method_t _method);
-
- VSOMEIP_EXPORT request_t get_request() const;
-
- VSOMEIP_EXPORT client_t get_client() const;
- VSOMEIP_EXPORT void set_client(client_t _client);
-
- VSOMEIP_EXPORT session_t get_session() const;
- VSOMEIP_EXPORT void set_session(session_t _session);
-
- VSOMEIP_EXPORT protocol_version_t get_protocol_version() const;
- VSOMEIP_EXPORT void set_protocol_version(protocol_version_t _protocol_version);
-
- VSOMEIP_EXPORT interface_version_t get_interface_version() const;
- VSOMEIP_EXPORT void set_interface_version(interface_version_t _interface_version);
-
- VSOMEIP_EXPORT message_type_e get_message_type() const;
- VSOMEIP_EXPORT void set_message_type(message_type_e _type);
-
- VSOMEIP_EXPORT return_code_e get_return_code() const;
- VSOMEIP_EXPORT void set_return_code(return_code_e _code);
-
- VSOMEIP_EXPORT bool is_reliable() const;
- VSOMEIP_EXPORT void set_reliable(bool _is_reliable);
-
- VSOMEIP_EXPORT virtual bool is_initial() const;
- VSOMEIP_EXPORT virtual void set_initial(bool _is_initial);
-
- VSOMEIP_EXPORT message * get_owner() const;
- VSOMEIP_EXPORT void set_owner(message *_owner);
-
- VSOMEIP_EXPORT bool is_valid_crc() const;
- VSOMEIP_EXPORT void set_is_valid_crc(bool _is_valid_crc);
-
-protected: // members
- message_header_impl header_;
- bool is_reliable_;
- bool is_initial_;
- bool is_valid_crc_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_MESSAGE_BASE_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_MESSAGE_BASE_IMPL_HPP
+#define VSOMEIP_V3_MESSAGE_BASE_IMPL_HPP
+
+#include <boost/thread.hpp>
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/message.hpp>
+
+#include "message_header_impl.hpp"
+
+namespace vsomeip_v3 {
+
+class message_base_impl
+ : virtual public message_base {
+public:
+ VSOMEIP_EXPORT message_base_impl();
+ VSOMEIP_EXPORT virtual ~message_base_impl();
+
+ VSOMEIP_EXPORT message_t get_message() const;
+ VSOMEIP_EXPORT void set_message(message_t _message);
+
+ VSOMEIP_EXPORT service_t get_service() const;
+ VSOMEIP_EXPORT void set_service(service_t _service);
+
+ VSOMEIP_EXPORT instance_t get_instance() const;
+ VSOMEIP_EXPORT void set_instance(instance_t _instance);
+
+ VSOMEIP_EXPORT method_t get_method() const;
+ VSOMEIP_EXPORT void set_method(method_t _method);
+
+ VSOMEIP_EXPORT request_t get_request() const;
+
+ VSOMEIP_EXPORT client_t get_client() const;
+ VSOMEIP_EXPORT void set_client(client_t _client);
+
+ VSOMEIP_EXPORT session_t get_session() const;
+ VSOMEIP_EXPORT void set_session(session_t _session);
+
+ VSOMEIP_EXPORT protocol_version_t get_protocol_version() const;
+ VSOMEIP_EXPORT void set_protocol_version(protocol_version_t _protocol_version);
+
+ VSOMEIP_EXPORT interface_version_t get_interface_version() const;
+ VSOMEIP_EXPORT void set_interface_version(interface_version_t _interface_version);
+
+ VSOMEIP_EXPORT message_type_e get_message_type() const;
+ VSOMEIP_EXPORT void set_message_type(message_type_e _type);
+
+ VSOMEIP_EXPORT return_code_e get_return_code() const;
+ VSOMEIP_EXPORT void set_return_code(return_code_e _code);
+
+ VSOMEIP_EXPORT bool is_reliable() const;
+ VSOMEIP_EXPORT void set_reliable(bool _is_reliable);
+
+ VSOMEIP_EXPORT bool is_initial() const;
+ VSOMEIP_EXPORT void set_initial(bool _is_initial);
+
+ VSOMEIP_EXPORT message * get_owner() const;
+ VSOMEIP_EXPORT void set_owner(message *_owner);
+
+protected: // members
+ message_header_impl header_;
+ bool is_reliable_;
+ bool is_initial_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_MESSAGE_BASE_IMPL_HPP
diff --git a/implementation/message/include/message_header_impl.hpp b/implementation/message/include/message_header_impl.hpp
index 8cd4b00..b6e305a 100644
--- a/implementation/message/include/message_header_impl.hpp
+++ b/implementation/message/include/message_header_impl.hpp
@@ -1,47 +1,47 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_MESSAGE_HEADER_IMPL_HPP
-#define VSOMEIP_MESSAGE_HEADER_IMPL_HPP
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/primitive_types.hpp>
-#include <vsomeip/enumeration_types.hpp>
-#include <vsomeip/internal/serializable.hpp>
-
-namespace vsomeip {
-
-class message_base;
-
-class message_header_impl: virtual public serializable {
-public:
- VSOMEIP_EXPORT message_header_impl();
- VSOMEIP_EXPORT message_header_impl(const message_header_impl& _header);
-
- VSOMEIP_EXPORT bool serialize(serializer *_to) const;
- VSOMEIP_EXPORT bool deserialize(deserializer *_from);
-
- // internal
- VSOMEIP_EXPORT message_base * get_owner() const;
- VSOMEIP_EXPORT void set_owner(message_base *_owner);
-
-public:
- service_t service_;
- method_t method_;
- length_t length_;
- client_t client_;
- session_t session_;
- protocol_version_t protocol_version_;
- interface_version_t interface_version_;
- message_type_e type_;
- return_code_e code_;
-
- instance_t instance_;
- message_base *owner_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_MESSAGE_HEADER_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_MESSAGE_HEADER_IMPL_HPP
+#define VSOMEIP_V3_MESSAGE_HEADER_IMPL_HPP
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/enumeration_types.hpp>
+#include <vsomeip/internal/serializable.hpp>
+
+namespace vsomeip_v3 {
+
+class message_base;
+
+class message_header_impl: virtual public serializable {
+public:
+ VSOMEIP_EXPORT message_header_impl();
+ VSOMEIP_EXPORT message_header_impl(const message_header_impl& _header);
+
+ VSOMEIP_EXPORT bool serialize(serializer *_to) const;
+ VSOMEIP_EXPORT bool deserialize(deserializer *_from);
+
+ // internal
+ VSOMEIP_EXPORT message_base * get_owner() const;
+ VSOMEIP_EXPORT void set_owner(message_base *_owner);
+
+public:
+ service_t service_;
+ method_t method_;
+ length_t length_;
+ client_t client_;
+ session_t session_;
+ protocol_version_t protocol_version_;
+ interface_version_t interface_version_;
+ message_type_e type_;
+ return_code_e code_;
+
+ instance_t instance_;
+ message_base *owner_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_MESSAGE_HEADER_IMPL_HPP
diff --git a/implementation/message/include/message_impl.hpp b/implementation/message/include/message_impl.hpp
index a10afe5..b121c46 100644
--- a/implementation/message/include/message_impl.hpp
+++ b/implementation/message/include/message_impl.hpp
@@ -1,50 +1,64 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_MESSAGE_IMPL_HPP
-#define VSOMEIP_MESSAGE_IMPL_HPP
-
-#include <memory>
-
-#include <vsomeip/export.hpp>
-#include "message_base_impl.hpp"
-
-# if _MSC_VER >= 1300
-/*
-* Diamond inheritance is used for the vsomeip::message_base base class.
-* The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class"
-* A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class
-* by using a common abstract base class. This is also called cross delegation.
-*/
-# pragma warning( disable : 4250 )
-# endif
-
-namespace vsomeip {
-
-class payload;
-
-class message_impl
- : virtual public message,
- virtual public message_base_impl {
-public:
- VSOMEIP_EXPORT message_impl();
- VSOMEIP_EXPORT virtual ~message_impl();
-
- VSOMEIP_EXPORT length_t get_length() const;
- VSOMEIP_EXPORT void set_length(length_t _length);
-
- VSOMEIP_EXPORT std::shared_ptr< payload > get_payload() const;
- VSOMEIP_EXPORT void set_payload(std::shared_ptr< payload > _payload);
-
- VSOMEIP_EXPORT bool serialize(serializer *_to) const;
- VSOMEIP_EXPORT bool deserialize(deserializer *_from);
-
-protected: // members
- std::shared_ptr< payload > payload_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_MESSAGE_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_MESSAGE_IMPL_HPP
+#define VSOMEIP_V3_MESSAGE_IMPL_HPP
+
+#include <memory>
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+#include "message_base_impl.hpp"
+
+# if _MSC_VER >= 1300
+/*
+* Diamond inheritance is used for the vsomeip::message_base base class.
+* The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class"
+* A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class
+* by using a common abstract base class. This is also called cross delegation.
+*/
+# pragma warning( disable : 4250 )
+# endif
+
+namespace vsomeip_v3 {
+
+class payload;
+
+class message_impl
+ : virtual public message,
+ virtual public message_base_impl {
+public:
+ VSOMEIP_EXPORT message_impl();
+ VSOMEIP_EXPORT virtual ~message_impl();
+
+ VSOMEIP_EXPORT length_t get_length() const;
+ VSOMEIP_EXPORT void set_length(length_t _length);
+
+ VSOMEIP_EXPORT std::shared_ptr< payload > get_payload() const;
+ VSOMEIP_EXPORT void set_payload(std::shared_ptr< payload > _payload);
+
+ VSOMEIP_EXPORT bool serialize(serializer *_to) const;
+ VSOMEIP_EXPORT bool deserialize(deserializer *_from);
+
+ VSOMEIP_EXPORT uint8_t get_check_result() const;
+ VSOMEIP_EXPORT void set_check_result(uint8_t _check_result);
+ VSOMEIP_EXPORT bool is_valid_crc() const;
+
+ VSOMEIP_EXPORT uid_t get_uid() const;
+ VSOMEIP_EXPORT void set_uid(uid_t _uid);
+
+ VSOMEIP_EXPORT gid_t get_gid() const;
+ VSOMEIP_EXPORT void set_gid(gid_t _gid);
+
+protected: // members
+ std::shared_ptr< payload > payload_;
+ uint8_t check_result_;
+ uid_t uid_;
+ gid_t gid_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_MESSAGE_IMPL_HPP
diff --git a/implementation/message/include/payload_impl.hpp b/implementation/message/include/payload_impl.hpp
index 2eb67e9..8ea256c 100644
--- a/implementation/message/include/payload_impl.hpp
+++ b/implementation/message/include/payload_impl.hpp
@@ -1,46 +1,46 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_PAYLOAD_IMPL_HPP
-#define VSOMEIP_PAYLOAD_IMPL_HPP
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/payload.hpp>
-
-namespace vsomeip {
-
-class serializer;
-class deserializer;
-
-class payload_impl: public payload {
-public:
- VSOMEIP_EXPORT payload_impl();
- VSOMEIP_EXPORT payload_impl(const byte_t *_data, uint32_t _size);
- VSOMEIP_EXPORT payload_impl(const std::vector< byte_t > &_data);
- VSOMEIP_EXPORT payload_impl(const payload_impl& _payload);
- VSOMEIP_EXPORT virtual ~payload_impl();
-
- VSOMEIP_EXPORT bool operator == (const payload &_other);
-
- VSOMEIP_EXPORT byte_t * get_data();
- VSOMEIP_EXPORT const byte_t * get_data() const;
- VSOMEIP_EXPORT length_t get_length() const;
-
- VSOMEIP_EXPORT void set_capacity(length_t _capacity);
-
- VSOMEIP_EXPORT void set_data(const byte_t *_data, length_t _length);
- VSOMEIP_EXPORT void set_data(const std::vector< byte_t > &_data);
- VSOMEIP_EXPORT void set_data(std::vector< byte_t > &&_data);
-
- VSOMEIP_EXPORT bool serialize(serializer *_to) const;
- VSOMEIP_EXPORT bool deserialize(deserializer *_from);
-
-private:
- std::vector<byte_t> data_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_PAYLOAD_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_PAYLOAD_IMPL_HPP
+#define VSOMEIP_V3_PAYLOAD_IMPL_HPP
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/payload.hpp>
+
+namespace vsomeip_v3 {
+
+class serializer;
+class deserializer;
+
+class payload_impl: public payload {
+public:
+ VSOMEIP_EXPORT payload_impl();
+ VSOMEIP_EXPORT payload_impl(const byte_t *_data, uint32_t _size);
+ VSOMEIP_EXPORT payload_impl(const std::vector< byte_t > &_data);
+ VSOMEIP_EXPORT payload_impl(const payload_impl& _payload);
+ VSOMEIP_EXPORT virtual ~payload_impl();
+
+ VSOMEIP_EXPORT bool operator == (const payload &_other);
+
+ VSOMEIP_EXPORT byte_t * get_data();
+ VSOMEIP_EXPORT const byte_t * get_data() const;
+ VSOMEIP_EXPORT length_t get_length() const;
+
+ VSOMEIP_EXPORT void set_capacity(length_t _capacity);
+
+ VSOMEIP_EXPORT void set_data(const byte_t *_data, length_t _length);
+ VSOMEIP_EXPORT void set_data(const std::vector< byte_t > &_data);
+ VSOMEIP_EXPORT void set_data(std::vector< byte_t > &&_data);
+
+ VSOMEIP_EXPORT bool serialize(serializer *_to) const;
+ VSOMEIP_EXPORT bool deserialize(deserializer *_from);
+
+private:
+ std::vector<byte_t> data_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_PAYLOAD_IMPL_HPP
diff --git a/implementation/message/include/serializer.hpp b/implementation/message/include/serializer.hpp
index c57797e..ff99679 100644
--- a/implementation/message/include/serializer.hpp
+++ b/implementation/message/include/serializer.hpp
@@ -1,50 +1,50 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SERIALIZER_HPP
-#define VSOMEIP_SERIALIZER_HPP
-
-#include <vector>
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/primitive_types.hpp>
-
-namespace vsomeip {
-
-class serializable;
-
-class VSOMEIP_IMPORT_EXPORT serializer {
-public:
- serializer(std::uint32_t _buffer_shrink_threshold);
- virtual ~serializer();
-
- bool serialize(const serializable *_from);
-
- bool serialize(const uint8_t _value);
- bool serialize(const uint16_t _value);
- bool serialize(const uint32_t _value, bool _omit_last_byte = false);
- bool serialize(const uint8_t *_data, uint32_t _length);
- bool serialize(const std::vector<byte_t> &_data);
-
- virtual const uint8_t * get_data() const;
- virtual uint32_t get_capacity() const;
- virtual uint32_t get_size() const;
-
- virtual void set_data(uint8_t *_data, uint32_t _capacity);
-
- virtual void reset();
-
-#ifdef VSOMEIP_DEBUGGING
- virtual void show();
-#endif
-private:
- std::vector<byte_t> data_;
- std::uint32_t shrink_count_;
- std::uint32_t buffer_shrink_threshold_;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERIALIZER_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SERIALIZER_HPP
+#define VSOMEIP_V3_SERIALIZER_HPP
+
+#include <vector>
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip_v3 {
+
+class serializable;
+
+class VSOMEIP_IMPORT_EXPORT serializer {
+public:
+ serializer(std::uint32_t _buffer_shrink_threshold);
+ virtual ~serializer();
+
+ bool serialize(const serializable *_from);
+
+ bool serialize(const uint8_t _value);
+ bool serialize(const uint16_t _value);
+ bool serialize(const uint32_t _value, bool _omit_last_byte = false);
+ bool serialize(const uint8_t *_data, uint32_t _length);
+ bool serialize(const std::vector<byte_t> &_data);
+
+ virtual const uint8_t * get_data() const;
+ virtual uint32_t get_capacity() const;
+ virtual uint32_t get_size() const;
+
+ virtual void set_data(uint8_t *_data, uint32_t _capacity);
+
+ virtual void reset();
+
+#ifdef VSOMEIP_DEBUGGING
+ virtual void show();
+#endif
+private:
+ std::vector<byte_t> data_;
+ std::uint32_t shrink_count_;
+ std::uint32_t buffer_shrink_threshold_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SERIALIZER_IMPL_HPP
diff --git a/implementation/message/src/deserializer.cpp b/implementation/message/src/deserializer.cpp
index b416199..c7464cb 100644
--- a/implementation/message/src/deserializer.cpp
+++ b/implementation/message/src/deserializer.cpp
@@ -1,235 +1,237 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <cstring>
-
-#ifdef VSOMEIP_DEBUGGING
-#include <iomanip>
-#include <sstream>
-#endif
-
-#include "../include/message_impl.hpp"
-#include "../include/deserializer.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/byteorder.hpp"
-
-namespace vsomeip {
-
-deserializer::deserializer(std::uint32_t _buffer_shrink_threshold)
- : position_(data_.begin()),
- remaining_(0),
- buffer_shrink_threshold_(_buffer_shrink_threshold),
- shrink_count_(0) {
-}
-
-deserializer::deserializer(byte_t *_data, std::size_t _length,
- std::uint32_t _buffer_shrink_threshold)
- : data_(_data, _data + _length),
- position_(data_.begin()),
- remaining_(_length),
- buffer_shrink_threshold_(_buffer_shrink_threshold),
- shrink_count_(0) {
-}
-
-deserializer::deserializer(const deserializer &_other)
- : data_(_other.data_),
- position_(_other.position_),
- remaining_(_other.remaining_),
- buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
- shrink_count_(_other.shrink_count_) {
-}
-
-deserializer::~deserializer() {
-}
-
-std::size_t deserializer::get_available() const {
- return data_.size();
-}
-
-std::size_t deserializer::get_remaining() const {
- return remaining_;
-}
-
-void deserializer::set_remaining(std::size_t _remaining) {
- remaining_ = _remaining;
-}
-
-bool deserializer::deserialize(uint8_t& _value) {
- if (0 == remaining_)
- return false;
-
- _value = *position_++;
-
- remaining_--;
- return true;
-}
-
-bool deserializer::deserialize(uint16_t& _value) {
- if (2 > remaining_)
- return false;
-
- uint8_t byte0, byte1;
- byte0 = *position_++;
- byte1 = *position_++;
- remaining_ -= 2;
-
- _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1);
-
- return true;
-}
-
-bool deserializer::deserialize(uint32_t &_value, bool _omit_last_byte) {
- if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
- return false;
-
- uint8_t byte0 = 0, byte1, byte2, byte3;
- if (!_omit_last_byte) {
- byte0 = *position_++;
- remaining_--;
- }
- byte1 = *position_++;
- byte2 = *position_++;
- byte3 = *position_++;
- remaining_ -= 3;
-
- _value = VSOMEIP_BYTES_TO_LONG(
- byte0, byte1, byte2, byte3);
-
- return true;
-}
-
-bool deserializer::deserialize(uint8_t *_data, std::size_t _length) {
- if (_length > remaining_)
- return false;
-
- std::memcpy(_data, &data_[position_ - data_.begin()], _length);
- position_ += _length;
- remaining_ -= _length;
-
- return true;
-}
-
-bool deserializer::deserialize(std::string& _target, std::size_t _length) {
- if (_length > remaining_ || _length > _target.capacity()) {
- return false;
- }
- _target.assign(position_, position_ + _length);
- position_ += _length;
- remaining_ -= _length;
-
- return true;
-}
-
-bool deserializer::deserialize(std::vector< uint8_t >& _value) {
- if (_value.capacity() > remaining_)
- return false;
-
- _value.assign(position_, position_ + _value.capacity());
- position_ += _value.capacity();
- remaining_ -= _value.capacity();
-
- return true;
-}
-
-bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const {
- if (_index >= data_.size())
- return false;
-
- _value = *(position_ + _index);
-
- return true;
-}
-
-bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const {
- if (_index+1 >= data_.size())
- return false;
-
- std::vector< uint8_t >::iterator i = position_ + _index;
- _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1));
-
- return true;
-}
-
-bool deserializer::look_ahead(std::size_t _index, uint32_t &_value) const {
- if (_index+3 >= data_.size())
- return false;
-
- std::vector< uint8_t >::const_iterator i = position_ + _index;
- _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3));
-
- return true;
-}
-
-message * deserializer::deserialize_message() {
- message_impl* deserialized_message = new message_impl;
- if (0 != deserialized_message) {
- if (false == deserialized_message->deserialize(this)) {
- VSOMEIP_ERROR << "SOME/IP message deserialization failed!";
- delete deserialized_message;
- deserialized_message = nullptr;
- }
- }
-
- return deserialized_message;
-}
-
-void deserializer::set_data(const byte_t *_data, std::size_t _length) {
- if (0 != _data) {
- data_.assign(_data, _data + _length);
- position_ = data_.begin();
- remaining_ = data_.end() - position_;
- } else {
- data_.clear();
- position_ = data_.end();
- remaining_ = 0;
- }
-}
-
-void deserializer::append_data(const byte_t *_data, std::size_t _length) {
- std::size_t offset = (position_ - data_.begin());
- data_.insert(data_.end(), _data, _data + _length);
- position_ = data_.begin() + offset;
- remaining_ += _length;
-}
-
-void deserializer::drop_data(std::size_t _length) {
- if (position_ + _length < data_.end())
- position_ += _length;
- else
- position_ = data_.end();
-}
-
-void deserializer::reset() {
- if (buffer_shrink_threshold_) {
- if (data_.size() < (data_.capacity() >> 1)) {
- shrink_count_++;
- } else {
- shrink_count_ = 0;
- }
- }
- data_.clear();
- position_ = data_.begin();
- remaining_ = data_.size();
- if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
- data_.shrink_to_fit();
- shrink_count_ = 0;
- }
-}
-
-#ifdef VSOMEIP_DEBUGGING
-void deserializer::show() const {
- std::stringstream its_message;
- its_message << "("
- << std::hex << std::setw(2) << std::setfill('0')
- << (int)*position_ << ", "
- << std:: dec << remaining_ << ") ";
- for (int i = 0; i < data_.size(); ++i)
- its_message << std::hex << std::setw(2) << std::setfill('0')
- << (int)data_[i] << " ";
- VSOMEIP_INFO << its_message;
-}
-#endif
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstring>
+
+#ifdef VSOMEIP_DEBUGGING
+#include <iomanip>
+#include <sstream>
+#endif
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/message_impl.hpp"
+#include "../include/deserializer.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+namespace vsomeip_v3 {
+
+deserializer::deserializer(std::uint32_t _buffer_shrink_threshold)
+ : position_(data_.begin()),
+ remaining_(0),
+ buffer_shrink_threshold_(_buffer_shrink_threshold),
+ shrink_count_(0) {
+}
+
+deserializer::deserializer(byte_t *_data, std::size_t _length,
+ std::uint32_t _buffer_shrink_threshold)
+ : data_(_data, _data + _length),
+ position_(data_.begin()),
+ remaining_(_length),
+ buffer_shrink_threshold_(_buffer_shrink_threshold),
+ shrink_count_(0) {
+}
+
+deserializer::deserializer(const deserializer &_other)
+ : data_(_other.data_),
+ position_(_other.position_),
+ remaining_(_other.remaining_),
+ buffer_shrink_threshold_(_other.buffer_shrink_threshold_),
+ shrink_count_(_other.shrink_count_) {
+}
+
+deserializer::~deserializer() {
+}
+
+std::size_t deserializer::get_available() const {
+ return data_.size();
+}
+
+std::size_t deserializer::get_remaining() const {
+ return remaining_;
+}
+
+void deserializer::set_remaining(std::size_t _remaining) {
+ remaining_ = _remaining;
+}
+
+bool deserializer::deserialize(uint8_t& _value) {
+ if (0 == remaining_)
+ return false;
+
+ _value = *position_++;
+
+ remaining_--;
+ return true;
+}
+
+bool deserializer::deserialize(uint16_t& _value) {
+ if (2 > remaining_)
+ return false;
+
+ uint8_t byte0, byte1;
+ byte0 = *position_++;
+ byte1 = *position_++;
+ remaining_ -= 2;
+
+ _value = VSOMEIP_BYTES_TO_WORD(byte0, byte1);
+
+ return true;
+}
+
+bool deserializer::deserialize(uint32_t &_value, bool _omit_last_byte) {
+ if (3 > remaining_ || (!_omit_last_byte && 4 > remaining_))
+ return false;
+
+ uint8_t byte0 = 0, byte1, byte2, byte3;
+ if (!_omit_last_byte) {
+ byte0 = *position_++;
+ remaining_--;
+ }
+ byte1 = *position_++;
+ byte2 = *position_++;
+ byte3 = *position_++;
+ remaining_ -= 3;
+
+ _value = VSOMEIP_BYTES_TO_LONG(
+ byte0, byte1, byte2, byte3);
+
+ return true;
+}
+
+bool deserializer::deserialize(uint8_t *_data, std::size_t _length) {
+ if (_length > remaining_)
+ return false;
+
+ std::memcpy(_data, &data_[static_cast<std::vector<byte_t>::size_type>(position_ - data_.begin())], _length);
+ position_ += static_cast<std::vector<byte_t>::difference_type>(_length);
+ remaining_ -= _length;
+
+ return true;
+}
+
+bool deserializer::deserialize(std::string& _target, std::size_t _length) {
+ if (_length > remaining_ || _length > _target.capacity()) {
+ return false;
+ }
+ _target.assign(position_, position_ + _length);
+ position_ += _length;
+ remaining_ -= _length;
+
+ return true;
+}
+
+bool deserializer::deserialize(std::vector< uint8_t >& _value) {
+ if (_value.capacity() > remaining_)
+ return false;
+
+ _value.assign(position_, position_
+ + static_cast<std::vector<byte_t>::difference_type>(_value.capacity()));
+ position_ += static_cast<std::vector<byte_t>::difference_type>(_value.capacity());
+ remaining_ -= _value.capacity();
+
+ return true;
+}
+
+bool deserializer::look_ahead(std::size_t _index, uint8_t &_value) const {
+ if (_index >= data_.size())
+ return false;
+
+ _value = *(position_ + static_cast<std::vector<byte_t>::difference_type>(_index));
+
+ return true;
+}
+
+bool deserializer::look_ahead(std::size_t _index, uint16_t &_value) const {
+ if (_index+1 >= data_.size())
+ return false;
+
+ std::vector< uint8_t >::iterator i = position_ +
+ static_cast<std::vector<byte_t>::difference_type>(_index);
+ _value = VSOMEIP_BYTES_TO_WORD(*i, *(i+1));
+
+ return true;
+}
+
+bool deserializer::look_ahead(std::size_t _index, uint32_t &_value) const {
+ if (_index+3 >= data_.size())
+ return false;
+
+ std::vector< uint8_t >::const_iterator i = position_ + static_cast<std::vector<byte_t>::difference_type>(_index);
+ _value = VSOMEIP_BYTES_TO_LONG(*i, *(i+1), *(i+2), *(i+3));
+
+ return true;
+}
+
+message_impl * deserializer::deserialize_message() {
+ message_impl* deserialized_message = new message_impl;
+ if (0 != deserialized_message) {
+ if (false == deserialized_message->deserialize(this)) {
+ VSOMEIP_ERROR << "SOME/IP message deserialization failed!";
+ delete deserialized_message;
+ deserialized_message = nullptr;
+ }
+ }
+
+ return deserialized_message;
+}
+
+void deserializer::set_data(const byte_t *_data, std::size_t _length) {
+ if (0 != _data) {
+ data_.assign(_data, _data + _length);
+ position_ = data_.begin();
+ remaining_ = static_cast<std::vector<byte_t>::size_type>(data_.end() - position_);
+ } else {
+ data_.clear();
+ position_ = data_.end();
+ remaining_ = 0;
+ }
+}
+
+void deserializer::append_data(const byte_t *_data, std::size_t _length) {
+ std::vector<byte_t>::difference_type offset = (position_ - data_.begin());
+ data_.insert(data_.end(), _data, _data + _length);
+ position_ = data_.begin() + offset;
+ remaining_ += _length;
+}
+
+void deserializer::drop_data(std::size_t _length) {
+ if (position_ + static_cast<std::vector<byte_t>::difference_type>(_length) < data_.end())
+ position_ += static_cast<std::vector<byte_t>::difference_type>(_length);
+ else
+ position_ = data_.end();
+}
+
+void deserializer::reset() {
+ if (buffer_shrink_threshold_) {
+ if (data_.size() < (data_.capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ data_.clear();
+ position_ = data_.begin();
+ remaining_ = data_.size();
+ if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
+ data_.shrink_to_fit();
+ shrink_count_ = 0;
+ }
+}
+
+#ifdef VSOMEIP_DEBUGGING
+void deserializer::show() const {
+ std::stringstream its_message;
+ its_message << "("
+ << std::hex << std::setw(2) << std::setfill('0')
+ << (int)*position_ << ", "
+ << std:: dec << remaining_ << ") ";
+ for (int i = 0; i < data_.size(); ++i)
+ its_message << std::hex << std::setw(2) << std::setfill('0')
+ << (int)data_[i] << " ";
+ VSOMEIP_INFO << its_message;
+}
+#endif
+
+} // namespace vsomeip_v3
diff --git a/implementation/message/src/message_base_impl.cpp b/implementation/message/src/message_base_impl.cpp
index e32a914..43295c4 100644
--- a/implementation/message/src/message_base_impl.cpp
+++ b/implementation/message/src/message_base_impl.cpp
@@ -1,131 +1,122 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/message_impl.hpp"
-#include "../../utility/include/byteorder.hpp"
-
-namespace vsomeip {
-
-message_base_impl::message_base_impl()
- : is_reliable_(false),
- is_initial_(false),
- is_valid_crc_(true) {
- header_.set_owner(this);
-}
-
-message_base_impl::~message_base_impl() {
-}
-
-// header interface
-message_t message_base_impl::get_message() const {
- return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_);
-}
-
-void message_base_impl::set_message(message_t _message) {
- header_.service_ = VSOMEIP_LONG_WORD0(_message);
- header_.method_ = VSOMEIP_LONG_WORD1(_message);
-}
-
-service_t message_base_impl::get_service() const {
- return header_.service_;
-}
-
-void message_base_impl::set_service(service_t _service) {
- header_.service_ = _service;
-}
-
-instance_t message_base_impl::get_instance() const {
- return header_.instance_;
-}
-
-void message_base_impl::set_instance(instance_t _instance) {
- header_.instance_ = _instance;
-}
-
-method_t message_base_impl::get_method() const {
- return header_.method_;
-}
-
-void message_base_impl::set_method(method_t _method) {
- header_.method_ = _method;
-}
-
-request_t message_base_impl::get_request() const {
- return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_);
-}
-
-client_t message_base_impl::get_client() const {
- return header_.client_;
-}
-
-void message_base_impl::set_client(client_t _client) {
- header_.client_ = _client;
-}
-
-session_t message_base_impl::get_session() const {
- return header_.session_;
-}
-
-void message_base_impl::set_session(session_t _session) {
- header_.session_ = _session;
-}
-
-protocol_version_t message_base_impl::get_protocol_version() const {
- return header_.protocol_version_;
-}
-
-void message_base_impl::set_protocol_version(protocol_version_t _protocol_version) {
- header_.protocol_version_ = _protocol_version;
-}
-
-interface_version_t message_base_impl::get_interface_version() const {
- return header_.interface_version_;
-}
-
-void message_base_impl::set_interface_version(interface_version_t _interface_version) {
- header_.interface_version_ = _interface_version;
-}
-
-message_type_e message_base_impl::get_message_type() const {
- return header_.type_;
-}
-
-void message_base_impl::set_message_type(message_type_e _type) {
- header_.type_ = _type;
-}
-
-return_code_e message_base_impl::get_return_code() const {
- return header_.code_;
-}
-
-void message_base_impl::set_return_code(return_code_e _code) {
- header_.code_ = _code;
-}
-
-bool message_base_impl::is_reliable() const {
- return is_reliable_;
-}
-
-void message_base_impl::set_reliable(bool _is_reliable) {
- is_reliable_ = _is_reliable;
-}
-
-bool message_base_impl::is_initial() const {
- return is_initial_;
-}
-void message_base_impl::set_initial(bool _is_initial) {
- is_initial_ = _is_initial;
-}
-
-bool message_base_impl::is_valid_crc() const {
- return is_valid_crc_;
-}
-
-void message_base_impl::set_is_valid_crc(bool _is_valid_crc) {
- is_valid_crc_ = _is_valid_crc;
-}
-
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/message_impl.hpp"
+#include "../../utility/include/byteorder.hpp"
+
+namespace vsomeip_v3 {
+
+message_base_impl::message_base_impl()
+ : is_reliable_(false),
+ is_initial_(false) {
+ header_.set_owner(this);
+}
+
+message_base_impl::~message_base_impl() {
+}
+
+// header interface
+message_t message_base_impl::get_message() const {
+ return VSOMEIP_WORDS_TO_LONG(header_.service_, header_.method_);
+}
+
+void message_base_impl::set_message(message_t _message) {
+ header_.service_ = VSOMEIP_LONG_WORD0(_message);
+ header_.method_ = VSOMEIP_LONG_WORD1(_message);
+}
+
+service_t message_base_impl::get_service() const {
+ return header_.service_;
+}
+
+void message_base_impl::set_service(service_t _service) {
+ header_.service_ = _service;
+}
+
+instance_t message_base_impl::get_instance() const {
+ return header_.instance_;
+}
+
+void message_base_impl::set_instance(instance_t _instance) {
+ header_.instance_ = _instance;
+}
+
+method_t message_base_impl::get_method() const {
+ return header_.method_;
+}
+
+void message_base_impl::set_method(method_t _method) {
+ header_.method_ = _method;
+}
+
+request_t message_base_impl::get_request() const {
+ return VSOMEIP_WORDS_TO_LONG(header_.client_, header_.session_);
+}
+
+client_t message_base_impl::get_client() const {
+ return header_.client_;
+}
+
+void message_base_impl::set_client(client_t _client) {
+ header_.client_ = _client;
+}
+
+session_t message_base_impl::get_session() const {
+ return header_.session_;
+}
+
+void message_base_impl::set_session(session_t _session) {
+ header_.session_ = _session;
+}
+
+protocol_version_t message_base_impl::get_protocol_version() const {
+ return header_.protocol_version_;
+}
+
+void message_base_impl::set_protocol_version(protocol_version_t _protocol_version) {
+ header_.protocol_version_ = _protocol_version;
+}
+
+interface_version_t message_base_impl::get_interface_version() const {
+ return header_.interface_version_;
+}
+
+void message_base_impl::set_interface_version(interface_version_t _interface_version) {
+ header_.interface_version_ = _interface_version;
+}
+
+message_type_e message_base_impl::get_message_type() const {
+ return header_.type_;
+}
+
+void message_base_impl::set_message_type(message_type_e _type) {
+ header_.type_ = _type;
+}
+
+return_code_e message_base_impl::get_return_code() const {
+ return header_.code_;
+}
+
+void message_base_impl::set_return_code(return_code_e _code) {
+ header_.code_ = _code;
+}
+
+bool message_base_impl::is_reliable() const {
+ return is_reliable_;
+}
+
+void message_base_impl::set_reliable(bool _is_reliable) {
+ is_reliable_ = _is_reliable;
+}
+
+bool message_base_impl::is_initial() const {
+ return is_initial_;
+}
+
+void message_base_impl::set_initial(bool _is_initial) {
+ is_initial_ = _is_initial;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/message/src/message_header_impl.cpp b/implementation/message/src/message_header_impl.cpp
index 3965453..27950e7 100644
--- a/implementation/message/src/message_header_impl.cpp
+++ b/implementation/message/src/message_header_impl.cpp
@@ -1,80 +1,80 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <vsomeip/defines.hpp>
-
-#include "../include/message_base_impl.hpp"
-#include "../include/message_header_impl.hpp"
-#include "../include/serializer.hpp"
-#include "../include/deserializer.hpp"
-
-namespace vsomeip {
-
-message_header_impl::message_header_impl()
- : service_(0x0), method_(0x0), length_(0x0),
- client_(0x0), session_(0x0),
- protocol_version_(0x1), interface_version_(0x0),
- type_(message_type_e::MT_UNKNOWN),
- code_(return_code_e::E_UNKNOWN),
- instance_(0x0), owner_(0x0) {
-}
-
-message_header_impl::message_header_impl(const message_header_impl &_header)
- : service_(_header.service_), method_(_header.method_),
- length_(_header.length_),
- client_(_header.client_), session_(_header.session_),
- protocol_version_(_header.protocol_version_),
- interface_version_(_header.interface_version_),
- type_(_header.type_),
- code_(_header.code_),
- instance_(_header.instance_), owner_(_header.owner_) {
-}
-
-bool message_header_impl::serialize(serializer *_to) const {
- return (0 != _to
- && _to->serialize(service_)
- && _to->serialize(method_)
- && _to->serialize(owner_->get_length())
- && _to->serialize(client_)
- && _to->serialize(session_)
- && _to->serialize(protocol_version_)
- && _to->serialize(interface_version_)
- && _to->serialize(static_cast<uint8_t>(type_))
- && _to->serialize(static_cast<uint8_t>(code_)));
-}
-
-bool message_header_impl::deserialize(deserializer *_from) {
- bool is_successful;
-
- uint8_t tmp_message_type, tmp_return_code;
-
- is_successful = (0 != _from
- && _from->deserialize(service_)
- && _from->deserialize(method_)
- && _from->deserialize(length_)
- && _from->deserialize(client_)
- && _from->deserialize(session_)
- && _from->deserialize(protocol_version_)
- && _from->deserialize(interface_version_)
- && _from->deserialize(tmp_message_type)
- && _from->deserialize(tmp_return_code));
-
- if (is_successful) {
- type_ = static_cast< message_type_e >(tmp_message_type);
- code_ = static_cast< return_code_e >(tmp_return_code);
- }
-
- return is_successful;
-}
-
-message_base * message_header_impl::get_owner() const {
- return owner_;
-}
-
-void message_header_impl::set_owner(message_base *_owner) {
- owner_ = _owner;
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/defines.hpp>
+
+#include "../include/message_base_impl.hpp"
+#include "../include/message_header_impl.hpp"
+#include "../include/serializer.hpp"
+#include "../include/deserializer.hpp"
+
+namespace vsomeip_v3 {
+
+message_header_impl::message_header_impl()
+ : service_(0x0), method_(0x0), length_(0x0),
+ client_(0x0), session_(0x0),
+ protocol_version_(0x1), interface_version_(0x0),
+ type_(message_type_e::MT_UNKNOWN),
+ code_(return_code_e::E_UNKNOWN),
+ instance_(0x0), owner_(0x0) {
+}
+
+message_header_impl::message_header_impl(const message_header_impl &_header)
+ : service_(_header.service_), method_(_header.method_),
+ length_(_header.length_),
+ client_(_header.client_), session_(_header.session_),
+ protocol_version_(_header.protocol_version_),
+ interface_version_(_header.interface_version_),
+ type_(_header.type_),
+ code_(_header.code_),
+ instance_(_header.instance_), owner_(_header.owner_) {
+}
+
+bool message_header_impl::serialize(serializer *_to) const {
+ return (0 != _to
+ && _to->serialize(service_)
+ && _to->serialize(method_)
+ && _to->serialize(owner_->get_length())
+ && _to->serialize(client_)
+ && _to->serialize(session_)
+ && _to->serialize(protocol_version_)
+ && _to->serialize(interface_version_)
+ && _to->serialize(static_cast<uint8_t>(type_))
+ && _to->serialize(static_cast<uint8_t>(code_)));
+}
+
+bool message_header_impl::deserialize(deserializer *_from) {
+ bool is_successful;
+
+ uint8_t tmp_message_type, tmp_return_code;
+
+ is_successful = (0 != _from
+ && _from->deserialize(service_)
+ && _from->deserialize(method_)
+ && _from->deserialize(length_)
+ && _from->deserialize(client_)
+ && _from->deserialize(session_)
+ && _from->deserialize(protocol_version_)
+ && _from->deserialize(interface_version_)
+ && _from->deserialize(tmp_message_type)
+ && _from->deserialize(tmp_return_code));
+
+ if (is_successful) {
+ type_ = static_cast< message_type_e >(tmp_message_type);
+ code_ = static_cast< return_code_e >(tmp_return_code);
+ }
+
+ return is_successful;
+}
+
+message_base * message_header_impl::get_owner() const {
+ return owner_;
+}
+
+void message_header_impl::set_owner(message_base *_owner) {
+ owner_ = _owner;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/message/src/message_impl.cpp b/implementation/message/src/message_impl.cpp
index 09a7ba8..25cf584 100644
--- a/implementation/message/src/message_impl.cpp
+++ b/implementation/message/src/message_impl.cpp
@@ -1,50 +1,84 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <vsomeip/defines.hpp>
-#include <vsomeip/payload.hpp>
-#include <vsomeip/runtime.hpp>
-
-#include "../include/message_impl.hpp"
-#include "../../utility/include/byteorder.hpp"
-
-namespace vsomeip {
-
-message_impl::message_impl()
- : payload_(runtime::get()->create_payload()) {
-}
-
-message_impl::~message_impl() {
-}
-
-length_t message_impl::get_length() const {
- return (VSOMEIP_SOMEIP_HEADER_SIZE
- + (payload_ ? payload_->get_length() : 0));
-}
-
-std::shared_ptr< payload > message_impl::get_payload() const {
- return payload_;
-}
-
-void message_impl::set_payload(std::shared_ptr< payload > _payload) {
- payload_ = _payload;
-}
-
-bool message_impl::serialize(serializer *_to) const {
- return (header_.serialize(_to)
- && (payload_ ? payload_->serialize(_to) : true));
-}
-
-bool message_impl::deserialize(deserializer *_from) {
- payload_ = runtime::get()->create_payload();
- bool is_successful = header_.deserialize(_from);
- if (is_successful) {
- payload_->set_capacity(header_.length_ - VSOMEIP_SOMEIP_HEADER_SIZE);
- is_successful = payload_->deserialize(_from);
- }
- return is_successful;
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/defines.hpp>
+#include <vsomeip/payload.hpp>
+#include <vsomeip/runtime.hpp>
+
+#include "../include/message_impl.hpp"
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif
+#include "../../utility/include/byteorder.hpp"
+
+namespace vsomeip_v3 {
+
+message_impl::message_impl()
+ : payload_(runtime::get()->create_payload()),
+ check_result_(0), uid_(ANY_UID), gid_(ANY_GID) {
+}
+
+message_impl::~message_impl() {
+}
+
+length_t message_impl::get_length() const {
+ return (VSOMEIP_SOMEIP_HEADER_SIZE
+ + (payload_ ? payload_->get_length() : 0));
+}
+
+std::shared_ptr< payload > message_impl::get_payload() const {
+ return payload_;
+}
+
+void message_impl::set_payload(std::shared_ptr< payload > _payload) {
+ payload_ = _payload;
+}
+
+bool message_impl::serialize(serializer *_to) const {
+ return (header_.serialize(_to)
+ && (payload_ ? payload_->serialize(_to) : true));
+}
+
+bool message_impl::deserialize(deserializer *_from) {
+ payload_ = runtime::get()->create_payload();
+ bool is_successful = header_.deserialize(_from);
+ if (is_successful) {
+ payload_->set_capacity(header_.length_ - VSOMEIP_SOMEIP_HEADER_SIZE);
+ is_successful = payload_->deserialize(_from);
+ }
+ return is_successful;
+}
+
+uint8_t message_impl::get_check_result() const {
+ return check_result_;
+}
+
+void message_impl::set_check_result(uint8_t _check_result) {
+ check_result_ = _check_result;
+}
+
+bool message_impl::is_valid_crc() const {
+ return (check_result_ == 0);
+}
+
+uid_t message_impl::get_uid() const {
+ return uid_;
+}
+
+void message_impl::set_uid(uid_t _uid) {
+ uid_ = _uid;
+}
+
+uid_t message_impl::get_gid() const {
+ return gid_;
+}
+
+void message_impl::set_gid(gid_t _gid) {
+ gid_ = _gid;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/message/src/payload_impl.cpp b/implementation/message/src/payload_impl.cpp
index 9794976..dd1a6aa 100644
--- a/implementation/message/src/payload_impl.cpp
+++ b/implementation/message/src/payload_impl.cpp
@@ -1,79 +1,79 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/deserializer.hpp"
-#include "../include/payload_impl.hpp"
-#include "../include/serializer.hpp"
-
-namespace vsomeip {
-
-payload_impl::payload_impl()
- : data_() {
-}
-
-payload_impl::payload_impl(const byte_t *_data, uint32_t _size) {
- data_.assign(_data, _data + _size);
-}
-
-payload_impl::payload_impl(const std::vector<byte_t> &_data)
- : data_(_data) {
-}
-
-payload_impl::payload_impl(const payload_impl& _payload)
- : data_(_payload.data_) {
-}
-
-payload_impl::~payload_impl() {
-}
-
-bool payload_impl::operator==(const payload &_other) {
- bool is_equal(true);
- try {
- const payload_impl &other = dynamic_cast< const payload_impl & >(_other);
- is_equal = (data_ == other.data_);
- }
- catch (...) {
- is_equal = false;
- }
- return is_equal;
-}
-
-byte_t * payload_impl::get_data() {
- return data_.data();
-}
-
-const byte_t * payload_impl::get_data() const {
- return data_.data();
-}
-
-length_t payload_impl::get_length() const {
- return length_t(data_.size());
-}
-
-void payload_impl::set_capacity(length_t _capacity) {
- data_.reserve(_capacity);
-}
-
-void payload_impl::set_data(const byte_t *_data, const length_t _length) {
- data_.assign(_data, _data + _length);
-}
-
-void payload_impl::set_data(const std::vector< byte_t > &_data) {
- data_ = _data;
-}
-
-void payload_impl::set_data(std::vector< byte_t > &&_data) {
- data_ = std::move(_data);
-}
-
-bool payload_impl::serialize(serializer *_to) const {
- return (0 != _to && _to->serialize(data_));
-}
-
-bool payload_impl::deserialize(deserializer *_from) {
- return (0 != _from && _from->deserialize(data_));
-}
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/deserializer.hpp"
+#include "../include/payload_impl.hpp"
+#include "../include/serializer.hpp"
+
+namespace vsomeip_v3 {
+
+payload_impl::payload_impl()
+ : data_() {
+}
+
+payload_impl::payload_impl(const byte_t *_data, uint32_t _size) {
+ data_.assign(_data, _data + _size);
+}
+
+payload_impl::payload_impl(const std::vector<byte_t> &_data)
+ : data_(_data) {
+}
+
+payload_impl::payload_impl(const payload_impl& _payload)
+ : data_(_payload.data_) {
+}
+
+payload_impl::~payload_impl() {
+}
+
+bool payload_impl::operator==(const payload &_other) {
+ bool is_equal(true);
+ try {
+ const payload_impl &other = dynamic_cast< const payload_impl & >(_other);
+ is_equal = (data_ == other.data_);
+ }
+ catch (...) {
+ is_equal = false;
+ }
+ return is_equal;
+}
+
+byte_t * payload_impl::get_data() {
+ return data_.data();
+}
+
+const byte_t * payload_impl::get_data() const {
+ return data_.data();
+}
+
+length_t payload_impl::get_length() const {
+ return length_t(data_.size());
+}
+
+void payload_impl::set_capacity(length_t _capacity) {
+ data_.reserve(_capacity);
+}
+
+void payload_impl::set_data(const byte_t *_data, const length_t _length) {
+ data_.assign(_data, _data + _length);
+}
+
+void payload_impl::set_data(const std::vector< byte_t > &_data) {
+ data_ = _data;
+}
+
+void payload_impl::set_data(std::vector< byte_t > &&_data) {
+ data_ = std::move(_data);
+}
+
+bool payload_impl::serialize(serializer *_to) const {
+ return (0 != _to && _to->serialize(data_));
+}
+
+bool payload_impl::deserialize(deserializer *_from) {
+ return (0 != _from && _from->deserialize(data_));
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/message/src/serializer.cpp b/implementation/message/src/serializer.cpp
index d9277d6..fe5196e 100644
--- a/implementation/message/src/serializer.cpp
+++ b/implementation/message/src/serializer.cpp
@@ -1,122 +1,122 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-//#include <cstring>
-
-#ifdef VSOMEIP_DEBUGGING
-#include <iomanip>
-#include <sstream>
-#endif
-
-#include <vsomeip/internal/serializable.hpp>
-
-#include "../include/serializer.hpp"
-#include "../../utility/include/byteorder.hpp"
-#include "../../logging/include/logger.hpp"
-
-namespace vsomeip {
-
-serializer::serializer(std::uint32_t _buffer_shrink_threshold) :
- data_(0),
- shrink_count_(0),
- buffer_shrink_threshold_(_buffer_shrink_threshold) {
-}
-
-serializer::~serializer() {
-}
-
-bool serializer::serialize(const serializable *_from) {
- return (_from && _from->serialize(this));
-}
-
-bool serializer::serialize(const uint8_t _value) {
- data_.push_back(_value);
- return true;
-}
-
-bool serializer::serialize(const uint16_t _value) {
- data_.push_back(VSOMEIP_WORD_BYTE1(_value));
- data_.push_back(VSOMEIP_WORD_BYTE0(_value));
- return true;
-}
-
-bool serializer::serialize(const uint32_t _value, bool _omit_last_byte) {
- if (!_omit_last_byte) {
- data_.push_back(VSOMEIP_LONG_BYTE3(_value));
- }
- data_.push_back(VSOMEIP_LONG_BYTE2(_value));
- data_.push_back(VSOMEIP_LONG_BYTE1(_value));
- data_.push_back(VSOMEIP_LONG_BYTE0(_value));
- return true;
-}
-
-bool serializer::serialize(const uint8_t *_data, uint32_t _length) {
- try {
- data_.insert(data_.end(), _data, _data + _length);
- } catch(const std::bad_alloc &e) {
- VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(*_data, length)" << e.what();
- return false;
- }
- return true;
-}
-
-bool serializer::serialize(const std::vector<byte_t> &_data) {
- try {
- data_.insert(data_.end(),_data.begin(), _data.end());
- } catch(const std::bad_alloc &e) {
- VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(vector)" << e.what();
- return false;
- }
- return true;
-}
-
-const byte_t * serializer::get_data() const {
- return data_.data();
-}
-
-uint32_t serializer::get_capacity() const {
- return static_cast<std::uint32_t>(data_.max_size());
-}
-
-uint32_t serializer::get_size() const {
- return static_cast<std::uint32_t>(data_.size());
-}
-
-void serializer::set_data(byte_t *_data, uint32_t _capacity) {
- data_.clear();
- try {
- data_.insert(data_.end(), _data, _data + _capacity);
- } catch(const std::bad_alloc &e) {
- VSOMEIP_ERROR << "Couldn't allocate memory in serializer::set_data" << e.what();
- }
-}
-
-void serializer::reset() {
- if (buffer_shrink_threshold_) {
- if (data_.size() < (data_.capacity() >> 1)) {
- shrink_count_++;
- } else {
- shrink_count_ = 0;
- }
- }
- data_.clear();
- if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
- data_.shrink_to_fit();
- shrink_count_ = 0;
- }
-}
-
-#ifdef VSOMEIP_DEBUGGING
-void serializer::show() {
- std::stringstream its_data;
- its_data << "SERIALIZED: ";
- for (const byte_t& e : data_)
- its_data << std::setw(2) << std::setfill('0')
- << std::hex << (int)e;
- VSOMEIP_INFO << its_data.str();
-}
-#endif
-
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+//#include <cstring>
+
+#ifdef VSOMEIP_DEBUGGING
+#include <iomanip>
+#include <sstream>
+#endif
+
+#include <vsomeip/internal/serializable.hpp>
+
+#include "../include/serializer.hpp"
+#include "../../utility/include/byteorder.hpp"
+#include <vsomeip/internal/logger.hpp>
+
+namespace vsomeip_v3 {
+
+serializer::serializer(std::uint32_t _buffer_shrink_threshold) :
+ data_(0),
+ shrink_count_(0),
+ buffer_shrink_threshold_(_buffer_shrink_threshold) {
+}
+
+serializer::~serializer() {
+}
+
+bool serializer::serialize(const serializable *_from) {
+ return (_from && _from->serialize(this));
+}
+
+bool serializer::serialize(const uint8_t _value) {
+ data_.push_back(_value);
+ return true;
+}
+
+bool serializer::serialize(const uint16_t _value) {
+ data_.push_back(VSOMEIP_WORD_BYTE1(_value));
+ data_.push_back(VSOMEIP_WORD_BYTE0(_value));
+ return true;
+}
+
+bool serializer::serialize(const uint32_t _value, bool _omit_last_byte) {
+ if (!_omit_last_byte) {
+ data_.push_back(VSOMEIP_LONG_BYTE3(_value));
+ }
+ data_.push_back(VSOMEIP_LONG_BYTE2(_value));
+ data_.push_back(VSOMEIP_LONG_BYTE1(_value));
+ data_.push_back(VSOMEIP_LONG_BYTE0(_value));
+ return true;
+}
+
+bool serializer::serialize(const uint8_t *_data, uint32_t _length) {
+ try {
+ data_.insert(data_.end(), _data, _data + _length);
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(*_data, length)" << e.what();
+ return false;
+ }
+ return true;
+}
+
+bool serializer::serialize(const std::vector<byte_t> &_data) {
+ try {
+ data_.insert(data_.end(),_data.begin(), _data.end());
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::serialize(vector)" << e.what();
+ return false;
+ }
+ return true;
+}
+
+const byte_t * serializer::get_data() const {
+ return data_.data();
+}
+
+uint32_t serializer::get_capacity() const {
+ return static_cast<std::uint32_t>(data_.max_size());
+}
+
+uint32_t serializer::get_size() const {
+ return static_cast<std::uint32_t>(data_.size());
+}
+
+void serializer::set_data(byte_t *_data, uint32_t _capacity) {
+ data_.clear();
+ try {
+ data_.insert(data_.end(), _data, _data + _capacity);
+ } catch(const std::bad_alloc &e) {
+ VSOMEIP_ERROR << "Couldn't allocate memory in serializer::set_data" << e.what();
+ }
+}
+
+void serializer::reset() {
+ if (buffer_shrink_threshold_) {
+ if (data_.size() < (data_.capacity() >> 1)) {
+ shrink_count_++;
+ } else {
+ shrink_count_ = 0;
+ }
+ }
+ data_.clear();
+ if (buffer_shrink_threshold_ && shrink_count_ > buffer_shrink_threshold_) {
+ data_.shrink_to_fit();
+ shrink_count_ = 0;
+ }
+}
+
+#ifdef VSOMEIP_DEBUGGING
+void serializer::show() {
+ std::stringstream its_data;
+ its_data << "SERIALIZED: ";
+ for (const byte_t& e : data_)
+ its_data << std::setw(2) << std::setfill('0')
+ << std::hex << (int)e;
+ VSOMEIP_INFO << its_data.str();
+}
+#endif
+
+} // namespace vsomeip_v3
diff --git a/implementation/plugin/include/plugin_manager.hpp b/implementation/plugin/include/plugin_manager.hpp
index 7d2d7f0..61662b8 100644
--- a/implementation/plugin/include/plugin_manager.hpp
+++ b/implementation/plugin/include/plugin_manager.hpp
@@ -1,55 +1,28 @@
-// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_PLUGIN_MANAGER_HPP
-#define VSOMEIP_PLUGIN_MANAGER_HPP
+#ifndef VSOMEIP_V3_PLUGIN_MANAGER_HPP
+#define VSOMEIP_V3_PLUGIN_MANAGER_HPP
-#include <map>
-#include <chrono>
-#include <mutex>
-#include <set>
+#include <memory>
+#include <string>
-#include <vsomeip/constants.hpp>
#include <vsomeip/export.hpp>
#include <vsomeip/plugin.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class plugin_manager {
public:
- VSOMEIP_EXPORT static std::shared_ptr<plugin_manager> get();
+ VSOMEIP_EXPORT virtual ~plugin_manager() {};
+ VSOMEIP_EXPORT static std::shared_ptr<plugin_manager> get();
+ VSOMEIP_EXPORT virtual void load_plugins() = 0;
+ VSOMEIP_EXPORT virtual std::shared_ptr<plugin> get_plugin(plugin_type_e _type, std::string _name) = 0;
- plugin_manager();
-
- ~plugin_manager();
-
- VSOMEIP_EXPORT void load_plugins();
-
- VSOMEIP_EXPORT std::shared_ptr<plugin> get_plugin(plugin_type_e _type, std::string _name);
-
- VSOMEIP_EXPORT std::shared_ptr<plugin> load_plugin(
- const std::string _library, plugin_type_e _type,
- const uint32_t _version);
-
- VSOMEIP_EXPORT bool unload_plugin(plugin_type_e _type);
-
-private:
- void add_plugin(const std::shared_ptr<plugin> &_plugin, const std::string _name);
-
- void * load_library(const std::string &_path);
- void * load_symbol(void * _handle, const std::string &_symbol);
-
- bool plugins_loaded_;
- std::mutex loader_mutex_;
-
- std::map<plugin_type_e, std::map<std::string, std::shared_ptr<plugin> > > plugins_;
- std::map<plugin_type_e, std::map<std::string, void*> > handles_;
- std::recursive_mutex plugins_mutex_;
-
- static std::shared_ptr<plugin_manager> the_plugin_manager__;
};
-}
-#endif // VSOMEIP_PLUGIN_MANAGER_HPP
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_PLUGIN_MANAGER_HPP
diff --git a/implementation/plugin/include/plugin_manager_impl.hpp b/implementation/plugin/include/plugin_manager_impl.hpp
new file mode 100644
index 0000000..eb7d09f
--- /dev/null
+++ b/implementation/plugin/include/plugin_manager_impl.hpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_PLUGIN_MANAGER_IMPL_HPP
+#define VSOMEIP_V3_PLUGIN_MANAGER_IMPL_HPP
+
+#include "../include/plugin_manager.hpp"
+
+#include <map>
+#include <chrono>
+#include <mutex>
+#include <set>
+
+#include <vsomeip/constants.hpp>
+#include <vsomeip/export.hpp>
+#include <vsomeip/plugin.hpp>
+
+namespace vsomeip_v3 {
+
+class plugin_manager_impl : public plugin_manager {
+public:
+ VSOMEIP_EXPORT static std::shared_ptr<plugin_manager_impl> get();
+
+ plugin_manager_impl();
+
+ ~plugin_manager_impl();
+
+ VSOMEIP_EXPORT void load_plugins();
+
+ VSOMEIP_EXPORT std::shared_ptr<plugin> get_plugin(plugin_type_e _type, std::string _name);
+
+ VSOMEIP_EXPORT std::shared_ptr<plugin> load_plugin(
+ const std::string& _library, plugin_type_e _type,
+ const uint32_t _version);
+
+ VSOMEIP_EXPORT bool unload_plugin(plugin_type_e _type);
+
+private:
+ void add_plugin(const std::shared_ptr<plugin> &_plugin, const std::string& _name);
+
+ void * load_library(const std::string &_path);
+ void * load_symbol(void * _handle, const std::string &_symbol);
+
+ bool plugins_loaded_;
+ std::mutex loader_mutex_;
+
+ std::map<plugin_type_e, std::map<std::string, std::shared_ptr<plugin> > > plugins_;
+ std::map<plugin_type_e, std::map<std::string, void*> > handles_;
+ std::recursive_mutex plugins_mutex_;
+
+ static std::shared_ptr<plugin_manager_impl> the_plugin_manager__;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_PLUGIN_MANAGER_IMPL_HPP
diff --git a/implementation/plugin/src/plugin_manager.cpp b/implementation/plugin/src/plugin_manager.cpp
index 3b9b3f7..f8ddaa1 100644
--- a/implementation/plugin/src/plugin_manager.cpp
+++ b/implementation/plugin/src/plugin_manager.cpp
@@ -3,208 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#include <sstream>
-#include <vector>
-#include <stdlib.h>
-#include <iostream>
+#include "../include/plugin_manager_impl.hpp"
-#ifdef _WIN32
- #ifndef _WINSOCKAPI_
- #include <Windows.h>
- #endif
-#else
- #include <dlfcn.h>
-#endif
-
-#include <vsomeip/plugins/application_plugin.hpp>
-#include <vsomeip/plugins/pre_configuration_plugin.hpp>
-
-#include "../include/plugin_manager.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../utility/include/utility.hpp"
-
-namespace vsomeip {
-
-std::shared_ptr<plugin_manager> plugin_manager::the_plugin_manager__ =
- std::make_shared<plugin_manager>();
+namespace vsomeip_v3 {
std::shared_ptr<plugin_manager> plugin_manager::get() {
- return the_plugin_manager__;
-}
-
-plugin_manager::plugin_manager() :
- plugins_loaded_(false) {
-}
-
-plugin_manager::~plugin_manager() {
- handles_.clear();
- plugins_.clear();
-}
-
-void plugin_manager::load_plugins() {
- {
- std::lock_guard<std::mutex> its_lock_start_stop(loader_mutex_);
- if (plugins_loaded_) {
- return;
- }
- plugins_loaded_ = true;
- }
-
- // Get plug-ins libraries from environment
- std::vector<std::string> plugins;
- const char *its_plugins = getenv(VSOMEIP_ENV_LOAD_PLUGINS);
- if (nullptr != its_plugins) {
- std::string token;
- std::stringstream ss(its_plugins);
- while(std::getline(ss, token, ',')) {
- plugins.push_back(token);
- }
- }
-
- std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
- // Load plug-in info from libraries parsed before
- for (auto plugin_name : plugins) {
- void* handle = load_library(plugin_name);
- plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
- load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
- if (its_init_func) {
- create_plugin_func its_create_func = (*its_init_func)();
- if (its_create_func) {
- auto its_plugin = (*its_create_func)();
- if (its_plugin) {
- handles_[its_plugin->get_plugin_type()][plugin_name] = handle;
- switch (its_plugin->get_plugin_type()) {
- case plugin_type_e::APPLICATION_PLUGIN:
- if (its_plugin->get_plugin_version()
- == VSOMEIP_APPLICATION_PLUGIN_VERSION) {
- add_plugin(its_plugin, plugin_name);
- } else {
- VSOMEIP_ERROR << "Plugin version mismatch. "
- << "Ignoring application plugin "
- << its_plugin->get_plugin_name();
- }
- break;
- case plugin_type_e::PRE_CONFIGURATION_PLUGIN:
- if (its_plugin->get_plugin_version()
- == VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION) {
- add_plugin(its_plugin, plugin_name);
- } else {
- VSOMEIP_ERROR << "Plugin version mismatch. Ignoring "
- << "pre-configuration plugin "
- << its_plugin->get_plugin_name();
- }
- break;
- default:
- break;
- }
- }
- }
- }
- }
-}
-
-std::shared_ptr<plugin> plugin_manager::get_plugin(plugin_type_e _type, std::string _name) {
- std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
- auto its_type = plugins_.find(_type);
- if (its_type != plugins_.end()) {
- auto its_name = its_type->second.find(_name);
- if (its_name != its_type->second.end()) {
- return its_name->second;
- }
- }
- return load_plugin(_name, _type, 1);
+ return plugin_manager_impl::get();
}
-std::shared_ptr<plugin> plugin_manager::load_plugin(const std::string _library,
- plugin_type_e _type, uint32_t _version) {
- void* handle = load_library(_library);
- plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
- load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
- if (its_init_func) {
- create_plugin_func its_create_func = (*its_init_func)();
- if (its_create_func) {
- handles_[_type][_library] = handle;
- auto its_plugin = (*its_create_func)();
- if (its_plugin) {
- if (its_plugin->get_plugin_type() == _type
- && its_plugin->get_plugin_version() == _version) {
- add_plugin(its_plugin, _library);
- return its_plugin;
- } else {
- VSOMEIP_ERROR << "Plugin version mismatch. Ignoring plugin "
- << its_plugin->get_plugin_name();
- }
- }
- }
- }
- return nullptr;
-}
-
-bool plugin_manager::unload_plugin(plugin_type_e _type) {
- std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
- const auto found_handle = handles_.find(_type);
- if (found_handle != handles_.end()) {
- for (auto its_name : found_handle->second) {
-#ifdef _WIN32
- FreeLibrary((HMODULE)its_name.second);
-#else
- if (dlclose(its_name.second)) {
- VSOMEIP_ERROR << "Unloading failed: (" << dlerror() << ")";
- }
-#endif
- }
- } else {
- VSOMEIP_ERROR << "plugin_manager::unload_plugin didn't find plugin"
- << " type:" << (int)_type;
- return false;
- }
- return plugins_.erase(_type);
-}
-
-void plugin_manager::add_plugin(const std::shared_ptr<plugin> &_plugin, const std::string _name) {
- plugins_[_plugin->get_plugin_type()][_name] = _plugin;
-}
-
-void * plugin_manager::load_library(const std::string &_path) {
-#ifdef _WIN32
- return LoadLibrary(_path.c_str());
-#else
- return dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
-#endif
-}
-
-void * plugin_manager::load_symbol(void * _handle,
- const std::string &_symbol) {
- void * its_symbol = 0;
-#ifdef _WIN32
- HINSTANCE hDLL = (HINSTANCE)_handle;
- if (hDLL != NULL) {
-
- typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT);
-
- LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str());
- if (!lpfnDllFunc1) {
- FreeLibrary(hDLL);
- std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl;
- }
- else {
- its_symbol = lpfnDllFunc1;
- }
- }
-#else
- if (0 != _handle) {
- its_symbol = dlsym(_handle, _symbol.c_str());
- const char *dlsym_error = dlerror();
- if (dlsym_error) {
- VSOMEIP_INFO << "Cannot load symbol : " << _symbol << " : " << dlsym_error;
- dlclose(_handle);
- }
- } else {
- VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
- }
-#endif
- return (its_symbol);
-}
-
-}
+} // namespace vsomeip_v3
diff --git a/implementation/plugin/src/plugin_manager_impl.cpp b/implementation/plugin/src/plugin_manager_impl.cpp
new file mode 100644
index 0000000..6da2d82
--- /dev/null
+++ b/implementation/plugin/src/plugin_manager_impl.cpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <sstream>
+#include <vector>
+#include <stdlib.h>
+#include <iostream>
+
+#ifdef _WIN32
+ #ifndef _WINSOCKAPI_
+ #include <Windows.h>
+ #endif
+#else
+ #include <dlfcn.h>
+#endif
+
+#include <vsomeip/plugins/application_plugin.hpp>
+#include <vsomeip/plugins/pre_configuration_plugin.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/plugin_manager_impl.hpp"
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+#include "../../utility/include/utility.hpp"
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<plugin_manager_impl> plugin_manager_impl::the_plugin_manager__ =
+ std::make_shared<plugin_manager_impl>();
+
+std::shared_ptr<plugin_manager_impl> plugin_manager_impl::get() {
+ return the_plugin_manager__;
+}
+
+plugin_manager_impl::plugin_manager_impl() :
+ plugins_loaded_(false) {
+}
+
+plugin_manager_impl::~plugin_manager_impl() {
+ handles_.clear();
+ plugins_.clear();
+}
+
+void plugin_manager_impl::load_plugins() {
+ {
+ std::lock_guard<std::mutex> its_lock_start_stop(loader_mutex_);
+ if (plugins_loaded_) {
+ return;
+ }
+ plugins_loaded_ = true;
+ }
+
+ // Get plug-ins libraries from environment
+ std::vector<std::string> plugins;
+ const char *its_plugins = getenv(VSOMEIP_ENV_LOAD_PLUGINS);
+ if (nullptr != its_plugins) {
+ std::string token;
+ std::stringstream ss(its_plugins);
+ while(std::getline(ss, token, ',')) {
+ plugins.push_back(token);
+ }
+ }
+
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ // Load plug-in info from libraries parsed before
+ for (const auto& plugin_name : plugins) {
+ void* handle = load_library(plugin_name);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ handles_[its_plugin->get_plugin_type()][plugin_name] = handle;
+ switch (its_plugin->get_plugin_type()) {
+ case plugin_type_e::APPLICATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_APPLICATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin, plugin_name);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. "
+ << "Ignoring application plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ case plugin_type_e::PRE_CONFIGURATION_PLUGIN:
+ if (its_plugin->get_plugin_version()
+ == VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION) {
+ add_plugin(its_plugin, plugin_name);
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring "
+ << "pre-configuration plugin "
+ << its_plugin->get_plugin_name();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+std::shared_ptr<plugin> plugin_manager_impl::get_plugin(plugin_type_e _type, std::string _name) {
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ auto its_type = plugins_.find(_type);
+ if (its_type != plugins_.end()) {
+ auto its_name = its_type->second.find(_name);
+ if (its_name != its_type->second.end()) {
+ return its_name->second;
+ }
+ }
+ return load_plugin(_name, _type, 1);
+}
+
+std::shared_ptr<plugin> plugin_manager_impl::load_plugin(const std::string& _library,
+ plugin_type_e _type, uint32_t _version) {
+ void* handle = load_library(_library);
+ plugin_init_func its_init_func = reinterpret_cast<plugin_init_func>(
+ load_symbol(handle, VSOMEIP_PLUGIN_INIT_SYMBOL));
+ if (its_init_func) {
+ create_plugin_func its_create_func = (*its_init_func)();
+ if (its_create_func) {
+ handles_[_type][_library] = handle;
+ auto its_plugin = (*its_create_func)();
+ if (its_plugin) {
+ if (its_plugin->get_plugin_type() == _type
+ && its_plugin->get_plugin_version() == _version) {
+ add_plugin(its_plugin, _library);
+ return its_plugin;
+ } else {
+ VSOMEIP_ERROR << "Plugin version mismatch. Ignoring plugin "
+ << its_plugin->get_plugin_name();
+ }
+ }
+ }
+ }
+ return nullptr;
+}
+
+bool plugin_manager_impl::unload_plugin(plugin_type_e _type) {
+ std::lock_guard<std::recursive_mutex> its_lock_start_stop(plugins_mutex_);
+ const auto found_handle = handles_.find(_type);
+ if (found_handle != handles_.end()) {
+ for (const auto& its_name : found_handle->second) {
+#ifdef _WIN32
+ FreeLibrary((HMODULE)its_name.second);
+#else
+ if (dlclose(its_name.second)) {
+ VSOMEIP_ERROR << "Unloading failed: (" << dlerror() << ")";
+ }
+#endif
+ }
+ } else {
+ VSOMEIP_ERROR << "plugin_manager_impl::unload_plugin didn't find plugin"
+ << " type:" << (int)_type;
+ return false;
+ }
+ return plugins_.erase(_type);
+}
+
+void plugin_manager_impl::add_plugin(const std::shared_ptr<plugin> &_plugin, const std::string& _name) {
+ plugins_[_plugin->get_plugin_type()][_name] = _plugin;
+}
+
+void * plugin_manager_impl::load_library(const std::string &_path) {
+#ifdef _WIN32
+ return LoadLibrary(_path.c_str());
+#else
+ return dlopen(_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+#endif
+}
+
+void * plugin_manager_impl::load_symbol(void * _handle,
+ const std::string &_symbol) {
+ void * its_symbol = 0;
+#ifdef _WIN32
+ HINSTANCE hDLL = (HINSTANCE)_handle;
+ if (hDLL != NULL) {
+
+ typedef UINT(CALLBACK* LPFNDLLFUNC1)(DWORD, UINT);
+
+ LPFNDLLFUNC1 lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, _symbol.c_str());
+ if (!lpfnDllFunc1) {
+ FreeLibrary(hDLL);
+ std::cerr << "Loading symbol \"" << _symbol << "\" failed (" << GetLastError() << ")" << std::endl;
+ }
+ else {
+ its_symbol = lpfnDllFunc1;
+ }
+ }
+#else
+ if (0 != _handle) {
+ its_symbol = dlsym(_handle, _symbol.c_str());
+ const char *dlsym_error = dlerror();
+ if (dlsym_error) {
+ VSOMEIP_INFO << "Cannot load symbol : " << _symbol << " : " << dlsym_error;
+ dlclose(_handle);
+ }
+ } else {
+ VSOMEIP_ERROR << "Loading failed: (" << dlerror() << ")";
+ }
+#endif
+ return (its_symbol);
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/routing/include/event.hpp b/implementation/routing/include/event.hpp
index 668bbf4..684a49b 100644
--- a/implementation/routing/include/event.hpp
+++ b/implementation/routing/include/event.hpp
@@ -3,9 +3,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_EVENT_IMPL_HPP
-#define VSOMEIP_EVENT_IMPL_HPP
+#ifndef VSOMEIP_V3_EVENT_IMPL_HPP_
+#define VSOMEIP_V3_EVENT_IMPL_HPP_
+#include <list>
#include <map>
#include <memory>
#include <mutex>
@@ -20,7 +21,13 @@
#include <vsomeip/function_types.hpp>
#include <vsomeip/payload.hpp>
-namespace vsomeip {
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+namespace vsomeip_v3 {
class endpoint;
class endpoint_definition;
@@ -28,7 +35,8 @@ class message;
class payload;
class routing_manager;
-class event: public std::enable_shared_from_this<event> {
+class event
+ : public std::enable_shared_from_this<event> {
public:
event(routing_manager *_routing, bool _is_shadow = false);
@@ -47,21 +55,25 @@ public:
const std::shared_ptr<payload> get_payload() const;
void set_payload(const std::shared_ptr<payload> &_payload,
- const client_t _client, bool _force, bool _flush);
+ const client_t _client, bool _force);
void set_payload(const std::shared_ptr<payload> &_payload,
- const std::shared_ptr<endpoint_definition> _target,
- bool _force, bool _flush);
+ const client_t _client,
+ const std::shared_ptr<endpoint_definition>& _target, bool _force);
bool set_payload_dont_notify(const std::shared_ptr<payload> &_payload);
+ bool set_payload_notify_pending(const std::shared_ptr<payload> &_payload);
- void set_payload(const std::shared_ptr<payload> &_payload,
- bool _force, bool _flush);
+ void set_payload(const std::shared_ptr<payload> &_payload, bool _force);
void unset_payload(bool _force = false);
- bool is_field() const;
- void set_field(bool _is_field);
+ event_type_e get_type() const;
+ void set_type(const event_type_e _type);
+
+ reliability_type_e get_reliability() const;
+ void set_reliability(const reliability_type_e _reliability);
+ bool is_field() const;
bool is_provided() const;
void set_provided(bool _is_provided);
@@ -75,25 +87,30 @@ public:
void set_update_on_change(bool _is_active);
// SIP_RPC_359 (epsilon change)
- void set_epsilon_change_function(const epsilon_change_func_t &_epsilon_change_func);
+ void set_epsilon_change_function(
+ const epsilon_change_func_t &_epsilon_change_func);
const std::set<eventgroup_t> get_eventgroups() const;
std::set<eventgroup_t> get_eventgroups(client_t _client) const;
void add_eventgroup(eventgroup_t _eventgroup);
void set_eventgroups(const std::set<eventgroup_t> &_eventgroups);
- void notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush);
- void notify_one(client_t _client, bool _flush);
+ void notify_one(client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target);
+ void notify_one(client_t _client);
+
bool add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _force);
void remove_subscriber(eventgroup_t _eventgroup, client_t _client);
bool has_subscriber(eventgroup_t _eventgroup, client_t _client);
std::set<client_t> get_subscribers();
+ std::set<client_t> get_subscribers(eventgroup_t _eventgroup);
void clear_subscribers();
void add_ref(client_t _client, bool _is_provided);
void remove_ref(client_t _client, bool _is_provided);
bool has_ref();
+ bool has_ref(client_t _client, bool _is_provided);
bool is_shadow() const;
void set_shadow(bool _shadow);
@@ -101,40 +118,36 @@ public:
bool is_cache_placeholder() const;
void set_cache_placeholder(bool _is_cache_place_holder);
- bool has_ref(client_t _client, bool _is_provided);
-
- std::set<client_t> get_subscribers(eventgroup_t _eventgroup);
-
bool is_subscribed(client_t _client);
- bool is_reliable() const;
- void set_reliable(bool _is_reliable);
-
- bool get_remote_notification_pending();
- void set_remote_notification_pending(bool _value);
+ void remove_pending(const std::shared_ptr<endpoint_definition> &_target);
private:
void update_cbk(boost::system::error_code const &_error);
- void notify(bool _flush);
- void notify(client_t _client, const std::shared_ptr<endpoint_definition> &_target);
+ void notify();
+ void notify(client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target);
void start_cycle();
void stop_cycle();
- bool compare(const std::shared_ptr<payload> &_lhs, const std::shared_ptr<payload> &_rhs) const;
+ bool compare(const std::shared_ptr<payload> &_lhs,
+ const std::shared_ptr<payload> &_rhs) const;
- bool set_payload_helper(const std::shared_ptr<payload> &_payload, bool _force);
+ bool set_payload_helper(const std::shared_ptr<payload> &_payload,
+ bool _force);
void reset_payload(const std::shared_ptr<payload> &_payload);
- void notify_one_unlocked(const std::shared_ptr<endpoint_definition> &_target, bool _flush);
- void notify_one_unlocked(client_t _client, bool _flush);
+ void notify_one_unlocked(client_t _client);
+ void notify_one_unlocked(client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target);
private:
routing_manager *routing_;
mutable std::mutex mutex_;
std::shared_ptr<message> message_;
- std::atomic<bool> is_field_;
+ std::atomic<event_type_e> type_;
boost::asio::steady_timer cycle_timer_;
std::chrono::milliseconds cycle_;
@@ -143,7 +156,7 @@ private:
std::atomic<bool> is_updating_on_change_;
mutable std::mutex eventgroups_mutex_;
- std::map<eventgroup_t, std::set<client_t>> eventgroups_;
+ std::map<eventgroup_t, std::set<client_t> > eventgroups_;
std::atomic<bool> is_set_;
std::atomic<bool> is_provided_;
@@ -156,11 +169,11 @@ private:
epsilon_change_func_t epsilon_change_func_;
- std::atomic<bool> is_reliable_;
+ std::atomic<reliability_type_e> reliability_;
- std::atomic<bool> remote_notification_pending_;
+ std::set<std::shared_ptr<endpoint_definition> > pending_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_EVENT_IMPL_HPP
+#endif // VSOMEIP_V3_EVENT_IMPL_HPP_
diff --git a/implementation/routing/include/eventgroupinfo.hpp b/implementation/routing/include/eventgroupinfo.hpp
index d6244b5..65f7e89 100644
--- a/implementation/routing/include/eventgroupinfo.hpp
+++ b/implementation/routing/include/eventgroupinfo.hpp
@@ -3,48 +3,62 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_EVENTGROUPINFO_HPP
-#define VSOMEIP_EVENTGROUPINFO_HPP
+#ifndef VSOMEIP_V3_EVENTGROUPINFO_HPP_
+#define VSOMEIP_V3_EVENTGROUPINFO_HPP_
+#include <atomic>
#include <chrono>
#include <list>
#include <memory>
-#include <set>
#include <mutex>
-#include <atomic>
+#include <set>
+#include <vector>
#include <boost/asio/ip/address.hpp>
#include <vsomeip/export.hpp>
#include <vsomeip/primitive_types.hpp>
+#include "remote_subscription.hpp"
#include "types.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint_definition;
class event;
class eventgroupinfo {
public:
- struct target_t {
- std::shared_ptr<endpoint_definition> endpoint_;
+ struct subscription_t {
+ std::shared_ptr<remote_subscription> subscription_;
std::chrono::steady_clock::time_point expiration_;
- bool operator==(const target_t &_other) const {
- return (endpoint_ == _other.endpoint_);
+ bool operator==(const subscription_t &_other) const {
+ return (subscription_ == _other.subscription_);
}
};
VSOMEIP_EXPORT eventgroupinfo();
- VSOMEIP_EXPORT eventgroupinfo(major_version_t _major, ttl_t _ttl);
+ VSOMEIP_EXPORT eventgroupinfo(
+ const service_t _service, const service_t _instance,
+ const eventgroup_t _eventgroup, const major_version_t _major,
+ const ttl_t _ttl);
VSOMEIP_EXPORT ~eventgroupinfo();
+ VSOMEIP_EXPORT service_t get_service() const;
+ VSOMEIP_EXPORT void set_service(const service_t _service);
+
+ VSOMEIP_EXPORT instance_t get_instance() const;
+ VSOMEIP_EXPORT void set_instance(const instance_t _instance);
+
+ VSOMEIP_EXPORT eventgroup_t get_eventgroup() const;
+ VSOMEIP_EXPORT void set_eventgroup(const eventgroup_t _eventgroup);
+
VSOMEIP_EXPORT major_version_t get_major() const;
- VSOMEIP_EXPORT void set_major(major_version_t _major);
+ VSOMEIP_EXPORT void set_major(const major_version_t _major);
VSOMEIP_EXPORT ttl_t get_ttl() const;
- VSOMEIP_EXPORT void set_ttl(ttl_t _ttl);
+ VSOMEIP_EXPORT void set_ttl(const ttl_t _ttl);
VSOMEIP_EXPORT bool is_multicast() const;
VSOMEIP_EXPORT bool get_multicast(boost::asio::ip::address &_address,
@@ -54,39 +68,48 @@ public:
VSOMEIP_EXPORT bool is_sending_multicast() const;
VSOMEIP_EXPORT const std::set<std::shared_ptr<event> > get_events() const;
- VSOMEIP_EXPORT void add_event(std::shared_ptr<event> _event);
- VSOMEIP_EXPORT void remove_event(std::shared_ptr<event> _event);
- VSOMEIP_EXPORT void get_reliability(bool& _has_reliable, bool& _has_unreliable) const;
-
- VSOMEIP_EXPORT const std::list<target_t> get_targets() const;
- VSOMEIP_EXPORT uint32_t get_unreliable_target_count() const;
-
- VSOMEIP_EXPORT bool add_target(const target_t &_target);
- VSOMEIP_EXPORT bool add_target(const target_t &_target, const target_t &_subscriber);
- VSOMEIP_EXPORT bool update_target(
- const std::shared_ptr<endpoint_definition> &_target,
- const std::chrono::steady_clock::time_point &_expiration);
- VSOMEIP_EXPORT bool remove_target(
- const std::shared_ptr<endpoint_definition> &_target);
- VSOMEIP_EXPORT void clear_targets();
-
- VSOMEIP_EXPORT void add_multicast_target(const target_t &_multicast_target);
- VSOMEIP_EXPORT void clear_multicast_targets();
- VSOMEIP_EXPORT const std::list<target_t> get_multicast_targets() const;
+ VSOMEIP_EXPORT void add_event(const std::shared_ptr<event>& _event);
+ VSOMEIP_EXPORT void remove_event(const std::shared_ptr<event>& _event);
+ VSOMEIP_EXPORT reliability_type_e get_reliability() const;
- VSOMEIP_EXPORT uint8_t get_threshold() const;
- VSOMEIP_EXPORT void set_threshold(uint8_t _threshold);
+ VSOMEIP_EXPORT std::set<std::shared_ptr<remote_subscription>>
+ get_remote_subscriptions() const;
+
+ std::shared_ptr<remote_subscription> get_remote_subscription(
+ const remote_subscription_id_t _id);
+
+ bool update_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription,
+ const std::chrono::steady_clock::time_point &_expiration,
+ std::set<client_t> &_changed, remote_subscription_id_t &_id,
+ const bool _is_subscribe);
+
+ remote_subscription_id_t add_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription);
- VSOMEIP_EXPORT std::unique_lock<std::mutex> get_subscription_lock();
+ VSOMEIP_EXPORT void remove_remote_subscription(
+ const remote_subscription_id_t _id);
- VSOMEIP_EXPORT pending_subscription_id_t add_pending_subscription(
- pending_subscription_t _pending_subscription);
+ VSOMEIP_EXPORT std::set<std::shared_ptr<endpoint_definition> >
+ get_unicast_targets() const;
+ VSOMEIP_EXPORT std::set<std::shared_ptr<endpoint_definition> >
+ get_multicast_targets() const;
- VSOMEIP_EXPORT std::vector<pending_subscription_t> remove_pending_subscription(
- pending_subscription_id_t _subscription_id);
+ VSOMEIP_EXPORT uint8_t get_threshold() const;
+ VSOMEIP_EXPORT void set_threshold(uint8_t _threshold);
- VSOMEIP_EXPORT void clear_pending_subscriptions();
+ VSOMEIP_EXPORT bool is_selective() const;
+
+ VSOMEIP_EXPORT void send_initial_events(
+ const std::shared_ptr<endpoint_definition> &_reliable,
+ const std::shared_ptr<endpoint_definition> &_unreliable) const;
private:
+ void update_id();
+ uint32_t get_unreliable_target_count() const;
+
+ std::atomic<service_t> service_;
+ std::atomic<instance_t> instance_;
+ std::atomic<eventgroup_t> eventgroup_;
std::atomic<major_version_t> major_;
std::atomic<ttl_t> ttl_;
@@ -96,24 +119,18 @@ private:
mutable std::mutex events_mutex_;
std::set<std::shared_ptr<event> > events_;
- mutable std::mutex targets_mutex_;
- std::list<target_t> targets_;
- mutable std::mutex multicast_targets_mutex_;
- std::list<target_t> multicast_targets_;
std::atomic<uint8_t> threshold_;
- std::mutex subscription_mutex_;
- std::atomic<bool> has_reliable_;
- std::atomic<bool> has_unreliable_;
+ mutable std::mutex subscriptions_mutex_;
+ std::map<remote_subscription_id_t,
+ std::shared_ptr<remote_subscription>
+ > subscriptions_;
+ remote_subscription_id_t id_;
- std::mutex pending_subscriptions_mutex_;
- std::map<pending_subscription_id_t, pending_subscription_t> pending_subscriptions_;
- std::map<std::tuple<boost::asio::ip::address, std::uint16_t, bool>,
- std::vector<pending_subscription_id_t>> pending_subscriptions_by_remote_;
- pending_subscription_id_t subscription_id_;
+ std::atomic<reliability_type_e> reliability_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_EVENTGROUPINFO_HPP
+#endif // VSOMEIP_V3_EVENTGROUPINFO_HPP_
diff --git a/implementation/routing/include/function_types.hpp b/implementation/routing/include/function_types.hpp
new file mode 100644
index 0000000..3f89c08
--- /dev/null
+++ b/implementation/routing/include/function_types.hpp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ROUTING_FUNCTION_TYPES_HPP_
+#define VSOMEIP_V3_ROUTING_FUNCTION_TYPES_HPP_
+
+namespace vsomeip_v3 {
+
+class remote_subscription;
+
+typedef std::function<
+ void (const std::shared_ptr<remote_subscription> &_subscription)
+> remote_subscription_callback_t;
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ROUTING_FUNCTION_TYPES_HPP_
diff --git a/implementation/routing/include/remote_subscription.hpp b/implementation/routing/include/remote_subscription.hpp
new file mode 100644
index 0000000..00f2b57
--- /dev/null
+++ b/implementation/routing/include/remote_subscription.hpp
@@ -0,0 +1,129 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_REMOTE_SUBSCRIPTION_HPP_
+#define VSOMEIP_V3_REMOTE_SUBSCRIPTION_HPP_
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <set>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "../../endpoints/include/endpoint_definition.hpp"
+#include "types.hpp"
+#include <vsomeip/export.hpp>
+
+
+namespace vsomeip_v3 {
+
+class eventgroupinfo;
+
+const remote_subscription_id_t PENDING_SUBSCRIPTION_ID(0);
+
+class remote_subscription {
+public:
+ VSOMEIP_EXPORT remote_subscription();
+ VSOMEIP_EXPORT ~remote_subscription();
+
+ bool operator==(const remote_subscription &_other) const;
+ bool equals(const std::shared_ptr<remote_subscription> &_other) const;
+
+ VSOMEIP_EXPORT void reset(const std::set<client_t> &_clients);
+
+ VSOMEIP_EXPORT bool is_initial() const;
+ VSOMEIP_EXPORT void set_initial(const bool _is_initial);
+
+ VSOMEIP_EXPORT bool force_initial_events() const;
+ VSOMEIP_EXPORT void set_force_initial_events(const bool _force_initial_events);
+
+ remote_subscription_id_t get_id() const;
+ void set_id(const remote_subscription_id_t _id);
+
+ std::shared_ptr<remote_subscription> get_parent() const;
+ void set_parent(const std::shared_ptr<remote_subscription> &_parent);
+
+ VSOMEIP_EXPORT std::shared_ptr<eventgroupinfo> get_eventgroupinfo() const;
+ VSOMEIP_EXPORT void set_eventgroupinfo(const std::shared_ptr<eventgroupinfo> &_info);
+
+ VSOMEIP_EXPORT ttl_t get_ttl() const;
+ VSOMEIP_EXPORT void set_ttl(const ttl_t _ttl);
+
+ uint16_t get_reserved() const;
+ void set_reserved(const uint16_t _reserved);
+
+ uint8_t get_counter() const;
+ void set_counter(uint8_t _counter);
+
+ VSOMEIP_EXPORT std::set<client_t> get_clients() const;
+ bool has_client() const;
+ bool has_client(const client_t _client) const;
+ void remove_client(const client_t _client);
+
+ VSOMEIP_EXPORT remote_subscription_state_e get_client_state(const client_t _client) const;
+ void set_client_state(const client_t _client,
+ remote_subscription_state_e _state);
+ void set_all_client_states(remote_subscription_state_e _state);
+
+ std::chrono::steady_clock::time_point get_expiration(const client_t _client) const;
+
+ VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_subscriber() const;
+ VSOMEIP_EXPORT void set_subscriber(const std::shared_ptr<endpoint_definition> &_subscriber);
+
+ VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_reliable() const;
+ VSOMEIP_EXPORT void set_reliable(const std::shared_ptr<endpoint_definition> &_reliable);
+
+ VSOMEIP_EXPORT std::shared_ptr<endpoint_definition> get_unreliable() const;
+ VSOMEIP_EXPORT void set_unreliable(const std::shared_ptr<endpoint_definition> &_unreliable);
+
+ VSOMEIP_EXPORT bool is_pending() const;
+ bool is_acknowledged() const;
+
+ std::set<client_t> update(const std::set<client_t> &_clients,
+ const std::chrono::steady_clock::time_point &_timepoint,
+ const bool _is_subscribe);
+
+ VSOMEIP_EXPORT std::uint32_t get_answers() const;
+ void set_answers(const std::uint32_t _answers);
+
+private:
+ std::atomic<remote_subscription_id_t> id_;
+ std::atomic<bool> is_initial_;
+ std::atomic<bool> force_initial_events_;
+ std::weak_ptr<remote_subscription> parent_;
+
+ std::weak_ptr<eventgroupinfo> eventgroupinfo_;
+
+ major_version_t major_;
+ ttl_t ttl_;
+ std::uint16_t reserved_;
+ std::uint8_t counter_;
+
+ std::map<client_t,
+ std::pair<remote_subscription_state_e,
+ std::chrono::steady_clock::time_point
+ >
+ > clients_;
+
+ // The endpoint that sent(!) the subscription
+ std::shared_ptr<endpoint_definition> subscriber_;
+
+ // The endpoints defined by the endpoint options
+ std::shared_ptr<endpoint_definition> reliable_;
+ std::shared_ptr<endpoint_definition> unreliable_;
+
+ // Number of acknowledgements that must be sent
+ // for the subscriptions. This is usally 1, but
+ // may be larger if a matching subscription arrived
+ // before the subscription could be acknowledged
+ std::uint32_t answers_;
+
+ mutable std::mutex mutex_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_REMOTE_SUBSCRIPTION_HPP_
diff --git a/implementation/routing/include/routing_host.hpp b/implementation/routing/include/routing_host.hpp
new file mode 100644
index 0000000..337e4a7
--- /dev/null
+++ b/implementation/routing/include/routing_host.hpp
@@ -0,0 +1,44 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_ROUTING_HOST_
+#define VSOMEIP_V3_ROUTING_HOST_
+
+#include <memory>
+
+#include <boost/asio/ip/address.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+namespace vsomeip_v3 {
+
+class endpoint;
+
+class routing_host {
+public:
+ virtual ~routing_host() = default;
+
+ virtual void on_message(const byte_t *_data, length_t _length,
+ endpoint *_receiver,
+ const boost::asio::ip::address &_destination =
+ boost::asio::ip::address(),
+ client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ credentials_t _credentials = {ANY_UID, ANY_GID},
+ const boost::asio::ip::address &_remote_address =
+ boost::asio::ip::address(),
+ std::uint16_t _remote_port = 0) = 0;
+
+ virtual client_t get_client() const = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_ROUTING_HOST_
diff --git a/implementation/routing/include/routing_manager.hpp b/implementation/routing/include/routing_manager.hpp
index 9ab09f4..fa0e675 100644
--- a/implementation/routing/include/routing_manager.hpp
+++ b/implementation/routing/include/routing_manager.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER
-#define VSOMEIP_ROUTING_MANAGER
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_
+#define VSOMEIP_V3_ROUTING_MANAGER_
#include <memory>
#include <set>
@@ -17,12 +17,13 @@
#include <vsomeip/handler.hpp>
#include "types.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
class endpoint_definition;
class event;
class payload;
+class security;
class routing_manager {
public:
@@ -31,6 +32,8 @@ public:
virtual boost::asio::io_service & get_io() = 0;
virtual client_t get_client() const = 0;
+ virtual void set_client(const client_t &_client) = 0;
+ virtual session_t get_session() = 0;
virtual void init() = 0;
virtual void start() = 0;
@@ -46,38 +49,41 @@ public:
virtual void request_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy) = 0;
+ minor_version_t _minor) = 0;
virtual void release_service(client_t _client, service_t _service,
instance_t _instance) = 0;
- virtual void subscribe(client_t _client, service_t _service,
+ virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type) = 0;
+ major_version_t _major, event_t _event) = 0;
- virtual void unsubscribe(client_t _client, service_t _service,
+ virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0;
- virtual bool send(client_t _client, std::shared_ptr<message> _message,
- bool _flush) = 0;
+ virtual bool send(client_t _client, std::shared_ptr<message> _message) = 0;
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable,
+ instance_t _instance, bool _reliable,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- bool _is_valid_crc = true, bool _sent_from_remote = false) = 0;
+ credentials_t _credentials = {ANY_UID, ANY_GID},
+ uint8_t _status_check = 0, bool _sent_from_remote = false) = 0;
- virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message>, bool _flush) = 0;
+ virtual bool send_to(const client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target,
+ std::shared_ptr<message>) = 0;
virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush) = 0;
-
- virtual void register_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups, bool _is_field,
+ const byte_t *_data, uint32_t _size, instance_t _instance) = 0;
+
+ virtual void register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups,
+ const event_type_e _type,
+ reliability_type_e _reliability,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
+ bool _update_on_change,
epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow = false,
bool _is_cache_placeholder = false) = 0;
@@ -93,20 +99,21 @@ public:
virtual void notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- bool _force, bool _flush) = 0;
+ bool _force) = 0;
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush, bool _remote_subscriber) = 0;
-
- virtual void on_identify_response(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) = 0;
+ client_t _client, bool _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , bool _remote_subscriber
+#endif
+ ) = 0;
virtual void set_routing_state(routing_state_e _routing_state) = 0;
virtual void send_get_offered_services_info(client_t _client, offer_type_e _offer_type) = 0;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif
+#endif // VSOMEIP_V3_ROUTING_MANAGER_
diff --git a/implementation/routing/include/routing_manager_adapter.hpp b/implementation/routing/include/routing_manager_adapter.hpp
index 3d81120..a2195ee 100644
--- a/implementation/routing/include/routing_manager_adapter.hpp
+++ b/implementation/routing/include/routing_manager_adapter.hpp
@@ -3,10 +3,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_ADAPTER
-#define VSOMEIP_ROUTING_MANAGER_ADAPTER
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_
+#define VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_
-namespace vsomeip {
+namespace vsomeip_v3 {
class routing_manager;
@@ -19,6 +19,6 @@ public:
virtual void process_command(const byte_t *_data, length_t _length) = 0;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_MANAGER_ADAPTER_HPP
+#endif // VSOMEIP_V3_ROUTING_MANAGER_ADAPTER_HPP_
diff --git a/implementation/routing/include/routing_manager_base.hpp b/implementation/routing/include/routing_manager_base.hpp
index 6bee10c..acd57fe 100644
--- a/implementation/routing/include/routing_manager_base.hpp
+++ b/implementation/routing/include/routing_manager_base.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_BASE
-#define VSOMEIP_ROUTING_MANAGER_BASE
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_BASE_
+#define VSOMEIP_V3_ROUTING_MANAGER_BASE_
#include <mutex>
#include <unordered_set>
@@ -12,6 +12,8 @@
#include <condition_variable>
#include <vsomeip/constants.hpp>
+
+#include "routing_host.hpp"
#include "routing_manager.hpp"
#include "routing_manager_host.hpp"
#include "types.hpp"
@@ -21,9 +23,10 @@
#include "../../message/include/serializer.hpp"
#include "../../message/include/deserializer.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../endpoints/include/endpoint_host.hpp"
+#include "../../endpoints/include/endpoint_manager_base.hpp"
+
+namespace vsomeip_v3 {
-namespace vsomeip {
#ifdef USE_DLT
namespace trace {
class connector_impl;
@@ -33,90 +36,91 @@ class connector_impl;
class serializer;
class routing_manager_base : public routing_manager,
- public endpoint_host,
- public std::enable_shared_from_this<routing_manager_base>{
+ public routing_host,
+ public std::enable_shared_from_this<routing_manager_base> {
public:
routing_manager_base(routing_manager_host *_host);
- virtual ~routing_manager_base();
+ virtual ~routing_manager_base() = default;
virtual boost::asio::io_service & get_io();
virtual client_t get_client() const;
+ virtual void set_client(const client_t &_client);
+ virtual session_t get_session();
- virtual void init();
+ virtual void init() = 0;
+ void init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager);
- virtual bool offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ virtual bool offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- virtual void stop_offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor);
+ virtual void stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- virtual void request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy);
+ virtual void request_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- virtual void release_service(client_t _client, service_t _service,
- instance_t _instance);
+ virtual void release_service(client_t _client,
+ service_t _service, instance_t _instance);
- virtual void register_event(client_t _client, service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field,
+ virtual void register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups,
+ const event_type_e _type, reliability_type_e _reliability,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
- epsilon_change_func_t _epsilon_change_func,
- bool _is_provided, bool _is_shadow = false, bool _is_cache_placeholder = false);
+ bool _update_on_change, epsilon_change_func_t _epsilon_change_func,
+ bool _is_provided, bool _is_shadow = false,
+ bool _is_cache_placeholder = false);
- virtual void unregister_event(client_t _client, service_t _service, instance_t _instance,
- event_t _event, bool _is_provided);
+ virtual void unregister_event(client_t _client,
+ service_t _service, instance_t _instance, event_t _event,
+ bool _is_provided);
virtual std::set<std::shared_ptr<event>> find_events(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
- virtual void subscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type);
+ virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major, event_t _event);
- virtual void unsubscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event);
+ virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event);
virtual void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- bool _force, bool _flush);
+ event_t _event, std::shared_ptr<payload> _payload, bool _force);
virtual void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush, bool _remote_subscriber);
+ client_t _client, bool _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , bool _remote_subscriber
+#endif
+ );
- virtual bool send(client_t _client, std::shared_ptr<message> _message,
- bool _flush);
+ virtual bool send(client_t _client, std::shared_ptr<message> _message);
virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable,
+ instance_t _instance, bool _reliable,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- bool _is_valid_crc = true, bool _sent_from_remote = false) = 0;
+ credentials_t _credentials = {ANY_UID, ANY_GID},
+ uint8_t _status_check = 0, bool _sent_from_remote = false) = 0;
- // Endpoint host ~> will be implemented by routing_manager_impl/_proxy/
- virtual void on_connect(std::shared_ptr<endpoint> _endpoint) = 0;
- virtual void on_disconnect(std::shared_ptr<endpoint> _endpoint) = 0;
+ // routing host -> will be implemented by routing_manager_impl/_proxy/
virtual void on_message(const byte_t *_data, length_t _length,
endpoint *_receiver, const boost::asio::ip::address &_destination
= boost::asio::ip::address(), client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
+ credentials_t _credentials = {ANY_UID, ANY_GID},
const boost::asio::ip::address &_remote_address = boost::asio::ip::address(),
std::uint16_t _remote_port = 0) = 0;
- virtual void on_error(const byte_t *_data, length_t _length,
- endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port) = 0;
-#ifndef _WIN32
- virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
-#endif
virtual void set_routing_state(routing_state_e _routing_state) = 0;
- virtual std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
- event_t _event) const;
-
virtual void register_client_error_handler(client_t _client,
const std::shared_ptr<endpoint> &_endpoint) = 0;
@@ -124,8 +128,16 @@ public:
std::set<client_t> find_local_clients(service_t _service, instance_t _instance);
-protected:
std::shared_ptr<serviceinfo> find_service(service_t _service, instance_t _instance) const;
+
+ client_t find_local_client(service_t _service, instance_t _instance) const;
+
+ std::shared_ptr<event> find_event(service_t _service, instance_t _instance,
+ event_t _event) const;
+
+ virtual void on_connect(const std::shared_ptr<endpoint>& _endpoint) = 0;
+ virtual void on_disconnect(const std::shared_ptr<endpoint>& _endpoint) = 0;
+protected:
std::shared_ptr<serviceinfo> create_service_info(service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl, bool _is_local_service);
@@ -134,21 +146,12 @@ protected:
services_t get_services() const;
services_t get_services_remote() const;
bool is_available(service_t _service, instance_t _instance, major_version_t _major);
- client_t find_local_client(service_t _service, instance_t _instance);
- std::shared_ptr<endpoint> create_local(client_t _client);
- std::shared_ptr<endpoint> find_or_create_local(client_t _client);
void remove_local(client_t _client, bool _remove_uid);
void remove_local(client_t _client,
const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
bool _remove_uid);
- std::shared_ptr<endpoint> find_local(client_t _client);
- std::shared_ptr<endpoint> find_local(service_t _service,
- instance_t _instance);
-
- std::unordered_set<client_t> get_connected_clients();
-
std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const;
@@ -157,33 +160,35 @@ protected:
bool send_local_notification(client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush = true, bool _reliable = false, bool _is_valid_crc = true);
+ bool _reliable = false, uint8_t _status_check = 0);
bool send_local(
std::shared_ptr<endpoint> &_target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc = true) const;
+ bool _reliable, uint8_t _command, uint8_t _status_check = 0) const;
bool insert_subscription(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, client_t _client,
std::set<event_t> *_already_subscribed_events);
+ std::shared_ptr<serializer> get_serializer();
+ void put_serializer(const std::shared_ptr<serializer> &_serializer);
std::shared_ptr<deserializer> get_deserializer();
- void put_deserializer(std::shared_ptr<deserializer>);
+ void put_deserializer(const std::shared_ptr<deserializer> &_deserializer);
void send_pending_subscriptions(service_t _service,
instance_t _instance, major_version_t _major);
virtual void send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type) = 0;
+ major_version_t _major, event_t _event) = 0;
void remove_pending_subscription(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
-
+#ifdef VSOMEIP_ENABLE_COMPAT
void send_pending_notify_ones(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber = false);
+#endif
void unset_all_eventpayloads(service_t _service, instance_t _instance);
void unset_all_eventpayloads(service_t _service, instance_t _instance,
@@ -194,11 +199,6 @@ protected:
eventgroup_t _eventgroup, event_t _event,
const std::set<event_t> &_events_to_exclude);
- void send_identify_request(service_t _service, instance_t _instance,
- major_version_t _major, bool _reliable);
-
- std::map<client_t, std::shared_ptr<endpoint>> get_local_endpoints();
-
std::set<std::tuple<service_t, instance_t, eventgroup_t>>
get_subscriptions(const client_t _client);
@@ -206,9 +206,9 @@ protected:
bool is_response_allowed(client_t _sender, service_t _service,
instance_t _instance, method_t _method);
- bool is_subscribe_to_any_event_allowed(client_t _client,
+ bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup);
-
+#ifdef VSOMEIP_ENABLE_COMPAT
void set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, subscription_state_e _state);
@@ -217,12 +217,9 @@ protected:
void erase_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
+#endif
private:
- std::shared_ptr<endpoint> create_local_unlocked(client_t _client);
- std::shared_ptr<endpoint> find_local_unlocked(client_t _client);
-
-
virtual bool create_placeholder_event_and_subscribe(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
event_t _event, client_t _client) = 0;
@@ -230,18 +227,22 @@ private:
protected:
routing_manager_host *host_;
boost::asio::io_service &io_;
- client_t client_;
+ std::atomic<client_t> client_;
std::shared_ptr<configuration> configuration_;
- std::shared_ptr<serializer> serializer_;
- std::mutex serialize_mutex_;
+
+ std::queue<std::shared_ptr<serializer>> serializers_;
+ std::mutex serializer_mutex_;
+ std::condition_variable serializer_condition_;
std::queue<std::shared_ptr<deserializer>> deserializers_;
std::mutex deserializer_mutex_;
std::condition_variable deserializer_condition_;
- std::mutex local_services_mutex_;
- std::map<service_t, std::map<instance_t, std::tuple< major_version_t, minor_version_t, client_t> > > local_services_;
+ mutable std::mutex local_services_mutex_;
+ typedef std::map<service_t, std::map<instance_t,
+ std::tuple<major_version_t, minor_version_t, client_t>>> local_services_map_t;
+ local_services_map_t local_services_;
std::map<service_t, std::map<instance_t, std::set<client_t> > > local_services_history_;
// Eventgroups
@@ -252,7 +253,11 @@ protected:
// Events (part of one or more eventgroups)
mutable std::mutex events_mutex_;
std::map<service_t,
- std::map<instance_t, std::map<event_t, std::shared_ptr<event> > > > events_;
+ std::map<instance_t,
+ std::map<event_t,
+ std::shared_ptr<event> > > > events_;
+
+ std::mutex event_registration_mutex_;
#ifdef USE_DLT
std::shared_ptr<trace::connector_impl> tc_;
@@ -264,7 +269,8 @@ protected:
eventgroup_t eventgroup_;
major_version_t major_;
event_t event_;
- subscription_type_e subscription_type_;
+ uid_t uid_;
+ gid_t gid_;
bool operator<(const subscription_data_t &_other) const {
return (service_ < _other.service_
@@ -284,21 +290,21 @@ protected:
services_t services_remote_;
mutable std::mutex services_remote_mutex_;
+ std::shared_ptr<endpoint_manager_base> ep_mgr_;
+
+ std::uint32_t own_uid_;
+ std::uint32_t own_gid_;
+
private:
services_t services_;
mutable std::mutex services_mutex_;
- std::map<client_t, std::shared_ptr<endpoint> > local_endpoints_;
- mutable std::mutex local_endpoint_mutex_;
-
+#ifdef VSOMEIP_ENABLE_COMPAT
std::map<service_t,
std::map<instance_t,
std::map<eventgroup_t,
std::shared_ptr<message> > > > pending_notify_ones_;
std::recursive_mutex pending_notify_ones_mutex_;
-
- std::mutex event_registration_mutex_;
-
std::map<client_t,
std::map<service_t,
std::map<instance_t,
@@ -306,9 +312,10 @@ private:
std::map<event_t,
subscription_state_e> > > > > incoming_subscription_state_;
std::recursive_mutex incoming_subscription_state_mutex_;
+#endif
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif //VSOMEIP_ROUTING_MANAGER_BASE
+#endif // VSOMEIP_V3_ROUTING_MANAGER_BASE_
diff --git a/implementation/routing/include/routing_manager_host.hpp b/implementation/routing/include/routing_manager_host.hpp
index 7aa767a..69133e2 100644
--- a/implementation/routing/include/routing_manager_host.hpp
+++ b/implementation/routing/include/routing_manager_host.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_HOST
-#define VSOMEIP_ROUTING_MANAGER_HOST
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_HOST_
+#define VSOMEIP_V3_ROUTING_MANAGER_HOST_
#include <memory>
@@ -12,7 +12,7 @@
#include <vsomeip/error.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
class message;
@@ -23,6 +23,8 @@ public:
}
virtual client_t get_client() const = 0;
+ virtual void set_client(const client_t &_client) = 0;
+ virtual session_t get_session() = 0;
virtual const std::string & get_name() const = 0;
virtual std::shared_ptr<configuration> get_configuration() const = 0;
virtual boost::asio::io_service & get_io() = 0;
@@ -30,19 +32,17 @@ public:
virtual void on_availability(service_t _service, instance_t _instance,
bool _is_available, major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0;
virtual void on_state(state_type_e _state) = 0;
- virtual void on_message(const std::shared_ptr<message> &&_message) = 0;
- virtual void on_error(error_code_e _error) = 0;
+ virtual void on_message(std::shared_ptr<message> &&_message) = 0;
virtual void on_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client, bool _subscribed, std::function<void(bool)> _accepted_cb) = 0;
- virtual void on_subscription_error(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, uint16_t _error) = 0;
+ eventgroup_t _eventgroup, client_t _client, uid_t _uid, gid_t _gid, bool _subscribed,
+ std::function<void(bool)> _accepted_cb) = 0;
virtual void on_subscription_status(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, uint16_t _error) = 0;
- virtual void send(std::shared_ptr<message> _message, bool _flush) = 0;
+ virtual void send(std::shared_ptr<message> _message) = 0;
virtual void on_offered_services_info(std::vector<std::pair<service_t, instance_t>> &_services) = 0;
virtual bool is_routing() const = 0;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_MANAGER_HOST
+#endif // VSOMEIP_V3_ROUTING_MANAGER_HOST_
diff --git a/implementation/routing/include/routing_manager_impl.hpp b/implementation/routing/include/routing_manager_impl.hpp
index 40abf73..bead207 100644
--- a/implementation/routing/include/routing_manager_impl.hpp
+++ b/implementation/routing/include/routing_manager_impl.hpp
@@ -1,10 +1,10 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_IMPL_HPP
-#define VSOMEIP_ROUTING_MANAGER_IMPL_HPP
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_
+#define VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_
#include <map>
#include <memory>
@@ -26,8 +26,10 @@
#include "../../endpoints/include/netlink_connector.hpp"
#include "../../service_discovery/include/service_discovery_host.hpp"
+#include "../../endpoints/include/endpoint_manager_impl.hpp"
-namespace vsomeip {
+
+namespace vsomeip_v3 {
class configuration;
class deserializer;
@@ -42,9 +44,9 @@ namespace sd {
class service_discovery;
} // namespace sd
-
-// TODO: encapsulate common parts of classes "routing_manager_impl"
-// and "routing_manager_proxy" into a base class.
+namespace e2e {
+class e2e_provider;
+} // namespace e2e
class routing_manager_impl: public routing_manager_base,
public routing_manager_stub_host,
@@ -55,61 +57,70 @@ public:
boost::asio::io_service & get_io();
client_t get_client() const;
- const std::shared_ptr<configuration> get_configuration() const;
void init();
void start();
void stop();
- bool offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ bool offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void stop_offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor);
+ void stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy);
+ void request_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void release_service(client_t _client, service_t _service,
- instance_t _instance);
+ void release_service(client_t _client,
+ service_t _service, instance_t _instance);
- void subscribe(client_t _client, service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, event_t _event,
- subscription_type_e _subscription_type);
+ void subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major, event_t _event);
- void unsubscribe(client_t _client, service_t _service, instance_t _instance,
+ void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
- bool send(client_t _client, std::shared_ptr<message> _message, bool _flush);
+ bool send(client_t _client, std::shared_ptr<message> _message);
- virtual bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable,
+ bool send(client_t _client, const byte_t *_data, uint32_t _size,
+ instance_t _instance, bool _reliable,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- bool _is_valid_crc = true, bool _sent_from_remote = false);
+ credentials_t _credentials = {ANY_UID, ANY_GID},
+ uint8_t _status_check = 0, bool _sent_from_remote = false);
- bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message, bool _flush);
+ bool send_to(const client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target,
+ std::shared_ptr<message> _message);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush);
+ instance_t _instance);
- bool send_to(const std::shared_ptr<endpoint_definition> &_target,
+ bool send_via_sd(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port);
- void register_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups, bool _is_field,
+ void register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups,
+ const event_type_e _type,
+ reliability_type_e _reliability,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
+ bool _update_on_change,
epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder);
- void register_shadow_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
+ void register_shadow_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, bool _is_provided);
+ event_type_e _type, reliability_type_e _reliability,
+ bool _is_provided);
void unregister_shadow_event(client_t _client, service_t _service,
instance_t _instance, event_t _event,
@@ -117,63 +128,68 @@ public:
void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush, bool _remote_subscriber);
+ client_t _client, bool _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , bool _remote_subscriber
+#endif
+ );
- void on_subscribe_nack(client_t _client, service_t _service,
+ void on_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id);
+ remote_subscription_id_t _id);
- void on_subscribe_ack(client_t _client, service_t _service,
+ void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id);
+ remote_subscription_id_t _id);
- void on_identify_response(client_t _client, service_t _service, instance_t _instance,
- bool _reliable);
// interface to stub
inline std::shared_ptr<endpoint> find_local(client_t _client) {
- return routing_manager_base::find_local(_client);
+ return ep_mgr_->find_local(_client);
}
inline std::shared_ptr<endpoint> find_or_create_local(
client_t _client) {
- return routing_manager_base::find_or_create_local(_client);
+ return ep_mgr_->find_or_create_local(_client);
}
+ std::shared_ptr<endpoint> find_or_create_remote_client(
+ service_t _service, instance_t _instance, bool _reliable,
+ client_t _client);
+
void remove_local(client_t _client, bool _remove_uid);
- void on_stop_offer_service(client_t _client, service_t _service, instance_t _instance,
+ void on_stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor);
void on_availability(service_t _service, instance_t _instance,
- bool _is_available, major_version_t _major, minor_version_t _minor);
+ bool _is_available,
+ major_version_t _major, minor_version_t _minor);
void on_pong(client_t _client);
+ void on_subscribe_ack_with_multicast(
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_address, uint16_t _port);
void on_unsubscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _unsubscription_id);
-
- // interface "endpoint_host"
- std::shared_ptr<endpoint> find_or_create_remote_client(service_t _service,
- instance_t _instance,
- bool _reliable, client_t _client);
- void on_connect(std::shared_ptr<endpoint> _endpoint);
- void on_disconnect(std::shared_ptr<endpoint> _endpoint);
- void on_error(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port);
+ remote_subscription_id_t _id);
+
+ void on_connect(const std::shared_ptr<endpoint>& _endpoint);
+ void on_disconnect(const std::shared_ptr<endpoint>& _endpoint);
+
void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
- client_t _bound_client,
+ client_t _bound_client, credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
bool on_message(service_t _service, instance_t _instance,
const byte_t *_data, length_t _size, bool _reliable,
- client_t _bound_client, bool _is_valid_crc = true,
+ client_t _bound_client, credentials_t _credentials,
+ uint8_t _check_status = 0,
bool _is_from_remote = false);
void on_notification(client_t _client, service_t _service,
instance_t _instance, const byte_t *_data, length_t _size,
bool _notify_one);
- void release_port(uint16_t _port, bool _reliable);
bool offer_service_remotely(service_t _service, instance_t _instance,
std::uint16_t _port, bool _reliable,
@@ -206,29 +222,22 @@ public:
bool _has_reliable, bool _has_unreliable);
void update_routing_info(std::chrono::milliseconds _elapsed);
- void on_remote_subscription(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<endpoint_definition> &_subscriber,
- const std::shared_ptr<endpoint_definition> &_target, ttl_t _ttl,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id,
- const std::function<void(remote_subscription_state_e, client_t)>& _callback);
- void on_unsubscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup,
- std::shared_ptr<endpoint_definition> _target);
- void on_subscribe_ack(service_t _service, instance_t _instance,
- const boost::asio::ip::address &_address, uint16_t _port);
+ // Handle remote subscriptions / subscription acks
+ void on_remote_subscribe(
+ std::shared_ptr<remote_subscription> &_subscription,
+ const remote_subscription_callback_t& _callback);
+ void on_remote_unsubscribe(
+ std::shared_ptr<remote_subscription> &_subscription);
void expire_subscriptions(const boost::asio::ip::address &_address);
void expire_services(const boost::asio::ip::address &_address);
std::chrono::steady_clock::time_point expire_subscriptions(bool _force);
- bool has_identified(client_t _client, service_t _service,
- instance_t _instance, bool _reliable);
-
void register_client_error_handler(client_t _client,
const std::shared_ptr<endpoint> &_endpoint);
void handle_client_error(client_t _client);
+ std::shared_ptr<endpoint_manager_impl> get_endpoint_manager() const;
void set_routing_state(routing_state_e _routing_state);
@@ -241,46 +250,61 @@ public:
eventgroup_t _eventgroup,
const std::shared_ptr<endpoint_definition> &_subscriber);
- void register_offer_acceptance_handler(offer_acceptance_handler_t _handler) const;
- void register_reboot_notification_handler(reboot_notification_handler_t _handler) const;
- void register_routing_ready_handler(routing_ready_handler_t _handler);
- void register_routing_state_handler(routing_state_handler_t _handler);
- void offer_acceptance_enabled(boost::asio::ip::address _address);
+ void print_stub_status() const;
+
+ void send_error(return_code_e _return_code, const byte_t *_data,
+ length_t _size, instance_t _instance, bool _reliable,
+ endpoint* const _receiver,
+ const boost::asio::ip::address &_remote_address,
+ std::uint16_t _remote_port);
+ void service_endpoint_connected(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ const std::shared_ptr<endpoint>& _endpoint,
+ bool _unreliable_only);
+ void service_endpoint_disconnected(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ const std::shared_ptr<endpoint>& _endpoint);
+
+ void register_sd_acceptance_handler(const sd_acceptance_handler_t& _handler) const;
+ void register_reboot_notification_handler(const reboot_notification_handler_t& _handler) const;
+ void register_routing_ready_handler(const routing_ready_handler_t& _handler);
+ void register_routing_state_handler(const routing_state_handler_t& _handler);
+ void sd_acceptance_enabled(const boost::asio::ip::address& _address);
void on_resend_provided_events_response(pending_remote_offer_id_t _id);
- bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid, ::std::shared_ptr<policy> _policy,
- std::shared_ptr<payload> _payload, security_update_handler_t _handler);
- bool remove_security_policy_configuration(uint32_t _uid, uint32_t _gid, security_update_handler_t _handler);
+ bool update_security_policy_configuration(uint32_t _uid, uint32_t _gid, const std::shared_ptr<policy>& _policy,
+ const std::shared_ptr<payload>& _payload, const security_update_handler_t& _handler);
+ bool remove_security_policy_configuration(uint32_t _uid, uint32_t _gid, const security_update_handler_t& _handler);
+ client_t find_local_client(service_t _service, instance_t _instance);
void on_security_update_response(pending_security_update_id_t _id, client_t _client);
std::set<client_t> find_local_clients(service_t _service, instance_t _instance);
- bool is_subscribe_to_any_event_allowed(client_t _client,
+ bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup);
private:
+ bool offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _must_queue);
+
+ void stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _must_queue);
+
bool deliver_message(const byte_t *_data, length_t _size,
instance_t _instance, bool _reliable, client_t _bound_client,
- bool _is_valid_crc = true, bool _is_from_remote = false);
+ credentials_t _credentials,
+ uint8_t _status_check = 0, bool _is_from_remote = false);
bool deliver_notification(service_t _service, instance_t _instance,
const byte_t *_data, length_t _length, bool _reliable, client_t _bound_client,
- bool _is_valid_crc = true, bool _is_from_remote = false);
+ credentials_t _credentials,
+ uint8_t _status_check = 0, bool _is_from_remote = false);
- instance_t find_instance(service_t _service, endpoint *_endpoint);
void init_service_info(service_t _service,
instance_t _instance, bool _is_local_service);
- std::shared_ptr<endpoint> create_client_endpoint(
- const boost::asio::ip::address &_address,
- uint16_t _local_port, uint16_t _remote_port,
- bool _reliable, client_t _client);
-
- std::shared_ptr<endpoint> create_server_endpoint(uint16_t _port,
- bool _reliable, bool _start);
- std::shared_ptr<endpoint> find_server_endpoint(uint16_t _port,
- bool _reliable) const;
- std::shared_ptr<endpoint> find_or_create_server_endpoint(uint16_t _port,
- bool _reliable, bool _start);
-
bool is_field(service_t _service, instance_t _instance,
event_t _event) const;
@@ -290,74 +314,32 @@ private:
std::shared_ptr<endpoint> create_remote_client(service_t _service,
instance_t _instance, bool _reliable, client_t _client);
- bool deliver_specific_endpoint_message(service_t _service, instance_t _instance,
- const byte_t *_data, length_t _size, endpoint *_receiver);
-
void clear_client_endpoints(service_t _service, instance_t _instance, bool _reliable);
void clear_multicast_endpoints(service_t _service, instance_t _instance);
- bool is_identifying(client_t _client, service_t _service,
- instance_t _instance, bool _reliable);
-
std::set<eventgroup_t> get_subscribed_eventgroups(service_t _service,
instance_t _instance);
void clear_targets_and_pending_sub_from_eventgroups(service_t _service, instance_t _instance);
void clear_remote_subscriber(service_t _service, instance_t _instance);
-private:
+
return_code_e check_error(const byte_t *_data, length_t _size,
instance_t _instance);
- void send_error(return_code_e _return_code, const byte_t *_data,
- length_t _size, instance_t _instance, bool _reliable,
- endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port);
-
- void identify_for_subscribe(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- subscription_type_e _subscription_type);
- bool send_identify_message(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- bool _reliable);
-
bool supports_selective(service_t _service, instance_t _instance);
- client_t find_client(service_t _service, instance_t _instance,
- const std::shared_ptr<eventgroupinfo> &_eventgroup,
- const std::shared_ptr<endpoint_definition> &_target) const;
-
void clear_remote_subscriber(service_t _service, instance_t _instance,
client_t _client,
const std::shared_ptr<endpoint_definition> &_target);
void log_version_timer_cbk(boost::system::error_code const & _error);
- void clear_remote_service_info(service_t _service, instance_t _instance, bool _reliable);
-
bool handle_local_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,minor_version_t _minor);
- void remove_specific_client_endpoint(client_t _client, service_t _service, instance_t _instance, bool _reliable);
-
- void clear_identified_clients( service_t _service, instance_t _instance);
-
- void clear_identifying_clients( service_t _service, instance_t _instance);
-
- void remove_identified_client(service_t _service, instance_t _instance, client_t _client);
-
- void remove_identifying_client(service_t _service, instance_t _instance, client_t _client);
-
- void unsubscribe_specific_client_at_sd(service_t _service, instance_t _instance, client_t _client);
-
- inline std::shared_ptr<endpoint> find_local(service_t _service, instance_t _instance) {
- return routing_manager_base::find_local(_service, _instance);
- }
-
void send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type);
+ major_version_t _major, event_t _event);
void on_net_interface_or_route_state_changed(bool _is_interface,
std::string _if,
@@ -373,7 +355,7 @@ private:
void call_sd_endpoint_connected(const boost::system::error_code& _error,
service_t _service, instance_t _instance,
- std::shared_ptr<endpoint> _endpoint,
+ const std::shared_ptr<endpoint>& _endpoint,
std::shared_ptr<boost::asio::steady_timer> _timer);
bool create_placeholder_event_and_subscribe(service_t _service,
@@ -385,29 +367,26 @@ private:
void handle_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
- client_t is_specific_endpoint_client(client_t _client, service_t _service, instance_t _instance);
- std::unordered_set<client_t> get_specific_endpoint_clients(service_t _service, instance_t _instance);
-
void memory_log_timer_cbk(boost::system::error_code const & _error);
void status_log_timer_cbk(boost::system::error_code const & _error);
- void send_subscription(client_t _offering_client,
- client_t _subscribing_client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major,
- pending_subscription_id_t _pending_subscription_id);
+ void send_subscription(const client_t _offering_client,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup, const major_version_t _major,
+ const std::set<client_t> &_clients,
+ const remote_subscription_id_t _id);
- void send_unsubscription(
- client_t _offering_client, client_t _subscribing_client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _pending_unsubscription_id);
+ void send_unsubscription(client_t _offering_client,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup, const major_version_t _major,
+ const std::set<client_t> &_removed,
+ const remote_subscription_id_t _id);
void cleanup_server_endpoint(service_t _service,
const std::shared_ptr<endpoint>& _endpoint);
pending_remote_offer_id_t pending_remote_offer_add(service_t _service,
instance_t _instance);
-
std::pair<service_t, instance_t> pending_remote_offer_remove(
pending_remote_offer_id_t _id);
@@ -417,7 +396,7 @@ private:
std::shared_ptr<boost::asio::steady_timer> _timer);
pending_security_update_id_t pending_security_update_add(
- std::unordered_set<client_t> _clients);
+ const std::unordered_set<client_t>& _clients);
std::unordered_set<client_t> pending_security_update_get(
pending_security_update_id_t _id);
@@ -428,54 +407,28 @@ private:
bool is_pending_security_update_finished(
pending_security_update_id_t _id);
- std::shared_ptr<routing_manager_stub> stub_;
- std::shared_ptr<sd::service_discovery> discovery_;
-
- // Server endpoints for local services
- typedef std::map<uint16_t, std::map<bool, std::shared_ptr<endpoint>>> server_endpoints_t;
- server_endpoints_t server_endpoints_;
- std::map<service_t, std::map<endpoint *, instance_t> > service_instances_;
+ bool insert_offer_command(service_t _service, instance_t _instance, uint8_t _command,
+ client_t _client, major_version_t _major, minor_version_t _minor);
+ bool erase_offer_command(service_t _service, instance_t _instance);
- // Multicast endpoint info (notifications)
- std::map<service_t, std::map<instance_t, std::shared_ptr<endpoint_definition> > > multicast_info;
+ bool is_last_stop_callback(const uint32_t _callback_id);
- // Client endpoints for remote services
- std::map<service_t,
- std::map<instance_t, std::map<bool, std::shared_ptr<endpoint_definition> > > > remote_service_info_;
-
- typedef std::map<service_t, std::map<instance_t, std::map<client_t,
- std::map<bool, std::shared_ptr<endpoint>>>>> remote_services_t;
- remote_services_t remote_services_;
+private:
+ std::shared_ptr<routing_manager_stub> stub_;
+ std::shared_ptr<sd::service_discovery> discovery_;
- typedef std::map<boost::asio::ip::address, std::map<uint16_t,
- std::map<bool, std::shared_ptr<endpoint>>>> client_endpoints_by_ip_t;
- client_endpoints_by_ip_t client_endpoints_by_ip_;
+ std::mutex requested_services_mutex_;
std::map<client_t,
std::map<service_t,
std::map<instance_t,
std::set<std::pair<major_version_t, minor_version_t>>>>> requested_services_;
- // Mutexes
- mutable std::recursive_mutex endpoint_mutex_;
- std::mutex identified_clients_mutex_;
- std::mutex requested_services_mutex_;
-
std::mutex remote_subscribers_mutex_;
std::map<service_t, std::map<instance_t, std::map<client_t,
std::set<std::shared_ptr<endpoint_definition>>>>> remote_subscribers_;
- std::mutex specific_endpoint_clients_mutex_;
- std::map<service_t, std::map<instance_t, std::unordered_set<client_t>>>specific_endpoint_clients_;
- std::map<service_t, std::map<instance_t,
- std::map<bool, std::unordered_set<client_t> > > > identified_clients_;
- std::map<service_t, std::map<instance_t,
- std::map<bool, std::unordered_set<client_t> > > > identifying_clients_;
-
std::shared_ptr<serviceinfo> sd_info_;
- std::map<bool, std::set<uint16_t>> used_client_ports_;
- std::mutex used_client_ports_mutex_;
-
std::mutex version_log_timer_mutex_;
boost::asio::steady_timer version_log_timer_;
@@ -488,12 +441,6 @@ private:
std::shared_ptr<netlink_connector> netlink_connector_;
#endif
-#ifndef WITHOUT_SYSTEMD
- std::mutex watchdog_timer_mutex_;
- boost::asio::steady_timer watchdog_timer_;
- void watchdog_cbk(boost::system::error_code const &_error);
-#endif
-
std::mutex pending_offers_mutex_;
// map to store pending offers.
// 1st client id in tuple: client id of new offering application
@@ -509,8 +456,7 @@ private:
std::map<std::tuple<service_t, instance_t, eventgroup_t, client_t>,
subscription_state_e> remote_subscription_state_;
- std::map<e2exf::data_identifier_t, std::shared_ptr<e2e::profile_interface::protector>> custom_protectors;
- std::map<e2exf::data_identifier_t, std::shared_ptr<e2e::profile_interface::checker>> custom_checkers;
+ std::shared_ptr<e2e::e2e_provider> e2e_provider_;
std::mutex status_log_timer_mutex_;
boost::asio::steady_timer status_log_timer_;
@@ -518,6 +464,10 @@ private:
std::mutex memory_log_timer_mutex_;
boost::asio::steady_timer memory_log_timer_;
+ std::shared_ptr<endpoint_manager_impl> ep_mgr_impl_;
+
+ reboot_notification_handler_t reboot_notification_handler_;
+
routing_ready_handler_t routing_ready_handler_;
routing_state_handler_t routing_state_handler_;
@@ -537,8 +487,14 @@ private:
std::mutex security_update_timers_mutex_;
std::map<pending_security_update_id_t, std::shared_ptr<boost::asio::steady_timer>> security_update_timers_;
+
+ std::mutex offer_serialization_mutex_;
+ std::map<std::pair<service_t, instance_t>, std::deque<std::tuple<uint8_t, client_t, major_version_t, minor_version_t>>> offer_commands_;
+
+ std::mutex callback_counts_mutex_;
+ std::map<uint32_t, uint16_t> callback_counts_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_MANAGER_IMPL_HPP
+#endif // VSOMEIP_V3_ROUTING_MANAGER_IMPL_HPP_
diff --git a/implementation/routing/include/routing_manager_proxy.hpp b/implementation/routing/include/routing_manager_proxy.hpp
index fbe775d..d1a29df 100644
--- a/implementation/routing/include/routing_manager_proxy.hpp
+++ b/implementation/routing/include/routing_manager_proxy.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_PROXY_HPP
-#define VSOMEIP_ROUTING_MANAGER_PROXY_HPP
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP
+#define VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP
#include <map>
#include <mutex>
@@ -19,7 +19,7 @@
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/handler.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
class event;
@@ -37,68 +37,70 @@ public:
void start();
void stop();
- const std::shared_ptr<configuration> get_configuration() const;
+ std::shared_ptr<configuration> get_configuration() const;
- bool offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ bool offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void stop_offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor);
+ void stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy);
+ void request_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
- void release_service(client_t _client, service_t _service,
- instance_t _instance);
+ void release_service(client_t _client,
+ service_t _service, instance_t _instance);
- void subscribe(client_t _client, service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, event_t _event,
- subscription_type_e _subscription_type);
+ void subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ event_t _event);
- void unsubscribe(client_t _client, service_t _service, instance_t _instance,
+ void unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
bool send(client_t _client, const byte_t *_data, uint32_t _size,
- instance_t _instance, bool _flush, bool _reliable,
+ instance_t _instance, bool _reliable,
client_t _bound_client = VSOMEIP_ROUTING_CLIENT,
- bool _is_valid_crc = true, bool _sent_from_remote = false);
+ credentials_t _credentials = {ANY_UID, ANY_GID},
+ uint8_t _status_check = 0, bool _sent_from_remote = false);
- bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message, bool _flush);
+ bool send_to(const client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target,
+ std::shared_ptr<message> _message);
bool send_to(const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, instance_t _instance, bool _flush);
+ const byte_t *_data, uint32_t _size, instance_t _instance);
- void register_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups, bool _is_field,
+ void register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups,
+ const event_type_e _type,
+ reliability_type_e _reliability,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
+ bool _update_on_change,
epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder);
void unregister_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
- bool _is_provided);
+ instance_t _instance, event_t _notifier, bool _is_provided);
- void on_connect(std::shared_ptr<endpoint> _endpoint);
- void on_disconnect(std::shared_ptr<endpoint> _endpoint);
+ void on_connect(const std::shared_ptr<endpoint>& _endpoint);
+ void on_disconnect(const std::shared_ptr<endpoint>& _endpoint);
void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
client_t _bound_client,
+ credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
- void on_error(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port);
- void release_port(uint16_t _port, bool _reliable);
void on_routing_info(const byte_t *_data, uint32_t _size);
- void on_identify_response(client_t _client, service_t _service, instance_t _instance,
- bool _reliable);
-
void register_client_error_handler(client_t _client,
const std::shared_ptr<endpoint> &_endpoint);
void handle_client_error(client_t _client);
@@ -108,6 +110,7 @@ public:
void send_get_offered_services_info(client_t _client, offer_type_e _offer_type);
private:
+ void assign_client();
void register_application();
void deregister_application();
@@ -117,24 +120,25 @@ private:
void send_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
minor_version_t _minor);
- void send_release_service(client_t _client, service_t _service,
- instance_t _instance);
- void send_register_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
+ void send_release_service(client_t _client,
+ service_t _service, instance_t _instance);
+ void send_register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, bool _is_provided);
+ const event_type_e _type, reliability_type_e _reliability,
+ bool _is_provided);
void send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type);
+ major_version_t _major, event_t _event);
void send_subscribe_nack(client_t _subscriber, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id);
+ remote_subscription_id_t _id);
void send_subscribe_ack(client_t _subscriber, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id);
+ remote_subscription_id_t _id);
bool is_field(service_t _service, instance_t _instance,
event_t _event) const;
@@ -161,6 +165,8 @@ private:
eventgroup_t _eventgroup, bool _increment);
void clear_remote_subscriber_count(service_t _service, instance_t _instance);
+ void assign_client_timeout_cbk(boost::system::error_code const &_error);
+
void register_application_timeout_cbk(boost::system::error_code const &_error);
void send_registered_ack();
@@ -171,19 +177,16 @@ private:
bool is_client_known(client_t _client);
- bool create_placeholder_event_and_subscribe(service_t _service,
- instance_t _instance,
- eventgroup_t _eventgroup,
- event_t _event,
- client_t _client);
+ bool create_placeholder_event_and_subscribe(
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _notifier, client_t _client);
void request_debounce_timeout_cbk(boost::system::error_code const &_error);
void send_request_services(std::set<service_data_t>& _requests);
void send_unsubscribe_ack(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup,
- pending_subscription_id_t _subscription_id);
+ eventgroup_t _eventgroup, remote_subscription_id_t _id);
void resend_provided_event_registrations();
void send_resend_provided_event_response(pending_remote_offer_id_t _id);
@@ -191,12 +194,15 @@ private:
void send_update_security_policy_response(pending_security_update_id_t _update_id);
void send_remove_security_policy_response(pending_security_update_id_t _update_id);
void on_update_security_credentials(const byte_t *_data, uint32_t _size);
+ void on_client_assign_ack(const client_t &_client);
private:
enum class inner_state_type_e : std::uint8_t {
ST_REGISTERED = 0x0,
ST_DEREGISTERED = 0x1,
- ST_REGISTERING = 0x2
+ ST_REGISTERING = 0x2,
+ ST_ASSIGNING = 0x3,
+ ST_ASSIGNED = 0x4
};
std::atomic<bool> is_connected_;
@@ -216,17 +222,18 @@ private:
struct event_data_t {
service_t service_;
instance_t instance_;
- event_t event_;
- bool is_field_;
+ event_t notifier_;
+ event_type_e type_;
+ reliability_type_e reliability_;
bool is_provided_;
std::set<eventgroup_t> eventgroups_;
bool operator<(const event_data_t &_other) const {
- return std::tie(service_, instance_, event_, is_field_,
- is_provided_, eventgroups_)
- < std::tie(_other.service_, _other.instance_, _other.event_,
- _other.is_field_, _other.is_provided_,
- _other.eventgroups_);
+ return std::tie(service_, instance_, notifier_,
+ type_, reliability_, is_provided_, eventgroups_)
+ < std::tie(_other.service_, _other.instance_,
+ _other.notifier_, _other.type_, _other.reliability_,
+ _other.is_provided_, _other.eventgroups_);
}
};
std::set<event_data_t> pending_event_registrations_;
@@ -255,6 +262,6 @@ private:
const std::set<std::tuple<service_t, instance_t> > client_side_logging_filter_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_MANAGER_PROXY_HPP
+#endif // VSOMEIP_V3_ROUTING_MANAGER_PROXY_HPP_
diff --git a/implementation/routing/include/routing_manager_stub.hpp b/implementation/routing/include/routing_manager_stub.hpp
index d586518..4a37644 100644
--- a/implementation/routing/include/routing_manager_stub.hpp
+++ b/implementation/routing/include/routing_manager_stub.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_STUB
-#define VSOMEIP_ROUTING_MANAGER_STUB
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_
+#define VSOMEIP_V3_ROUTING_MANAGER_STUB_
#include <condition_variable>
#include <list>
@@ -20,54 +20,48 @@
#include <boost/asio/steady_timer.hpp>
#include "../../endpoints/include/endpoint_host.hpp"
-#include "../../configuration/include/internal.hpp"
+#include "../include/routing_host.hpp"
+
#include "types.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
class routing_manager_stub_host;
-class routing_manager_stub: public endpoint_host,
+class routing_manager_stub: public routing_host,
public std::enable_shared_from_this<routing_manager_stub> {
public:
routing_manager_stub(
routing_manager_stub_host *_host,
- std::shared_ptr<configuration> _configuration);
+ const std::shared_ptr<configuration>& _configuration);
virtual ~routing_manager_stub();
void init();
void start();
void stop();
- const std::shared_ptr<configuration> get_configuration() const;
-
- void on_connect(std::shared_ptr<endpoint> _endpoint);
- void on_disconnect(std::shared_ptr<endpoint> _endpoint);
void on_message(const byte_t *_data, length_t _size, endpoint *_receiver,
const boost::asio::ip::address &_destination,
client_t _bound_client,
+ credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port);
- void on_error(const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port);
- void release_port(uint16_t _port, bool _reliable);
void on_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor);
void on_stop_offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor);
- bool send_subscribe(std::shared_ptr<vsomeip::endpoint> _target,
+ bool send_subscribe(const std::shared_ptr<endpoint>& _target,
client_t _client, service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, pending_subscription_id_t _subscription_id);
+ eventgroup_t _eventgroup, major_version_t _major, event_t _event,
+ remote_subscription_id_t _id);
- bool send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _target,
+ bool send_unsubscribe(const std::shared_ptr<endpoint>& _target,
client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _unsubscription_id);
+ event_t _event, remote_subscription_id_t _id);
void send_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event);
@@ -86,14 +80,6 @@ public:
void handle_credentials(const client_t _client, std::set<service_data_t>& _requests);
void handle_requests(const client_t _client, std::set<service_data_t>& _requests);
- void send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
- service_t _service, instance_t _instance, major_version_t _major,
- bool _reliable);
-
-#ifndef _WIN32
- virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
-#endif
-
void update_registration(client_t _client, registration_type_e _type);
void print_endpoint_status() const;
@@ -103,12 +89,12 @@ public:
bool is_policy_cached(uint32_t _uid);
- void policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload);
+ void policy_cache_add(uint32_t _uid, const std::shared_ptr<payload>& _payload);
void policy_cache_remove(uint32_t _uid);
bool send_update_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
- uint32_t _uid, std::shared_ptr<payload> _payload);
+ uint32_t _uid, const std::shared_ptr<payload>& _payload);
bool send_remove_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
uint32_t _uid, uint32_t _gid);
@@ -131,7 +117,6 @@ private:
void on_pong(client_t _client);
void start_watchdog();
void check_watchdog();
- void send_application_lost(std::list<client_t> &_lost);
void client_registration_func(void);
void init_routing_endpoint();
@@ -175,8 +160,6 @@ private:
std::set<client_t> used_client_ids_;
std::mutex used_client_ids_mutex_;
- std::string endpoint_path_;
- std::string local_receiver_path_;
std::shared_ptr<endpoint> endpoint_;
std::shared_ptr<endpoint> local_receiver_;
std::mutex local_receiver_mutex_;
@@ -186,8 +169,6 @@ private:
mutable std::mutex routing_info_mutex_;
std::shared_ptr<configuration> configuration_;
- size_t routingCommandSize_;
-
bool is_socket_activated_;
std::atomic<bool> client_registration_running_;
std::shared_ptr<std::thread> client_registration_thread_;
@@ -215,7 +196,6 @@ private:
};
-} // namespace vsomeip
-
-#endif // VSOMEIP_ROUTING_MANAGER_STUB
+} // namespace vsomeip_v3
+#endif // VSOMEIP_V3_ROUTING_MANAGER_STUB_
diff --git a/implementation/routing/include/routing_manager_stub_host.hpp b/implementation/routing/include/routing_manager_stub_host.hpp
index 5c474fb..b89134d 100644
--- a/implementation/routing/include/routing_manager_stub_host.hpp
+++ b/implementation/routing/include/routing_manager_stub_host.hpp
@@ -3,15 +3,17 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_MANAGER_STUB_HOST
-#define VSOMEIP_ROUTING_MANAGER_STUB_HOST
+#ifndef VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_
+#define VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_
#include <boost/asio/io_service.hpp>
#include <vsomeip/handler.hpp>
#include "types.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
+
+class endpoint_manager_impl;
class routing_manager_stub_host {
public:
@@ -20,49 +22,52 @@ public:
virtual bool offer_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
- minor_version_t _minor) = 0;
+ minor_version_t _minor, bool _must_queue = true) = 0;
virtual void stop_offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) = 0;
-
- virtual void request_service(client_t _client, service_t _service,
instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy) = 0;
+ minor_version_t _minor, bool _must_queue = true) = 0;
+
+ virtual void request_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) = 0;
- virtual void release_service(client_t _client, service_t _service,
- instance_t _instance) = 0;
+ virtual void release_service(client_t _client,
+ service_t _service, instance_t _instance) = 0;
- virtual void register_shadow_event(client_t _client, service_t _service,
- instance_t _instance, event_t _event,
+ virtual void register_shadow_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, bool _is_provided) = 0;
+ event_type_e _type, reliability_type_e _reliability,
+ bool _is_provided) = 0;
virtual void unregister_shadow_event(client_t _client, service_t _service,
instance_t _instance, event_t _event, bool _is_provided) = 0;
- virtual void subscribe(client_t _client, service_t _service,
+ virtual void subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type) = 0;
+ major_version_t _major, event_t _event) = 0;
virtual void on_subscribe_nack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id) = 0;
+ remote_subscription_id_t _subscription_id) = 0;
virtual void on_subscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _subscription_id) = 0;
+ remote_subscription_id_t _subscription_id) = 0;
- virtual void unsubscribe(client_t _client, service_t _service,
+ virtual void unsubscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0;
virtual void on_unsubscribe_ack(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _unsubscription_id) = 0;
+ remote_subscription_id_t _unsubscription_id) = 0;
virtual bool on_message(service_t _service, instance_t _instance,
const byte_t *_data, length_t _size, bool _reliable, client_t _bound_client,
- bool _is_valid_crc = true, bool _is_from_remote = false) = 0;
+ credentials_t _credentials,
+ uint8_t _status_check = 0, bool _is_from_remote = false) = 0;
virtual void on_notification(client_t _client,
service_t _service, instance_t _instance,
@@ -84,25 +89,24 @@ public:
virtual boost::asio::io_service & get_io() = 0;
virtual client_t get_client() const = 0;
- virtual void on_identify_response(client_t _client, service_t _service, instance_t _instance,
- bool _reliable) = 0;
-
virtual void on_pong(client_t _client) = 0;
virtual void handle_client_error(client_t _client) = 0;
- virtual void set_routing_state(routing_state_e _routing_state) = 0;
+ virtual std::shared_ptr<endpoint_manager_impl> get_endpoint_manager() const = 0;
virtual void on_resend_provided_events_response(pending_remote_offer_id_t _id) = 0;
virtual void on_security_update_response(pending_security_update_id_t _id, client_t _client) = 0;
+ virtual client_t find_local_client(service_t _service, instance_t _instance) = 0;
+
virtual std::set<client_t> find_local_clients(service_t _service, instance_t _instance) = 0;
- virtual bool is_subscribe_to_any_event_allowed(client_t _client,
+ virtual bool is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup) = 0;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_MANAGER_STUB_HOST
+#endif // VSOMEIP_V3_ROUTING_MANAGER_STUB_HOST_
diff --git a/implementation/routing/include/serviceinfo.hpp b/implementation/routing/include/serviceinfo.hpp
index 72be585..a405cf0 100644
--- a/implementation/routing/include/serviceinfo.hpp
+++ b/implementation/routing/include/serviceinfo.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SERVICEINFO_HPP
-#define VSOMEIP_SERVICEINFO_HPP
+#ifndef VSOMEIP_V3_SERVICEINFO_HPP_
+#define VSOMEIP_V3_SERVICEINFO_HPP_
#include <memory>
#include <set>
@@ -15,14 +15,15 @@
#include <vsomeip/export.hpp>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
class servicegroup;
class serviceinfo {
public:
- VSOMEIP_EXPORT serviceinfo(major_version_t _major, minor_version_t _minor,
+ VSOMEIP_EXPORT serviceinfo(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
ttl_t _ttl, bool _is_local);
VSOMEIP_EXPORT serviceinfo(const serviceinfo& _other);
VSOMEIP_EXPORT ~serviceinfo();
@@ -30,6 +31,9 @@ public:
VSOMEIP_EXPORT servicegroup * get_group() const;
VSOMEIP_EXPORT void set_group(servicegroup *_group);
+ VSOMEIP_EXPORT service_t get_service() const;
+ VSOMEIP_EXPORT instance_t get_instance() const;
+
VSOMEIP_EXPORT major_version_t get_major() const;
VSOMEIP_EXPORT minor_version_t get_minor() const;
@@ -40,7 +44,7 @@ public:
VSOMEIP_EXPORT void set_precise_ttl(std::chrono::milliseconds _precise_ttl);
VSOMEIP_EXPORT std::shared_ptr<endpoint> get_endpoint(bool _reliable) const;
- VSOMEIP_EXPORT void set_endpoint(std::shared_ptr<endpoint> _endpoint,
+ VSOMEIP_EXPORT void set_endpoint(const std::shared_ptr<endpoint>& _endpoint,
bool _reliable);
VSOMEIP_EXPORT void add_client(client_t _client);
@@ -55,6 +59,9 @@ public:
private:
servicegroup *group_;
+ service_t service_;
+ instance_t instance_;
+
major_version_t major_;
minor_version_t minor_;
@@ -72,6 +79,6 @@ private:
bool is_in_mainphase_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SERVICEINFO_HPP
+#endif // VSOMEIP_V3_SERVICEINFO_HPP_
diff --git a/implementation/routing/include/types.hpp b/implementation/routing/include/types.hpp
index 59acfa3..389b226 100644
--- a/implementation/routing/include/types.hpp
+++ b/implementation/routing/include/types.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ROUTING_TYPES_HPP
-#define VSOMEIP_ROUTING_TYPES_HPP
+#ifndef VSOMEIP_V3_ROUTING_TYPES_HPP_
+#define VSOMEIP_V3_ROUTING_TYPES_HPP_
#include <map>
#include <memory>
@@ -13,10 +13,7 @@
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/constants.hpp>
-#include "../../service_discovery/include/message_impl.hpp"
-#include "../../configuration/include/internal.hpp"
-
-namespace vsomeip {
+namespace vsomeip_v3 {
class serviceinfo;
class endpoint_definition;
@@ -40,87 +37,20 @@ enum class registration_type_e : std::uint8_t {
DEREGISTER_ON_ERROR = 0x3
};
-struct sd_message_identifier_t {
- sd_message_identifier_t(session_t _session,
- boost::asio::ip::address _sender,
- boost::asio::ip::address _destination,
- const std::shared_ptr<sd::message_impl> &_response) :
- session_(_session),
- sender_(_sender),
- destination_(_destination),
- response_(_response) {
- }
-
- sd_message_identifier_t() :
- session_(0),
- sender_(boost::asio::ip::address()),
- destination_(boost::asio::ip::address()),
- response_(std::shared_ptr<sd::message_impl>()) {
- }
-
- bool operator==(const sd_message_identifier_t &_other) const {
- return !(session_ != _other.session_ ||
- sender_ != _other.sender_ ||
- destination_ != _other.destination_ ||
- response_ != _other.response_);
- }
-
- bool operator<(const sd_message_identifier_t &_other) const {
- return (session_ < _other.session_
- || (session_ == _other.session_ && sender_ < _other.sender_)
- || (session_ == _other.session_ && sender_ == _other.sender_
- && destination_ < _other.destination_)
- || (session_ == _other.session_ && sender_ == _other.sender_
- && destination_ == _other.destination_
- && response_ < _other.response_));
- }
-
- session_t session_;
- boost::asio::ip::address sender_;
- boost::asio::ip::address destination_;
- std::shared_ptr<sd::message_impl> response_;
-};
+enum class remote_subscription_state_e : std::uint8_t {
+ SUBSCRIPTION_PENDING = 0x00,
-struct pending_subscription_t {
- pending_subscription_t(
- std::shared_ptr<sd_message_identifier_t> _sd_message_identifier,
- std::shared_ptr<endpoint_definition> _subscriber,
- std::shared_ptr<endpoint_definition> _target,
- ttl_t _ttl,
- client_t _subscribing_client) :
- sd_message_identifier_(_sd_message_identifier),
- subscriber_(_subscriber),
- target_(_target),
- ttl_(_ttl),
- subscribing_client_(_subscribing_client),
- pending_subscription_id_(DEFAULT_SUBSCRIPTION) {
- }
- pending_subscription_t () :
- sd_message_identifier_(std::shared_ptr<sd_message_identifier_t>()),
- subscriber_(std::shared_ptr<endpoint_definition>()),
- target_(std::shared_ptr<endpoint_definition>()),
- ttl_(0),
- subscribing_client_(VSOMEIP_ROUTING_CLIENT),
- pending_subscription_id_(DEFAULT_SUBSCRIPTION) {
- }
- std::shared_ptr<sd_message_identifier_t> sd_message_identifier_;
- std::shared_ptr<endpoint_definition> subscriber_;
- std::shared_ptr<endpoint_definition> target_;
- ttl_t ttl_;
- client_t subscribing_client_;
- pending_subscription_id_t pending_subscription_id_;
-};
+ SUBSCRIPTION_ACKED = 0x01,
+ SUBSCRIPTION_NACKED = 0x02,
-enum remote_subscription_state_e : std::uint8_t {
- SUBSCRIPTION_ACKED,
- SUBSCRIPTION_NACKED,
- SUBSCRIPTION_PENDING,
- SUBSCRIPTION_ERROR
+ SUBSCRIPTION_ERROR = 0x03,
+ SUBSCRIPTION_UNKNOWN = 0xFF
};
+typedef std::uint16_t remote_subscription_id_t;
typedef std::uint32_t pending_remote_offer_id_t;
}
-// namespace vsomeip
+// namespace vsomeip_v3
-#endif // VSOMEIP_ROUTING_TYPES_HPP
+#endif // VSOMEIP_V3_ROUTING_TYPES_HPP_
diff --git a/implementation/routing/src/event.cpp b/implementation/routing/src/event.cpp
index ce78a65..7575733 100644
--- a/implementation/routing/src/event.cpp
+++ b/implementation/routing/src/event.cpp
@@ -4,25 +4,27 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <iomanip>
+#include <sstream>
#include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
#include <vsomeip/message.hpp>
#include <vsomeip/payload.hpp>
#include <vsomeip/runtime.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/event.hpp"
#include "../include/routing_manager.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../message/include/payload_impl.hpp"
-namespace vsomeip {
+#include "../../endpoints/include/endpoint_definition.hpp"
+
+namespace vsomeip_v3 {
event::event(routing_manager *_routing, bool _is_shadow) :
routing_(_routing),
message_(runtime::get()->create_notification()),
- is_field_(false),
+ type_(event_type_e::ET_EVENT),
cycle_timer_(_routing->get_io()),
cycle_(std::chrono::milliseconds::zero()),
change_resets_cycle_(false),
@@ -33,8 +35,7 @@ event::event(routing_manager *_routing, bool _is_shadow) :
is_cache_placeholder_(false),
epsilon_change_func_(std::bind(&event::compare, this,
std::placeholders::_1, std::placeholders::_2)),
- is_reliable_(false),
- remote_notification_pending_(false) {
+ reliability_(reliability_type_e::RT_UNKNOWN) {
}
service_t event::get_service() const {
@@ -69,12 +70,16 @@ void event::set_event(event_t _event) {
message_->set_method(_event); // TODO: maybe we should check for the leading 0-bit
}
-bool event::is_field() const {
- return (is_field_);
+event_type_e event::get_type() const {
+ return (type_);
}
-void event::set_field(bool _is_field) {
- is_field_ = _is_field;
+void event::set_type(const event_type_e _type) {
+ type_ = _type;
+}
+
+bool event::is_field() const {
+ return (type_ == event_type_e::ET_FIELD);
}
bool event::is_provided() const {
@@ -109,8 +114,7 @@ bool event::set_payload_dont_notify(const std::shared_ptr<payload> &_payload) {
return true;
}
-void event::set_payload(const std::shared_ptr<payload> &_payload,
- bool _force, bool _flush) {
+void event::set_payload(const std::shared_ptr<payload> &_payload, bool _force) {
std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
@@ -119,7 +123,7 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
if (change_resets_cycle_)
stop_cycle();
- notify(_flush);
+ notify();
if (change_resets_cycle_)
start_cycle();
@@ -132,13 +136,13 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
}
void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _client,
- bool _force, bool _flush) {
+ bool _force) {
std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one_unlocked(_client, _flush);
+ notify_one_unlocked(_client);
}
}
} else {
@@ -148,14 +152,15 @@ void event::set_payload(const std::shared_ptr<payload> &_payload, client_t _clie
}
void event::set_payload(const std::shared_ptr<payload> &_payload,
- const std::shared_ptr<endpoint_definition> _target,
- bool _force, bool _flush) {
+ const client_t _client,
+ const std::shared_ptr<endpoint_definition>& _target,
+ bool _force) {
std::lock_guard<std::mutex> its_lock(mutex_);
if (is_provided_) {
if (set_payload_helper(_payload, _force)) {
reset_payload(_payload);
if (is_updating_on_change_) {
- notify_one_unlocked(_target, _flush);
+ notify_one_unlocked(_client, _target);
}
}
} else {
@@ -164,6 +169,25 @@ void event::set_payload(const std::shared_ptr<payload> &_payload,
}
}
+bool event::set_payload_notify_pending(const std::shared_ptr<payload> &_payload) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ if (!is_set_ && is_provided_) {
+ reset_payload(_payload);
+
+ // Send pending initial events.
+ for (const auto &its_target : pending_) {
+ message_->set_session(routing_->get_session());
+ routing_->send_to(VSOMEIP_ROUTING_CLIENT,
+ its_target, message_);
+ }
+ pending_.clear();
+
+ return true;
+ }
+
+ return false;
+}
+
void event::unset_payload(bool _force) {
std::lock_guard<std::mutex> its_lock(mutex_);
if (_force) {
@@ -209,7 +233,7 @@ const std::set<eventgroup_t> event::get_eventgroups() const {
std::set<eventgroup_t> its_eventgroups;
{
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
- for (const auto e : eventgroups_) {
+ for (const auto& e : eventgroups_) {
its_eventgroups.insert(e.first);
}
}
@@ -243,7 +267,7 @@ void event::update_cbk(boost::system::error_code const &_error) {
if (!_error) {
std::lock_guard<std::mutex> its_lock(mutex_);
cycle_timer_.expires_from_now(cycle_);
- notify(true);
+ notify();
auto its_handler =
std::bind(&event::update_cbk, shared_from_this(),
std::placeholders::_1);
@@ -251,47 +275,70 @@ void event::update_cbk(boost::system::error_code const &_error) {
}
}
-void event::notify(bool _flush) {
+void event::notify() {
if (is_set_) {
- routing_->send(VSOMEIP_ROUTING_CLIENT, message_, _flush);
+ message_->set_session(routing_->get_session());
+ routing_->send(VSOMEIP_ROUTING_CLIENT, message_);
} else {
- VSOMEIP_INFO << "Notify event " << std::hex << message_->get_method()
- << "failed. Event payload not set!";
+ VSOMEIP_INFO << __func__
+ << ": Notifying " << std::hex << get_event()
+ << " failed. Event payload not (yet) set!";
}
}
-void event::notify_one(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- notify_one_unlocked(_target, _flush);
+void event::notify_one(client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target) {
+ if (_target) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ notify_one_unlocked(_client, _target);
+ } else {
+ VSOMEIP_WARNING << __func__
+ << ": Notifying " << std::hex << get_event()
+ << " failed. Target undefined";
+ }
}
-void event::notify_one_unlocked(const std::shared_ptr<endpoint_definition> &_target, bool _flush) {
- if (is_set_) {
- routing_->send_to(_target, message_, _flush);
+void event::notify_one_unlocked(client_t _client,
+ const std::shared_ptr<endpoint_definition> &_target) {
+ if (_target) {
+ if (is_set_) {
+ message_->set_session(routing_->get_session());
+ routing_->send_to(_client, _target, message_);
+ } else {
+ VSOMEIP_INFO << __func__
+ << ": Notifying " << std::hex << get_event()
+ << " failed. Event payload not (yet) set!";
+ pending_.insert(_target);
+ }
} else {
- VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method()
- << "failed. Event payload not set!";
+ VSOMEIP_WARNING << __func__
+ << ": Notifying " << std::hex << get_event()
+ << " failed. Target undefined";
}
}
-void event::notify_one(client_t _client, bool _flush) {
+void event::notify_one(client_t _client) {
std::lock_guard<std::mutex> its_lock(mutex_);
- notify_one_unlocked(_client, _flush);
+ notify_one_unlocked(_client);
}
-void event::notify_one_unlocked(client_t _client, bool _flush) {
+void event::notify_one_unlocked(client_t _client) {
if (is_set_) {
- routing_->send(_client, message_, _flush);
+ message_->set_session(routing_->get_session());
+ routing_->send(_client, message_);
} else {
- VSOMEIP_INFO << "Notify one event " << std::hex << message_->get_method()
- << " to client " << _client << " failed. Event payload not set!";
+ VSOMEIP_INFO << __func__
+ << ": Notifying "
+ << std::hex << message_->get_method()
+ << " to client " << _client
+ << " failed. Event payload not set!";
}
}
bool event::set_payload_helper(const std::shared_ptr<payload> &_payload, bool _force) {
std::shared_ptr<payload> its_payload = message_->get_payload();
- bool is_change(!is_field_);
- if (is_field_) {
+ bool is_change(type_ != event_type_e::ET_FIELD);
+ if (!is_change) {
is_change = _force || epsilon_change_func_(its_payload, _payload);
}
return is_change;
@@ -357,7 +404,7 @@ bool event::add_subscriber(eventgroup_t _eventgroup, client_t _client, bool _for
} else {
VSOMEIP_WARNING << __func__ << ": Didnt' insert client "
<< std::hex << std::setw(4) << std::setfill('0') << _client
- << "to eventgroup 0x"
+ << " to eventgroup 0x"
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup;
}
return ret;
@@ -480,20 +527,20 @@ bool event::is_subscribed(client_t _client) {
return false;
}
-bool event::is_reliable() const {
- return is_reliable_;
+reliability_type_e
+event::get_reliability() const {
+ return reliability_;
}
-void event::set_reliable(bool _is_reliable) {
- is_reliable_ = _is_reliable;
+void
+event::set_reliability(const reliability_type_e _reliability) {
+ reliability_ = _reliability;
}
-bool event::get_remote_notification_pending() {
- return remote_notification_pending_;
-}
-
-void event::set_remote_notification_pending(bool _value) {
- remote_notification_pending_ = _value;
+void
+event::remove_pending(const std::shared_ptr<endpoint_definition> &_target) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ pending_.erase(_target);
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/eventgroupinfo.cpp b/implementation/routing/src/eventgroupinfo.cpp
index 77bb228..52c6c1e 100644
--- a/implementation/routing/src/eventgroupinfo.cpp
+++ b/implementation/routing/src/eventgroupinfo.cpp
@@ -4,46 +4,77 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <algorithm>
+#include <iomanip>
#include <vsomeip/constants.hpp>
-
+#include <vsomeip/internal/logger.hpp>
#include "../include/eventgroupinfo.hpp"
#include "../include/event.hpp"
+#include "../include/remote_subscription.hpp"
#include "../../endpoints/include/endpoint_definition.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../configuration/include/internal.hpp"
-
-namespace vsomeip {
-eventgroupinfo::eventgroupinfo() :
- major_(DEFAULT_MAJOR),
- ttl_(DEFAULT_TTL),
- port_(ILLEGAL_PORT),
- threshold_(0),
- has_reliable_(false),
- has_unreliable_(false),
- subscription_id_(DEFAULT_SUBSCRIPTION) {
+namespace vsomeip_v3 {
+
+eventgroupinfo::eventgroupinfo()
+ : service_(0),
+ instance_(0),
+ eventgroup_(0),
+ major_(DEFAULT_MAJOR),
+ ttl_(DEFAULT_TTL),
+ port_(ILLEGAL_PORT),
+ threshold_(0),
+ id_(PENDING_SUBSCRIPTION_ID),
+ reliability_(reliability_type_e::RT_UNKNOWN) {
}
-eventgroupinfo::eventgroupinfo(major_version_t _major, ttl_t _ttl) :
- major_(_major),
- ttl_(_ttl),
- port_(ILLEGAL_PORT),
- threshold_(0),
- has_reliable_(false),
- has_unreliable_(false),
- subscription_id_(DEFAULT_SUBSCRIPTION) {
+eventgroupinfo::eventgroupinfo(
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup, const major_version_t _major,
+ const ttl_t _ttl)
+ : service_(_service),
+ instance_(_instance),
+ eventgroup_(_eventgroup),
+ major_(_major),
+ ttl_(_ttl),
+ port_(ILLEGAL_PORT),
+ threshold_(0),
+ id_(PENDING_SUBSCRIPTION_ID),
+ reliability_(reliability_type_e::RT_UNKNOWN) {
}
eventgroupinfo::~eventgroupinfo() {
}
+service_t eventgroupinfo::get_service() const {
+ return service_;
+}
+
+void eventgroupinfo::set_service(const service_t _service) {
+ service_ = _service;
+}
+
+instance_t eventgroupinfo::get_instance() const {
+ return instance_;
+}
+
+void eventgroupinfo::set_instance(const instance_t _instance) {
+ instance_ = _instance;
+}
+
+eventgroup_t eventgroupinfo::get_eventgroup() const {
+ return eventgroup_;
+}
+
+void eventgroupinfo::set_eventgroup(const eventgroup_t _eventgroup) {
+ eventgroup_ = _eventgroup;
+}
+
major_version_t eventgroupinfo::get_major() const {
return major_;
}
-void eventgroupinfo::set_major(major_version_t _major) {
+void eventgroupinfo::set_major(const major_version_t _major) {
major_ = _major;
}
@@ -51,7 +82,7 @@ ttl_t eventgroupinfo::get_ttl() const {
return ttl_;
}
-void eventgroupinfo::set_ttl(ttl_t _ttl) {
+void eventgroupinfo::set_ttl(const ttl_t _ttl) {
ttl_ = _ttl;
}
@@ -89,264 +120,239 @@ const std::set<std::shared_ptr<event> > eventgroupinfo::get_events() const {
return events_;
}
-void eventgroupinfo::add_event(std::shared_ptr<event> _event) {
+void eventgroupinfo::add_event(const std::shared_ptr<event>& _event) {
std::lock_guard<std::mutex> its_lock(events_mutex_);
events_.insert(_event);
- _event->is_reliable() ? has_reliable_ = true : has_unreliable_ = true;
+
+ switch (_event->get_reliability()) {
+ case reliability_type_e::RT_RELIABLE:
+ if (reliability_ == reliability_type_e::RT_UNRELIABLE) {
+ reliability_ = reliability_type_e::RT_BOTH;
+ } else if (reliability_ != reliability_type_e::RT_BOTH) {
+ reliability_ = reliability_type_e::RT_RELIABLE;
+ }
+ break;
+ case reliability_type_e::RT_UNRELIABLE:
+ if (reliability_ == reliability_type_e::RT_RELIABLE) {
+ reliability_ = reliability_type_e::RT_BOTH;
+ } else if (reliability_ != reliability_type_e::RT_BOTH) {
+ reliability_ = reliability_type_e::RT_UNRELIABLE;
+ }
+ break;
+ case reliability_type_e::RT_BOTH:
+ reliability_ = reliability_type_e::RT_BOTH;
+ break;
+ default:
+ ;
+ }
}
-void eventgroupinfo::remove_event(std::shared_ptr<event> _event) {
+void eventgroupinfo::remove_event(const std::shared_ptr<event>& _event) {
std::lock_guard<std::mutex> its_lock(events_mutex_);
events_.erase(_event);
}
-void eventgroupinfo::get_reliability(bool& _has_reliable, bool& _has_unreliable) const {
- _has_reliable = has_reliable_;
- _has_unreliable = has_unreliable_;
+reliability_type_e eventgroupinfo::get_reliability() const {
+ return reliability_;
}
-const std::list<eventgroupinfo::target_t> eventgroupinfo::get_targets() const {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- return targets_;
-}
+uint32_t
+eventgroupinfo::get_unreliable_target_count() const {
+ uint32_t its_count(0);
-uint32_t eventgroupinfo::get_unreliable_target_count() const {
- uint32_t _count(0);
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- for (auto i = targets_.begin(); i != targets_.end(); i++) {
- if (!i->endpoint_->is_reliable()) {
- _count++;
- }
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ for (const auto &s : subscriptions_) {
+ auto its_subscription = s.second;
+ if (!its_subscription->get_parent()
+ && its_subscription->get_unreliable()) {
+ its_count++;
+ }
}
- return _count;
+
+ return its_count;
}
-void eventgroupinfo::add_multicast_target(const eventgroupinfo::target_t &_multicast_target) {
- std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_);
- if (std::find(multicast_targets_.begin(), multicast_targets_.end(), _multicast_target)
- == multicast_targets_.end()) {
- multicast_targets_.push_back(_multicast_target);
- }
+uint8_t eventgroupinfo::get_threshold() const {
+ return threshold_;
}
-void eventgroupinfo::clear_multicast_targets() {
- std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_);
- multicast_targets_.clear();
+void eventgroupinfo::set_threshold(uint8_t _threshold) {
+ threshold_ = _threshold;
}
-const std::list<eventgroupinfo::target_t> eventgroupinfo::get_multicast_targets() const {
- std::lock_guard<std::mutex> its_lock(multicast_targets_mutex_);
- return multicast_targets_;
+std::set<std::shared_ptr<remote_subscription> >
+eventgroupinfo::get_remote_subscriptions() const {
+ std::set<std::shared_ptr<remote_subscription> > its_subscriptions;
+
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ for (const auto &i : subscriptions_)
+ its_subscriptions.insert(i.second);
+
+ return its_subscriptions;
}
-bool eventgroupinfo::add_target(const eventgroupinfo::target_t &_target) {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- std::size_t its_size = targets_.size();
- if (std::find(targets_.begin(), targets_.end(), _target) == targets_.end()) {
- targets_.push_back(_target);
- }
- return (its_size != targets_.size());
-}
-
-bool eventgroupinfo::add_target(const eventgroupinfo::target_t &_target,
- const eventgroupinfo::target_t &_subscriber) {
- bool found(false);
- bool add(false);
- bool ret(false);
- {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- std::size_t its_size = targets_.size();
-
- for (auto i = targets_.begin(); i != targets_.end(); i++) {
- if (i->endpoint_->get_address() == _subscriber.endpoint_->get_address() &&
- i->endpoint_->get_port() == _subscriber.endpoint_->get_port() &&
- i->endpoint_->is_reliable() == _subscriber.endpoint_->is_reliable()) {
- found = true;
- break;
+bool
+eventgroupinfo::update_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription,
+ const std::chrono::steady_clock::time_point &_expiration,
+ std::set<client_t> &_changed, remote_subscription_id_t &_id,
+ const bool _is_subscribe) {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+
+ for (const auto& its_item : subscriptions_) {
+ if (its_item.second->equals(_subscription)) {
+ // update existing subscription
+ _changed = its_item.second->update(
+ _subscription->get_clients(), _expiration, _is_subscribe);
+ _id = its_item.second->get_id();
+
+ // Copy acknowledgment states from existing subscription
+ for (const auto its_client : _subscription->get_clients()) {
+ _subscription->set_client_state(its_client,
+ its_item.second->get_client_state(its_client));
}
- }
- if (!found) {
- targets_.push_back(_subscriber);
- add = true;
- }
- ret = (its_size != targets_.size());
- }
- if (add) {
- add_multicast_target(_target);
- }
- return ret;
-}
-
-bool eventgroupinfo::update_target(
- const std::shared_ptr<endpoint_definition> &_target,
- const std::chrono::steady_clock::time_point &_expiration) {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- bool updated_target(false);
-
- for (auto i = targets_.begin(); i != targets_.end(); i++) {
- if (i->endpoint_->get_address() == _target->get_address() &&
- i->endpoint_->get_port() == _target->get_port() &&
- i->endpoint_->is_reliable() == _target->is_reliable() ) {
- i->expiration_ = _expiration;
- updated_target = true;
- break;
+ if (_is_subscribe) {
+ if (!_changed.empty()) {
+ // New clients:
+ // Let this be a child subscription
+ _subscription->set_parent(its_item.second);
+ update_id();
+ _subscription->set_id(id_);
+ subscriptions_[id_] = _subscription;
+ } else {
+ if (!_subscription->is_pending()) {
+ if (!_subscription->force_initial_events()) {
+ _subscription->set_initial(false);
+ }
+ } else {
+ its_item.second->set_answers(
+ its_item.second->get_answers() + 1);
+ }
+ }
+ } else {
+ if (its_item.second->is_pending()) {
+ for (const auto &its_event : events_)
+ its_event->remove_pending(
+ its_item.second->get_subscriber());
+ }
+ }
+
+ return true;
}
}
- return updated_target;
+
+ return false;
}
-bool eventgroupinfo::remove_target(
- const std::shared_ptr<endpoint_definition> &_target) {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- std::size_t its_size = targets_.size();
+remote_subscription_id_t
+eventgroupinfo::add_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription) {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ update_id();
- for (auto i = targets_.begin(); i != targets_.end(); i++) {
- if (i->endpoint_->get_address() == _target->get_address() &&
- i->endpoint_->get_port() == _target->get_port() &&
- i->endpoint_->is_reliable() == _target->is_reliable()) {
- targets_.erase(i);
- break;
- }
- }
+ _subscription->set_id(id_);
+ subscriptions_[id_] = _subscription;
- return (its_size != targets_.size());
+ return id_;
}
-void eventgroupinfo::clear_targets() {
- std::lock_guard<std::mutex> its_lock(targets_mutex_);
- targets_.clear();
+std::shared_ptr<remote_subscription>
+eventgroupinfo::get_remote_subscription(
+ const remote_subscription_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+
+ auto find_subscription = subscriptions_.find(_id);
+ if (find_subscription != subscriptions_.end())
+ return find_subscription->second;
+
+ return nullptr;
}
-uint8_t eventgroupinfo::get_threshold() const {
- return threshold_;
+void
+eventgroupinfo::remove_remote_subscription(
+ const remote_subscription_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ subscriptions_.erase(_id);
}
-void eventgroupinfo::set_threshold(uint8_t _threshold) {
- threshold_ = _threshold;
+std::set<std::shared_ptr<endpoint_definition> >
+eventgroupinfo::get_unicast_targets() const {
+ std::set<std::shared_ptr<endpoint_definition>> its_targets;
+
+ std::lock_guard<std::mutex> its_lock(subscriptions_mutex_);
+ for (const auto &s : subscriptions_) {
+ const auto its_reliable = s.second->get_reliable();
+ if (its_reliable)
+ its_targets.insert(its_reliable);
+ const auto its_unreliable = s.second->get_unreliable();
+ if (its_unreliable)
+ its_targets.insert(its_unreliable);
+ }
+
+ return its_targets;
}
-std::unique_lock<std::mutex> eventgroupinfo::get_subscription_lock() {
- return std::unique_lock<std::mutex>(subscription_mutex_);
+std::set<std::shared_ptr<endpoint_definition> >
+eventgroupinfo::get_multicast_targets() const {
+ std::set<std::shared_ptr<endpoint_definition>> its_targets;
+ return its_targets;
}
-pending_subscription_id_t eventgroupinfo::add_pending_subscription(
- pending_subscription_t _pending_subscription) {
- std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_);
- if (++subscription_id_ == DEFAULT_SUBSCRIPTION) {
- subscription_id_++;
- }
- _pending_subscription.pending_subscription_id_ = subscription_id_;
- pending_subscriptions_[subscription_id_] = _pending_subscription;
-
- const auto remote_address_port = std::make_tuple(
- _pending_subscription.subscriber_->get_address(),
- _pending_subscription.subscriber_->get_port(),
- _pending_subscription.subscriber_->is_reliable());
-
- auto found_address = pending_subscriptions_by_remote_.find(remote_address_port);
- if (found_address != pending_subscriptions_by_remote_.end()) {
- found_address->second.push_back(subscription_id_);
- VSOMEIP_WARNING << __func__ << " num pending subscriptions: "
- << std::dec << found_address->second.size();
- return DEFAULT_SUBSCRIPTION;
- } else {
- pending_subscriptions_by_remote_[remote_address_port].push_back(subscription_id_);
- }
- return subscription_id_;
-}
-
-std::vector<pending_subscription_t> eventgroupinfo::remove_pending_subscription(
- pending_subscription_id_t _subscription_id) {
- std::vector<pending_subscription_t> its_pending_subscriptions;
- std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_);
- const auto found_pending_subscription = pending_subscriptions_.find(
- _subscription_id);
- if (found_pending_subscription != pending_subscriptions_.end()) {
- pending_subscription_t its_pending_sub = found_pending_subscription->second;
- const auto remote_address_port = std::make_tuple(
- its_pending_sub.subscriber_->get_address(),
- its_pending_sub.subscriber_->get_port(),
- its_pending_sub.subscriber_->is_reliable());
- const bool removed_is_subscribe = (found_pending_subscription->second.ttl_ > 0);
-
- // check if more (un)subscriptions to this eventgroup arrived from the
- // same remote during the time the current pending subscription was processed
- auto found_remote = pending_subscriptions_by_remote_.find(remote_address_port);
- if (found_remote != pending_subscriptions_by_remote_.end()) {
- if (found_remote->second.size()
- && found_remote->second.front() == _subscription_id) {
- pending_subscriptions_.erase(found_pending_subscription);
- found_remote->second.erase(found_remote->second.begin());
-
- // return removed (un)subscription as first element
- its_pending_subscriptions.push_back(its_pending_sub);
-
- // retrieve all pending (un)subscriptions which arrived during
- // the time the rm_proxy answered the currently processed subscription
- for (auto iter = found_remote->second.begin();
- iter != found_remote->second.end();) {
- const auto other_pen_sub = pending_subscriptions_.find(*iter);
- if (other_pen_sub != pending_subscriptions_.end()) {
- const bool queued_is_subscribe = (other_pen_sub->second.ttl_ > 0);
- if (removed_is_subscribe) {
- its_pending_subscriptions.push_back(other_pen_sub->second);
- if (!queued_is_subscribe) {
- // unsubscribe was queued and needs to be sent to
- // rm_proxy first before continuing processing
- // following queued (un)subscriptions
- break;
- } else {
- iter = found_remote->second.erase(iter);
- pending_subscriptions_.erase(other_pen_sub);
- }
- } else {
- if (queued_is_subscribe) {
- // subscribe was queued and needs to be sent to
- // rm_proxy first before continuing processing
- // following queued (un)subscriptions
- its_pending_subscriptions.push_back(other_pen_sub->second);
- break;
- } else {
- // further queued unsubscriptions can be ignored
- iter = found_remote->second.erase(iter);
- pending_subscriptions_.erase(other_pen_sub);
- }
- }
- } else {
- VSOMEIP_ERROR << __func__ << " didn't find queued subscription: "
- << *iter;
- ++iter;
- }
- }
+bool eventgroupinfo::is_selective() const {
+ /* Selective eventgroups always contain a single event */
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ if (events_.size() != 1)
+ return false;
- if (found_remote->second.empty()) {
- pending_subscriptions_by_remote_.erase(found_remote);
- }
- } else {
- boost::system::error_code ec;
- VSOMEIP_WARNING << __func__ << " Subscriptions were answered in "
- << " in wrong order by rm_proxy! ["
- << " subscriber: " << std::get<0>(remote_address_port).to_string(ec)
- << ":" << std::dec << std::get<1>(remote_address_port);
- // found_pending_subscription isn't deleted from
- // pending_subscriptions_ map in this case to ensure answer
- // sequence of SD messages.
- its_pending_subscriptions.clear();
- }
- }
- } else {
- VSOMEIP_ERROR << __func__ << " didn't find pending_subscription: "
- << _subscription_id;
- }
- return its_pending_subscriptions;
+ return ((*events_.begin())->get_type()
+ == event_type_e::ET_SELECTIVE_EVENT);
}
+void
+eventgroupinfo::update_id() {
+ id_++;
+ if (id_ == PENDING_SUBSCRIPTION_ID)
+ id_ = 1;
+}
-void eventgroupinfo::clear_pending_subscriptions() {
- std::lock_guard<std::mutex> its_lock(pending_subscriptions_mutex_);
- pending_subscriptions_.clear();
- pending_subscriptions_by_remote_.clear();
+void
+eventgroupinfo::send_initial_events(
+ const std::shared_ptr<endpoint_definition> &_reliable,
+ const std::shared_ptr<endpoint_definition> &_unreliable) const {
+ std::lock_guard<std::mutex> its_lock(events_mutex_);
+ for (const auto &its_event : events_) {
+ if (its_event && its_event->get_type() == event_type_e::ET_FIELD) {
+#ifndef VSOMEIP_ENABLE_COMPAT
+ const auto its_reliability = its_event->get_reliability();
+ switch (its_reliability) {
+ case reliability_type_e::RT_RELIABLE:
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+ break;
+ case reliability_type_e::RT_UNRELIABLE:
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ break;
+ case reliability_type_e::RT_BOTH:
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ break;
+ default:
+ VSOMEIP_WARNING << __func__ << "Event reliability unknown: ["
+ << std::hex << std::setw(4) << std::setfill('0') << service_ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << instance_ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << eventgroup_ << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_event->get_event() << "]";
+ }
+#else
+ if (_reliable) {
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _reliable);
+ }
+ if (_unreliable) {
+ its_event->notify_one(VSOMEIP_ROUTING_CLIENT, _unreliable);
+ }
+#endif
+ }
+ }
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/remote_subscription.cpp b/implementation/routing/src/remote_subscription.cpp
new file mode 100644
index 0000000..a896b36
--- /dev/null
+++ b/implementation/routing/src/remote_subscription.cpp
@@ -0,0 +1,315 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/remote_subscription.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+
+namespace vsomeip_v3 {
+
+remote_subscription::remote_subscription()
+ : id_(PENDING_SUBSCRIPTION_ID),
+ is_initial_(true),
+ force_initial_events_(false),
+ major_(DEFAULT_MAJOR),
+ ttl_(DEFAULT_TTL),
+ reserved_(0),
+ counter_(0),
+ answers_(1) {
+}
+
+remote_subscription::~remote_subscription() {
+}
+
+bool
+remote_subscription::operator==(
+ const remote_subscription &_other) const {
+ auto own_egi = eventgroupinfo_.lock();
+ auto other_egi = _other.eventgroupinfo_.lock();
+ bool reliable_equal(true);
+ if (reliable_ && _other.reliable_) {
+ reliable_equal = (reliable_ == _other.reliable_);
+ }
+ bool unreliable_equal(true);
+ if (unreliable_ && _other.unreliable_) {
+ unreliable_equal = (unreliable_ == _other.unreliable_);
+ }
+ return (own_egi && other_egi && own_egi == other_egi && unreliable_equal
+ && reliable_equal);
+}
+
+bool
+remote_subscription::equals(
+ const std::shared_ptr<remote_subscription> &_other) const {
+ return operator ==(*_other);
+}
+
+void
+remote_subscription::reset(const std::set<client_t> &_clients) {
+ auto its_client_state = std::make_pair(
+ remote_subscription_state_e::SUBSCRIPTION_PENDING,
+ std::chrono::steady_clock::time_point());
+ if (_clients.empty()) {
+ clients_[0] = its_client_state;
+ } else {
+ for (const auto &its_client : _clients)
+ clients_[its_client] = its_client_state;
+ }
+}
+
+bool
+remote_subscription::is_initial() const {
+ return is_initial_;
+}
+
+void
+remote_subscription::set_initial(const bool _is_initial) {
+ is_initial_ = _is_initial;
+}
+
+bool
+remote_subscription::force_initial_events() const {
+ return force_initial_events_;
+}
+
+void
+remote_subscription::set_force_initial_events(
+ const bool _force_initial_events) {
+ force_initial_events_ = _force_initial_events;
+}
+
+remote_subscription_id_t
+remote_subscription::get_id() const {
+ return id_;
+}
+
+void
+remote_subscription::set_id(const remote_subscription_id_t _id) {
+ id_ = _id;
+}
+
+std::shared_ptr<eventgroupinfo>
+remote_subscription::get_eventgroupinfo() const {
+ return eventgroupinfo_.lock();
+}
+
+void
+remote_subscription::set_eventgroupinfo(
+ const std::shared_ptr<eventgroupinfo> &_info) {
+ eventgroupinfo_ = _info;
+}
+
+ttl_t
+remote_subscription::get_ttl() const {
+ return ttl_;
+}
+
+void
+remote_subscription::set_ttl(const ttl_t _ttl) {
+ ttl_ = _ttl;
+}
+
+uint16_t
+remote_subscription::get_reserved() const {
+ return reserved_;
+}
+
+void
+remote_subscription::set_reserved(const uint16_t _reserved) {
+ reserved_ = _reserved;
+}
+
+uint8_t
+remote_subscription::get_counter() const {
+ return counter_;
+}
+
+void
+remote_subscription::set_counter(uint8_t _counter) {
+ counter_ = _counter;
+}
+
+std::set<client_t>
+remote_subscription::get_clients() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ std::set<client_t> its_clients;
+ for (const auto its_item : clients_)
+ its_clients.insert(its_item.first);
+ return its_clients;
+}
+
+bool
+remote_subscription::has_client() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ return (clients_.size() > 0);
+}
+
+bool
+remote_subscription::has_client(const client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ return (clients_.find(_client) != clients_.end());
+}
+
+void
+remote_subscription::remove_client(const client_t _client) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ clients_.erase(_client);
+}
+
+remote_subscription_state_e
+remote_subscription::get_client_state(const client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ auto found_client = clients_.find(_client);
+ if (found_client != clients_.end()) {
+ return found_client->second.first;
+ }
+ return remote_subscription_state_e::SUBSCRIPTION_UNKNOWN;
+}
+
+void
+remote_subscription::set_client_state(const client_t _client,
+ remote_subscription_state_e _state) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ auto found_item = clients_.find(_client);
+ if (found_item != clients_.end()) {
+ found_item->second.first = _state;
+ if (found_item->second.second == std::chrono::steady_clock::time_point()
+ && (_state == remote_subscription_state_e::SUBSCRIPTION_ACKED
+ || _state == remote_subscription_state_e::SUBSCRIPTION_NACKED)) {
+ found_item->second.second = std::chrono::steady_clock::now();
+ }
+ }
+}
+
+void
+remote_subscription::set_all_client_states(remote_subscription_state_e _state) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (auto &its_item : clients_)
+ its_item.second.first = _state;
+}
+
+std::shared_ptr<endpoint_definition>
+remote_subscription::get_subscriber() const {
+ return subscriber_;
+}
+
+void
+remote_subscription::set_subscriber(
+ const std::shared_ptr<endpoint_definition> &_subscriber) {
+ subscriber_ = _subscriber;
+}
+
+std::shared_ptr<endpoint_definition>
+remote_subscription::get_reliable() const {
+ return reliable_;
+}
+
+void
+remote_subscription::set_reliable(
+ const std::shared_ptr<endpoint_definition> &_reliable) {
+ reliable_ = _reliable;
+}
+
+std::shared_ptr<endpoint_definition>
+remote_subscription::get_unreliable() const {
+ return unreliable_;
+}
+
+void
+remote_subscription::set_unreliable(
+ const std::shared_ptr<endpoint_definition> &_unreliable) {
+ unreliable_ = _unreliable;
+}
+
+bool
+remote_subscription::is_pending() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (auto its_client : clients_) {
+ if (its_client.second.first
+ == remote_subscription_state_e::SUBSCRIPTION_PENDING) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+remote_subscription::is_acknowledged() const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (auto its_client : clients_) {
+ if (its_client.second.first
+ != remote_subscription_state_e::SUBSCRIPTION_ACKED) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::chrono::steady_clock::time_point
+remote_subscription::get_expiration(const client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ auto found_client = clients_.find(_client);
+ if (found_client != clients_.end()) {
+ return found_client->second.second;
+ }
+ return std::chrono::steady_clock::now();
+}
+
+std::set<client_t>
+remote_subscription::update(const std::set<client_t> &_clients,
+ const std::chrono::steady_clock::time_point &_timepoint,
+ const bool _is_subscribe) {
+ std::set<client_t> its_changed;
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ for (const auto &its_client : _clients) {
+ auto found_client = clients_.find(its_client);
+ if (_is_subscribe) {
+ if (found_client != clients_.end()) {
+ found_client->second.second = _timepoint;
+ } else {
+ its_changed.insert(its_client);
+ }
+ } else {
+ if (found_client != clients_.end()) {
+ its_changed.insert(its_client);
+ }
+ }
+ }
+
+ for (const auto &its_client : its_changed) {
+ if (_is_subscribe) {
+ clients_[its_client] = std::make_pair(
+ remote_subscription_state_e::SUBSCRIPTION_PENDING, _timepoint);
+ } else {
+ clients_.erase(its_client);
+ }
+ }
+
+ return its_changed;
+}
+
+std::shared_ptr<remote_subscription>
+remote_subscription::get_parent() const {
+ return parent_.lock();
+}
+
+void
+remote_subscription::set_parent(
+ const std::shared_ptr<remote_subscription> &_parent) {
+ parent_ = _parent;
+}
+
+std::uint32_t
+remote_subscription::get_answers() const {
+ return answers_;
+}
+
+void
+remote_subscription::set_answers(const std::uint32_t _answers) {
+ answers_ = _answers;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_base.cpp b/implementation/routing/src/routing_manager_base.cpp
index 517ccdb..77e5b83 100644
--- a/implementation/routing/src/routing_manager_base.cpp
+++ b/implementation/routing/src/routing_manager_base.cpp
@@ -6,40 +6,47 @@
#include <iomanip>
#include <vsomeip/runtime.hpp>
+#include <vsomeip/internal/logger.hpp>
-#include "../../utility/include/utility.hpp"
-#include "../../utility/include/byteorder.hpp"
#include "../include/routing_manager_base.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../endpoints/include/local_client_endpoint_impl.hpp"
#include "../../endpoints/include/local_server_endpoint_impl.hpp"
+#include "../../security/include/security.hpp"
#ifdef USE_DLT
#include "../../tracing/include/connector_impl.hpp"
#endif
+#include "../../utility/include/byteorder.hpp"
+#include "../../utility/include/utility.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
routing_manager_base::routing_manager_base(routing_manager_host *_host) :
host_(_host),
io_(host_->get_io()),
client_(host_->get_client()),
- configuration_(host_->get_configuration()),
- serializer_(
- std::make_shared<serializer>(
- configuration_->get_buffer_shrink_threshold()))
+ configuration_(host_->get_configuration())
#ifdef USE_DLT
, tc_(trace::connector_impl::get())
#endif
{
+ const std::size_t its_max = configuration_->get_io_thread_count(host_->get_name());
const uint32_t its_buffer_shrink_threshold =
configuration_->get_buffer_shrink_threshold();
- for (int i = 0; i < VSOMEIP_MAX_DESERIALIZER; ++i) {
+
+ for (std::size_t i = 0; i < its_max; ++i) {
+ serializers_.push(
+ std::make_shared<serializer>(its_buffer_shrink_threshold));
deserializers_.push(
- std::make_shared<deserializer>(its_buffer_shrink_threshold));
+ std::make_shared<deserializer>(its_buffer_shrink_threshold));
}
-}
-routing_manager_base::~routing_manager_base() {
+ own_uid_ = ANY_UID;
+ own_gid_ = ANY_GID;
+#ifndef _WIN32
+ own_uid_ = getuid();
+ own_gid_ = getgid();
+#endif
+
}
boost::asio::io_service & routing_manager_base::get_io() {
@@ -50,12 +57,21 @@ client_t routing_manager_base::get_client() const {
return client_;
}
-void routing_manager_base::init() {
+void routing_manager_base::set_client(const client_t &_client) {
+ client_ = _client;
+}
+
+session_t routing_manager_base::get_session() {
+ return host_->get_session();
+}
+
+void routing_manager_base::init(const std::shared_ptr<endpoint_manager_base>& _endpoint_manager) {
+ ep_mgr_ = _endpoint_manager;
}
-bool routing_manager_base::offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor) {
+bool routing_manager_base::offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
(void)_client;
// Remote route (incoming only)
@@ -67,7 +83,6 @@ bool routing_manager_base::offer_service(client_t _client, service_t _service,
&& its_info->get_minor() == _minor) {
its_info->set_ttl(DEFAULT_TTL);
} else {
- host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
VSOMEIP_ERROR << "rm_base::offer_service service property mismatch ("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
@@ -98,11 +113,13 @@ bool routing_manager_base::offer_service(client_t _client, service_t _service,
return true;
}
-void routing_manager_base::stop_offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
+void routing_manager_base::stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
(void)_client;
(void)_major;
(void)_minor;
+
std::map<event_t, std::shared_ptr<event> > events;
{
std::lock_guard<std::mutex> its_lock(events_mutex_);
@@ -122,11 +139,9 @@ void routing_manager_base::stop_offer_service(client_t _client, service_t _servi
}
}
-void routing_manager_base::request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy) {
- (void)_use_exclusive_proxy;
-
+void routing_manager_base::request_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
auto its_info = find_service(_service, _instance);
if (its_info) {
if ((_major == its_info->get_major()
@@ -137,7 +152,6 @@ void routing_manager_base::request_service(client_t _client, service_t _service,
|| _minor == ANY_MINOR)) {
its_info->add_client(_client);
} else {
- host_->on_error(error_code_e::SERVICE_PROPERTY_MISMATCH);
VSOMEIP_ERROR << "rm_base::request_service service property mismatch ("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
@@ -150,8 +164,8 @@ void routing_manager_base::request_service(client_t _client, service_t _service,
}
}
-void routing_manager_base::release_service(client_t _client, service_t _service,
- instance_t _instance) {
+void routing_manager_base::release_service(client_t _client,
+ service_t _service, instance_t _instance) {
auto its_info = find_service(_service, _instance);
if (its_info) {
its_info->remove_client(_client);
@@ -168,38 +182,84 @@ void routing_manager_base::release_service(client_t _client, service_t _service,
}
}
-void routing_manager_base::register_event(client_t _client, service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups, bool _is_field,
- std::chrono::milliseconds _cycle, bool _change_resets_cycle,
- epsilon_change_func_t _epsilon_change_func,
- bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
- std::lock_guard<std::mutex> its_event_reg_lock(event_registration_mutex_);
- std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
+void routing_manager_base::register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups,
+ const event_type_e _type,
+ reliability_type_e _reliability,
+ std::chrono::milliseconds _cycle, bool _change_resets_cycle,
+ bool _update_on_change,
+ epsilon_change_func_t _epsilon_change_func,
+ bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
+ std::lock_guard<std::mutex> its_registration_lock(event_registration_mutex_);
+
+ auto determine_event_reliability = [this, &_service, &_instance,
+ &_notifier, &_reliability]() {
+ reliability_type_e its_reliability =
+ configuration_->get_event_reliability(_service, _instance, _notifier);
+ if (its_reliability != reliability_type_e::RT_UNKNOWN) {
+ // event was explicitly configured -> overwrite value passed via API
+ return its_reliability;
+ } else if (_reliability != reliability_type_e::RT_UNKNOWN) {
+ // use value provided via API
+ return _reliability;
+ } else { // automatic mode, user service' reliability
+ return configuration_->get_service_reliability(_service, _instance);
+ }
+ };
+
+ std::shared_ptr<event> its_event = find_event(_service, _instance, _notifier);
bool transfer_subscriptions_from_any_event(false);
if (its_event) {
- if(!its_event->is_cache_placeholder()) {
- if (its_event->is_field() == _is_field) {
+ if (!its_event->is_cache_placeholder()) {
+ if (_type == its_event->get_type()
+ || its_event->get_type() == event_type_e::ET_UNKNOWN
+#ifdef VSOMEIP_ENABLE_COMPAT
+ || (its_event->get_type() == event_type_e::ET_EVENT
+ && _type == event_type_e::ET_SELECTIVE_EVENT)
+ || (its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT
+ && _type == event_type_e::ET_EVENT && _is_provided)
+#endif
+ ) {
+#ifdef VSOMEIP_ENABLE_COMPAT
+ if (its_event->get_type() == event_type_e::ET_EVENT
+ && _type == event_type_e::ET_SELECTIVE_EVENT) {
+ its_event->set_type(_type);
+ VSOMEIP_INFO << "Event type changed to selective ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client << ") ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _notifier << "]";
+ }
+#endif
if (_is_provided) {
its_event->set_provided(true);
+ its_event->set_reliability(determine_event_reliability());
}
if (_is_shadow && _is_provided) {
its_event->set_shadow(_is_shadow);
}
if (_client == host_->get_client() && _is_provided) {
its_event->set_shadow(false);
+ its_event->set_update_on_change(_update_on_change);
}
for (auto eg : _eventgroups) {
its_event->add_eventgroup(eg);
}
transfer_subscriptions_from_any_event = true;
} else {
- VSOMEIP_ERROR << "Event registration update failed. "
- "Specified arguments do not match existing registration.";
+#ifdef VSOMEIP_ENABLE_COMPAT
+ if (!(its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT
+ && _type == event_type_e::ET_EVENT))
+#endif
+ VSOMEIP_ERROR << "Event registration update failed. "
+ "Specified arguments do not match existing registration.";
}
} else {
// the found event was a placeholder for caching.
// update it with the real values
- if(!_is_field) {
+ if (_type != event_type_e::ET_FIELD) {
// don't cache payload for non-fields
its_event->unset_payload(true);
}
@@ -208,8 +268,10 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
}
if (_client == host_->get_client() && _is_provided) {
its_event->set_shadow(false);
+ its_event->set_update_on_change(_update_on_change);
}
- its_event->set_field(_is_field);
+ its_event->set_type(_type);
+ its_event->set_reliability(determine_event_reliability());
its_event->set_provided(_is_provided);
its_event->set_cache_placeholder(false);
std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance);
@@ -218,7 +280,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
}
if (_eventgroups.size() == 0) { // No eventgroup specified
std::set<eventgroup_t> its_eventgroups;
- its_eventgroups.insert(_event);
+ its_eventgroups.insert(_notifier);
its_event->set_eventgroups(its_eventgroups);
} else {
for (auto eg : _eventgroups) {
@@ -232,11 +294,11 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
}
} else {
its_event = std::make_shared<event>(this, _is_shadow);
- its_event->set_reliable(configuration_->is_event_reliable(_service, _instance, _event));
its_event->set_service(_service);
its_event->set_instance(_instance);
- its_event->set_event(_event);
- its_event->set_field(_is_field);
+ its_event->set_event(_notifier);
+ its_event->set_type(_type);
+ its_event->set_reliability(determine_event_reliability());
its_event->set_provided(_is_provided);
its_event->set_cache_placeholder(_is_cache_placeholder);
std::shared_ptr<serviceinfo> its_service = find_service(_service, _instance);
@@ -246,15 +308,15 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
if (_eventgroups.size() == 0) { // No eventgroup specified
std::set<eventgroup_t> its_eventgroups;
- its_eventgroups.insert(_event);
+ its_eventgroups.insert(_notifier);
its_event->set_eventgroups(its_eventgroups);
} else {
its_event->set_eventgroups(_eventgroups);
}
if (_is_shadow && !_epsilon_change_func) {
- std::shared_ptr<vsomeip::cfg::debounce> its_debounce
- = configuration_->get_debounce(_service, _instance, _event);
+ std::shared_ptr<cfg::debounce> its_debounce
+ = configuration_->get_debounce(_service, _instance, _notifier);
if (its_debounce) {
VSOMEIP_WARNING << "Using debounce configuration for "
<< " SOME/IP event "
@@ -263,7 +325,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
<< std::hex << std::setw(4) << std::setfill('0')
<< _instance << "."
<< std::hex << std::setw(4) << std::setfill('0')
- << _event << ".";
+ << _notifier << ".";
std::stringstream its_debounce_parameters;
its_debounce_parameters << "(on_change="
<< (its_debounce->on_change_ ? "true" : "false")
@@ -349,6 +411,7 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
its_event->set_epsilon_change_function(_epsilon_change_func);
its_event->set_change_resets_cycle(_change_resets_cycle);
its_event->set_update_cycle(_cycle);
+ its_event->set_update_on_change(_update_on_change);
if (_is_provided) {
transfer_subscriptions_from_any_event = true;
@@ -381,18 +444,21 @@ void routing_manager_base::register_event(client_t _client, service_t _service,
}
for (auto eg : _eventgroups) {
- std::shared_ptr<eventgroupinfo> its_eventgroup_info
+ std::shared_ptr<eventgroupinfo> its_eventgroupinfo
= find_eventgroup(_service, _instance, eg);
- if (!its_eventgroup_info) {
- its_eventgroup_info = std::make_shared<eventgroupinfo>();
+ if (!its_eventgroupinfo) {
+ its_eventgroupinfo = std::make_shared<eventgroupinfo>();
+ its_eventgroupinfo->set_service(_service);
+ its_eventgroupinfo->set_instance(_instance);
+ its_eventgroupinfo->set_eventgroup(eg);
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
- eventgroups_[_service][_instance][eg] = its_eventgroup_info;
+ eventgroups_[_service][_instance][eg] = its_eventgroupinfo;
}
- its_eventgroup_info->add_event(its_event);
+ its_eventgroupinfo->add_event(its_event);
}
std::lock_guard<std::mutex> its_lock(events_mutex_);
- events_[_service][_instance][_event] = its_event;
+ events_[_service][_instance][_notifier] = its_event;
}
void routing_manager_base::unregister_event(client_t _client, service_t _service, instance_t _instance,
@@ -470,7 +536,9 @@ std::vector<event_t> routing_manager_base::find_events(
bool routing_manager_base::is_response_allowed(client_t _sender, service_t _service,
instance_t _instance, method_t _method) {
- if (!configuration_->is_security_enabled()) {
+
+ const auto its_security(security::get());
+ if (!its_security->is_enabled()) {
return true;
}
@@ -495,7 +563,7 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv
// service is now offered by another client
// or service is not offered at all
std::string security_mode_text = "!";
- if (!configuration_->is_audit_mode_enabled()) {
+ if (!its_security->is_audit()) {
security_mode_text = ", but will be allowed due to audit mode is active!";
}
@@ -506,16 +574,23 @@ bool routing_manager_base::is_response_allowed(client_t _sender, service_t _serv
<< _service << "/" << _instance << "/" << _method
<< security_mode_text;
- return !configuration_->is_audit_mode_enabled();
+ return !its_security->is_audit();
}
-bool routing_manager_base::is_subscribe_to_any_event_allowed(client_t _client,
+bool routing_manager_base::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
+
+ const auto its_security(security::get());
+ const uid_t its_uid(std::get<0>(_credentials));
+ const gid_t its_gid(std::get<1>(_credentials));
+
bool is_allowed(true);
+
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- for (auto e : its_eventgroup->get_events()) {
- if (!configuration_->is_client_allowed(_client, _service, _instance, e->get_event())) {
+ for (const auto& e : its_eventgroup->get_events()) {
+ if (!its_security->is_client_allowed(its_uid, its_gid,
+ _client, _service, _instance, e->get_event())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
<< _client << " : routing_manager_base::is_subscribe_to_any_event_allowed: "
<< "subscribes to service/instance/event "
@@ -526,16 +601,17 @@ bool routing_manager_base::is_subscribe_to_any_event_allowed(client_t _client,
}
}
}
+
return is_allowed;
}
-void routing_manager_base::subscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major, event_t _event,
- subscription_type_e _subscription_type) {
+void routing_manager_base::subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, event_t _event) {
(void) _major;
- (void) _subscription_type;
+ (void)_uid;
+ (void)_gid;
std::set<event_t> its_already_subscribed_events;
bool inserted = insert_subscription(_service, _instance, _eventgroup,
_event, _client, &its_already_subscribed_events);
@@ -545,8 +621,10 @@ void routing_manager_base::subscribe(client_t _client, service_t _service,
}
}
-void routing_manager_base::unsubscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+void routing_manager_base::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,event_t _event) {
+ (void)_uid;
+ (void)_gid;
if (_event != ANY_EVENT) {
auto its_event = find_event(_service, _instance, _event);
if (its_event) {
@@ -555,8 +633,9 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service,
} else {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- for (auto e : its_eventgroup->get_events()) {
- e->remove_subscriber(_eventgroup, _client);
+ for (const auto &e : its_eventgroup->get_events()) {
+ if (e)
+ e->remove_subscriber(_eventgroup, _client);
}
}
}
@@ -564,10 +643,10 @@ void routing_manager_base::unsubscribe(client_t _client, service_t _service,
void routing_manager_base::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- bool _force, bool _flush) {
+ bool _force) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- its_event->set_payload(_payload, _force, _flush);
+ its_event->set_payload(_payload, _force);
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
<< std::hex << _service << "." << _instance << "." << _event
@@ -577,14 +656,20 @@ void routing_manager_base::notify(service_t _service, instance_t _instance,
void routing_manager_base::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush, bool _remote_subscriber) {
+ client_t _client, bool _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , bool _remote_subscriber
+#endif
+ ) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
// Event is valid for service/instance
bool found_eventgroup(false);
bool already_subscribed(false);
+#ifdef VSOMEIP_ENABLE_COMPAT
eventgroup_t valid_group = 0;
subscription_state_e its_subscription_state(subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED);
+#endif
// Iterate over all groups of the event to ensure at least
// one valid eventgroup for service/instance exists.
for (auto its_group : its_event->get_eventgroups()) {
@@ -592,14 +677,21 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
if (its_eventgroup) {
// Eventgroup is valid for service/instance
found_eventgroup = true;
+#ifdef VSOMEIP_ENABLE_COMPAT
valid_group = its_group;
its_subscription_state = get_incoming_subscription_state(_client, _service,
_instance, valid_group, _event);
- if (find_local(_client)) {
+#endif
+ if (ep_mgr_->find_local(_client)) {
already_subscribed = its_event->has_subscriber(its_group, _client);
+#ifdef VSOMEIP_ENABLE_COMPAT
} else if (subscription_state_e::IS_SUBSCRIBING != its_subscription_state
|| _remote_subscriber) {
// Remotes always needs to be marked as subscribed here if they are not currently subscribing
+#else
+ } else {
+ // Remotes always needs to be marked as subscribed here
+#endif
already_subscribed = true;
}
break;
@@ -607,8 +699,10 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
if (found_eventgroup) {
if (already_subscribed) {
- its_event->set_payload(_payload, _client, _force, _flush);
- } else {
+ its_event->set_payload(_payload, _client, _force);
+ }
+#ifdef VSOMEIP_ENABLE_COMPAT
+ else {
// cache notification if subscription is in progress
if (subscription_state_e::IS_SUBSCRIBING == its_subscription_state) {
VSOMEIP_INFO << "routing_manager_base::notify_one("
@@ -634,6 +728,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
}
}
+#endif
}
} else {
VSOMEIP_WARNING << "Attempt to update the undefined event/field ["
@@ -642,6 +737,7 @@ void routing_manager_base::notify_one(service_t _service, instance_t _instance,
}
}
+#ifdef VSOMEIP_ENABLE_COMPAT
void routing_manager_base::send_pending_notify_ones(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client, bool _remote_subscriber) {
std::lock_guard<std::recursive_mutex> its_lock(pending_notify_ones_mutex_);
@@ -659,12 +755,13 @@ void routing_manager_base::send_pending_notify_ones(service_t _service, instance
<< std::hex << std::setw(4) << std::setfill('0') << its_group->second->get_method() << "]";
notify_one(_service, _instance, its_group->second->get_method(),
- its_group->second->get_payload(), _client, false, true, _remote_subscriber);
+ its_group->second->get_payload(), _client, false, _remote_subscriber);
its_instance->second.erase(_eventgroup);
}
}
}
}
+#endif
void routing_manager_base::unset_all_eventpayloads(service_t _service,
instance_t _instance) {
@@ -719,16 +816,16 @@ void routing_manager_base::notify_one_current_value(
if (_event != ANY_EVENT) {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event && its_event->is_field())
- its_event->notify_one(_client, true);
+ its_event->notify_one(_client);
} else {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
std::set<std::shared_ptr<event> > its_events = its_eventgroup->get_events();
- for (auto e : its_events) {
+ for (const auto &e : its_events) {
if (e->is_field()
&& _events_to_exclude.find(e->get_event())
== _events_to_exclude.end()) {
- e->notify_one(_client, true); // TODO: use _flush to send all events together!
+ e->notify_one(_client);
}
}
}
@@ -736,18 +833,19 @@ void routing_manager_base::notify_one_current_value(
}
bool routing_manager_base::send(client_t _client,
- std::shared_ptr<message> _message,
- bool _flush) {
+ std::shared_ptr<message> _message) {
bool is_sent(false);
if (utility::is_request(_message->get_message_type())) {
_message->set_client(_client);
}
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- if (serializer_->serialize(_message.get())) {
- is_sent = send(_client, serializer_->get_data(),
- serializer_->get_size(), _message->get_instance(),
- _flush, _message->is_reliable(), get_client(), true, false);
- serializer_->reset();
+
+ std::shared_ptr<serializer> its_serializer(get_serializer());
+ if (its_serializer->serialize(_message.get())) {
+ is_sent = send(_client, its_serializer->get_data(),
+ its_serializer->get_size(), _message->get_instance(),
+ _message->is_reliable(), get_client(), std::make_pair(ANY_UID, ANY_GID), 0, false);
+ its_serializer->reset();
+ put_serializer(its_serializer);
} else {
VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
}
@@ -759,7 +857,8 @@ std::shared_ptr<serviceinfo> routing_manager_base::create_service_info(
service_t _service, instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl, bool _is_local_service) {
std::shared_ptr<serviceinfo> its_info =
- std::make_shared<serviceinfo>(_major, _minor, _ttl, _is_local_service);
+ std::make_shared<serviceinfo>(_service, _instance,
+ _major, _minor, _ttl, _is_local_service);
{
std::lock_guard<std::mutex> its_lock(services_mutex_);
services_[_service][_instance] = its_info;
@@ -873,7 +972,8 @@ std::set<client_t> routing_manager_base::find_local_clients(service_t _service,
return its_clients;
}
-client_t routing_manager_base::find_local_client(service_t _service, instance_t _instance) {
+client_t routing_manager_base::find_local_client(service_t _service,
+ instance_t _instance) const {
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
client_t its_client(VSOMEIP_ROUTING_CLIENT);
auto its_service = local_services_.find(_service);
@@ -886,70 +986,6 @@ client_t routing_manager_base::find_local_client(service_t _service, instance_t
return its_client;
}
-std::shared_ptr<endpoint> routing_manager_base::create_local_unlocked(client_t _client) {
- std::stringstream its_path;
- its_path << utility::get_base_path(configuration_) << std::hex << _client;
-
-#ifdef _WIN32
- boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1");
- int port = VSOMEIP_INTERNAL_BASE_PORT + _client;
- VSOMEIP_INFO << "Connecting to ["
- << std::hex << _client << "] at " << port;
-#else
- VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is connecting to ["
- << std::hex << _client << "] at " << its_path.str();
-#endif
- std::shared_ptr<local_client_endpoint_impl> its_endpoint = std::make_shared<
- local_client_endpoint_impl>(shared_from_this(),
-#ifdef _WIN32
- boost::asio::ip::tcp::endpoint(address, port)
-#else
- boost::asio::local::stream_protocol::endpoint(its_path.str())
-#endif
- , io_, configuration_->get_max_message_size_local(),
- configuration_->get_endpoint_queue_limit_local());
-
- // Messages sent to the VSOMEIP_ROUTING_CLIENT are meant to be routed to
- // external devices. Therefore, its local endpoint must not be found by
- // a call to find_local. Thus it must not be inserted to the list of local
- // clients.
- if (_client != VSOMEIP_ROUTING_CLIENT) {
- local_endpoints_[_client] = its_endpoint;
- }
- register_client_error_handler(_client, its_endpoint);
-
- return its_endpoint;
-}
-
-std::shared_ptr<endpoint> routing_manager_base::create_local(client_t _client) {
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- return create_local_unlocked(_client);
-}
-
-std::shared_ptr<endpoint> routing_manager_base::find_local_unlocked(client_t _client) {
- std::shared_ptr<endpoint> its_endpoint;
- auto found_endpoint = local_endpoints_.find(_client);
- if (found_endpoint != local_endpoints_.end()) {
- its_endpoint = found_endpoint->second;
- }
- return (its_endpoint);
-}
-
-std::shared_ptr<endpoint> routing_manager_base::find_local(client_t _client) {
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- return find_local_unlocked(_client);
-}
-
-std::shared_ptr<endpoint> routing_manager_base::find_or_create_local(client_t _client) {
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- std::shared_ptr<endpoint> its_endpoint(find_local_unlocked(_client));
- if (!its_endpoint) {
- its_endpoint = create_local_unlocked(_client);
- its_endpoint->start();
- }
- return (its_endpoint);
-}
-
void routing_manager_base::remove_local(client_t _client, bool _remove_uid) {
remove_local(_client, get_subscriptions(_client), _remove_uid);
}
@@ -957,24 +993,20 @@ void routing_manager_base::remove_local(client_t _client, bool _remove_uid) {
void routing_manager_base::remove_local(client_t _client,
const std::set<std::tuple<service_t, instance_t, eventgroup_t>>& _subscribed_eventgroups,
bool _remove_uid) {
+
+ std::pair<uid_t, gid_t> its_uid_gid(ANY_UID, ANY_GID);
+ security::get()->get_client_to_uid_gid_mapping(_client, its_uid_gid);
+
if (_remove_uid) {
- configuration_->remove_client_to_uid_gid_mapping(_client);
+ security::get()->remove_client_to_uid_gid_mapping(_client);
}
for (auto its_subscription : _subscribed_eventgroups) {
host_->on_subscription(std::get<0>(its_subscription), std::get<1>(its_subscription),
- std::get<2>(its_subscription), _client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
- routing_manager_base::unsubscribe(_client, std::get<0>(its_subscription),
+ std::get<2>(its_subscription), _client, its_uid_gid.first, its_uid_gid.second, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ routing_manager_base::unsubscribe(_client, its_uid_gid.first, its_uid_gid.second, std::get<0>(its_subscription),
std::get<1>(its_subscription), std::get<2>(its_subscription), ANY_EVENT);
}
- std::shared_ptr<endpoint> its_endpoint(find_local(_client));
- if (its_endpoint) {
- its_endpoint->register_error_handler(nullptr);
- its_endpoint->stop();
- VSOMEIP_INFO << "Client [" << std::hex << get_client() << "] is closing connection to ["
- << std::hex << _client << "]";
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- local_endpoints_.erase(_client);
- }
+ ep_mgr_->remove_local(_client);
{
std::lock_guard<std::mutex> its_lock(local_services_mutex_);
// Finally remove all services that are implemented by the client.
@@ -1016,24 +1048,10 @@ void routing_manager_base::remove_local(client_t _client,
}
}
-std::shared_ptr<endpoint> routing_manager_base::find_local(service_t _service,
- instance_t _instance) {
- return find_local(find_local_client(_service, _instance));
-}
-
-std::unordered_set<client_t> routing_manager_base::get_connected_clients() {
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- std::unordered_set<client_t> clients;
- for (auto its_client : local_endpoints_) {
- clients.insert(its_client.first);
- }
- return clients;
-}
-
std::shared_ptr<event> routing_manager_base::find_event(service_t _service,
instance_t _instance, event_t _event) const {
- std::shared_ptr<event> its_event;
std::lock_guard<std::mutex> its_lock(events_mutex_);
+ std::shared_ptr<event> its_event;
auto find_service = events_.find(_service);
if (find_service != events_.end()) {
auto find_instance = find_service->second.find(_instance);
@@ -1082,6 +1100,8 @@ std::shared_ptr<eventgroupinfo> routing_manager_base::find_eventgroup(
"multicast address is configured!";
}
}
+
+ // LB: THIS IS STRANGE. A "FIND" - METHOD SHOULD NOT ADD INFORMATION...
its_info->set_major(its_service_info->get_major());
its_info->set_ttl(its_service_info->get_ttl());
its_info->set_threshold(configuration_->get_threshold(
@@ -1107,7 +1127,7 @@ void routing_manager_base::remove_eventgroup_info(service_t _service,
bool routing_manager_base::send_local_notification(client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable, bool _is_valid_crc) {
+ bool _reliable, uint8_t _status_check) {
#ifdef USE_DLT
bool has_local(false);
#endif
@@ -1118,7 +1138,6 @@ bool routing_manager_base::send_local_notification(client_t _client,
_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method);
if (its_event && !its_event->is_shadow()) {
- std::vector< byte_t > its_data;
for (auto its_client : its_event->get_subscribers()) {
// local
@@ -1131,10 +1150,10 @@ bool routing_manager_base::send_local_notification(client_t _client,
has_local = true;
}
#endif
- std::shared_ptr<endpoint> its_local_target = find_local(its_client);
+ std::shared_ptr<endpoint> its_local_target = ep_mgr_->find_local(its_client);
if (its_local_target) {
send_local(its_local_target, _client, _data, _size,
- _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
+ _instance, _reliable, VSOMEIP_SEND, _status_check);
}
}
}
@@ -1156,7 +1175,7 @@ bool routing_manager_base::send_local_notification(client_t _client,
bool routing_manager_base::send_local(
std::shared_ptr<endpoint>& _target, client_t _client,
const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush, bool _reliable, uint8_t _command, bool _is_valid_crc) const {
+ bool _reliable, uint8_t _command, uint8_t _status_check) const {
const std::size_t its_complete_size = VSOMEIP_SEND_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE + _size;
const client_t sender = get_client();
@@ -1169,12 +1188,10 @@ bool routing_manager_base::send_local(
&its_complete_size, sizeof(_size));
std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
&_instance, sizeof(instance_t));
- std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_FLUSH_POS],
- &_flush, sizeof(bool));
std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
&_reliable, sizeof(bool));
- std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
- &_is_valid_crc, sizeof(bool));
+ std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
+ &_status_check, sizeof(uint8_t));
// Add target client, only relevant for selective notifications
std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
&_client, sizeof(client_t));
@@ -1244,7 +1261,33 @@ bool routing_manager_base::insert_subscription(
return is_inserted;
}
+std::shared_ptr<serializer> routing_manager_base::get_serializer() {
+
+ std::unique_lock<std::mutex> its_lock(serializer_mutex_);
+ while (serializers_.empty()) {
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_serializer ~> all in use!";
+ serializer_condition_.wait(its_lock);
+ VSOMEIP_INFO << std::hex << "client " << get_client() <<
+ "routing_manager_base::get_serializer ~> wait finished!";
+ }
+
+ auto its_serializer = serializers_.front();
+ serializers_.pop();
+
+ return (its_serializer);
+}
+
+void routing_manager_base::put_serializer(
+ const std::shared_ptr<serializer> &_serializer) {
+
+ std::lock_guard<std::mutex> its_lock(serializer_mutex_);
+ serializers_.push(_serializer);
+ serializer_condition_.notify_one();
+}
+
std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
+
std::unique_lock<std::mutex> its_lock(deserializer_mutex_);
while (deserializers_.empty()) {
VSOMEIP_INFO << std::hex << "client " << get_client() <<
@@ -1253,30 +1296,28 @@ std::shared_ptr<deserializer> routing_manager_base::get_deserializer() {
VSOMEIP_INFO << std::hex << "client " << get_client() <<
"routing_manager_base::get_deserializer ~> wait finished!";
}
- auto deserializer = deserializers_.front();
+
+ auto its_deserializer = deserializers_.front();
deserializers_.pop();
- return deserializer;
+
+ return (its_deserializer);
}
-void routing_manager_base::put_deserializer(std::shared_ptr<deserializer> _deserializer) {
+void routing_manager_base::put_deserializer(
+ const std::shared_ptr<deserializer> &_deserializer) {
+
std::lock_guard<std::mutex> its_lock(deserializer_mutex_);
deserializers_.push(_deserializer);
deserializer_condition_.notify_one();
}
-#ifndef _WIN32
-bool routing_manager_base::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
- return configuration_->check_credentials(_client, _uid, _gid);
-}
-#endif
-
void routing_manager_base::send_pending_subscriptions(service_t _service,
instance_t _instance, major_version_t _major) {
for (auto &ps : pending_subscriptions_) {
if (ps.service_ == _service &&
ps.instance_ == _instance && ps.major_ == _major) {
send_subscribe(client_, ps.service_, ps.instance_,
- ps.eventgroup_, ps.major_, ps.event_, ps.subscription_type_);
+ ps.eventgroup_, ps.major_, ps.event_);
}
}
}
@@ -1324,11 +1365,11 @@ std::set<std::tuple<service_t, instance_t, eventgroup_t>>
routing_manager_base::get_subscriptions(const client_t _client) {
std::set<std::tuple<service_t, instance_t, eventgroup_t>> result;
std::lock_guard<std::mutex> its_lock(events_mutex_);
- for (auto its_service : events_) {
- for (auto its_instance : its_service.second) {
- for (auto its_event : its_instance.second) {
+ for (const auto& its_service : events_) {
+ for (const auto& its_instance : its_service.second) {
+ for (const auto& its_event : its_instance.second) {
auto its_eventgroups = its_event.second->get_eventgroups(_client);
- for (auto e : its_eventgroups) {
+ for (const auto& e : its_eventgroups) {
result.insert(std::make_tuple(
its_service.first,
its_instance.first,
@@ -1340,27 +1381,7 @@ routing_manager_base::get_subscriptions(const client_t _client) {
return result;
}
-void routing_manager_base::send_identify_request(service_t _service,
- instance_t _instance, major_version_t _major, bool _reliable) {
- auto message = runtime::get()->create_message(_reliable);
- message->set_service(_service);
- message->set_instance(_instance);
- message->set_client(get_client());
- message->set_method(ANY_METHOD - 1);
- message->set_interface_version(_major);
- message->set_message_type(message_type_e::MT_REQUEST);
-
- // Initiate a request/response to the remote service
- // Use host for sending to ensure correct session id is set
- host_->send(message, true);
-}
-
-std::map<client_t, std::shared_ptr<endpoint>>
-routing_manager_base::get_local_endpoints() {
- std::lock_guard<std::mutex> its_lock(local_endpoint_mutex_);
- return local_endpoints_;
-}
-
+#ifdef VSOMEIP_ENABLE_COMPAT
void routing_manager_base::set_incoming_subscription_state(client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, subscription_state_e _state) {
std::lock_guard<std::recursive_mutex> its_lock(incoming_subscription_state_mutex_);
@@ -1427,5 +1448,6 @@ void routing_manager_base::erase_incoming_subscription_state(client_t _client, s
}
}
}
+#endif
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_impl.cpp b/implementation/routing/src/routing_manager_impl.cpp
index f8dbd14..48e2cb5 100644
--- a/implementation/routing/src/routing_manager_impl.cpp
+++ b/implementation/routing/src/routing_manager_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -15,25 +15,23 @@
#include <time.h>
#endif
-#ifndef WITHOUT_SYSTEMD
-#include <systemd/sd-daemon.h>
-#endif
-
#include <boost/asio/steady_timer.hpp>
#include <vsomeip/constants.hpp>
-#include <vsomeip/message.hpp>
#include <vsomeip/payload.hpp>
#include <vsomeip/runtime.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/event.hpp"
#include "../include/eventgroupinfo.hpp"
+#include "../include/remote_subscription.hpp"
#include "../include/routing_manager_host.hpp"
#include "../include/routing_manager_impl.hpp"
#include "../include/routing_manager_stub.hpp"
#include "../include/serviceinfo.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
+#include "../../security/include/security.hpp"
+
#include "../../endpoints/include/endpoint_definition.hpp"
#include "../../endpoints/include/local_client_endpoint_impl.hpp"
#include "../../endpoints/include/tcp_client_endpoint_impl.hpp"
@@ -41,32 +39,38 @@
#include "../../endpoints/include/udp_client_endpoint_impl.hpp"
#include "../../endpoints/include/udp_server_endpoint_impl.hpp"
#include "../../endpoints/include/virtual_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../message/include/deserializer.hpp"
+#include "../../message/include/message_impl.hpp"
#include "../../message/include/serializer.hpp"
#include "../../service_discovery/include/constants.hpp"
#include "../../service_discovery/include/defines.hpp"
#include "../../service_discovery/include/runtime.hpp"
-#include "../../service_discovery/include/service_discovery_impl.hpp"
+#include "../../service_discovery/include/service_discovery.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
-#include "../../plugin/include/plugin_manager.hpp"
+#include "../../plugin/include/plugin_manager_impl.hpp"
#ifdef USE_DLT
#include "../../tracing/include/connector_impl.hpp"
#endif
+#ifndef ANDROID
#include "../../e2e_protection/include/buffer/buffer.hpp"
#include "../../e2e_protection/include/e2exf/config.hpp"
-#include "../../e2e_protection/include/e2e/profile/profile01/profile_01.hpp"
-#include "../../e2e_protection/include/e2e/profile/profile01/protector.hpp"
-#include "../../e2e_protection/include/e2e/profile/profile01/checker.hpp"
+#include "../../e2e_protection/include/e2e/profile/e2e_provider.hpp"
+#endif
-#include "../../e2e_protection/include/e2e/profile/profile_custom/profile_custom.hpp"
-#include "../../e2e_protection/include/e2e/profile/profile_custom/protector.hpp"
-#include "../../e2e_protection/include/e2e/profile/profile_custom/checker.hpp"
+#ifdef USE_DLT
+#include "../../tracing/include/connector_impl.hpp"
+#endif
-namespace vsomeip {
+namespace vsomeip_v3 {
+
+#ifdef ANDROID
+namespace sd {
+runtime::~runtime() {}
+}
+#endif
routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
routing_manager_base(_host),
@@ -74,11 +78,9 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
if_state_running_(false),
sd_route_set_(false),
routing_running_(false),
-#ifndef WITHOUT_SYSTEMD
- watchdog_timer_(_host->get_io()),
-#endif
status_log_timer_(_host->get_io()),
memory_log_timer_(_host->get_io()),
+ ep_mgr_impl_(std::make_shared<endpoint_manager_impl>(this, io_, configuration_)),
pending_remote_offer_id_(0),
last_resume_(std::chrono::steady_clock::now().min()),
pending_security_update_id_(0)
@@ -86,6 +88,8 @@ routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
}
routing_manager_impl::~routing_manager_impl() {
+ utility::remove_lockfile(configuration_);
+ utility::reset_client_ids();
}
boost::asio::io_service & routing_manager_impl::get_io() {
@@ -100,22 +104,23 @@ std::set<client_t> routing_manager_impl::find_local_clients(service_t _service,
return routing_manager_base::find_local_clients(_service, _instance);
}
-bool routing_manager_impl::is_subscribe_to_any_event_allowed(client_t _client,
+client_t routing_manager_impl::find_local_client(service_t _service, instance_t _instance) {
+ return routing_manager_base::find_local_client(_service, _instance);
+}
+
+bool routing_manager_impl::is_subscribe_to_any_event_allowed(credentials_t _credentials, client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup) {
- return routing_manager_base::is_subscribe_to_any_event_allowed(_client,
+ return routing_manager_base::is_subscribe_to_any_event_allowed(_credentials, _client,
_service, _instance, _eventgroup);
}
void routing_manager_impl::init() {
- routing_manager_base::init();
+ routing_manager_base::init(ep_mgr_impl_);
// TODO: Only instantiate the stub if needed
stub_ = std::make_shared<routing_manager_stub>(this, configuration_);
stub_->init();
- // We need to be able to send messages to ourself (for delivering events)
- (void)create_local(VSOMEIP_ROUTING_CLIENT);
-
if (configuration_->is_sd_enabled()) {
VSOMEIP_INFO<< "Service Discovery enabled. Trying to load module.";
auto its_plugin = plugin_manager::get()->get_plugin(
@@ -130,34 +135,29 @@ void routing_manager_impl::init() {
}
}
+#ifndef ANDROID
if( configuration_->is_e2e_enabled()) {
VSOMEIP_INFO << "E2E protection enabled.";
+
+ const char *its_e2e_module = getenv(VSOMEIP_ENV_E2E_PROTECTION_MODULE);
+ std::string plugin_name = its_e2e_module != nullptr ? its_e2e_module : VSOMEIP_E2E_LIBRARY;
+
+ auto its_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN, plugin_name);
+ if (its_plugin) {
+ VSOMEIP_INFO << "E2E module loaded.";
+ e2e_provider_ = std::dynamic_pointer_cast<e2e::e2e_provider>(its_plugin);
+ }
+ }
+
+ if(e2e_provider_) {
std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration();
for (auto &identifier : its_e2e_configuration) {
- auto its_cfg = identifier.second;
- if(its_cfg->profile == "CRC8") {
- e2exf::data_identifier_t its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
- e2e::profile01::profile_config its_profile_config = e2e::profile01::profile_config(its_cfg->crc_offset, its_cfg->data_id,
- (e2e::profile01::p01_data_id_mode) its_cfg->data_id_mode, its_cfg->data_length, its_cfg->counter_offset, its_cfg->data_id_nibble_offset);
- if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) {
- custom_protectors[its_data_identifier] = std::make_shared<e2e::profile01::protector>(its_profile_config);
- }
- if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) {
- custom_checkers[its_data_identifier] = std::make_shared<e2e::profile01::profile_01_checker>(its_profile_config);
- }
- } else if(its_cfg->profile == "CRC32") {
- e2exf::data_identifier_t its_data_identifier = {its_cfg->service_id, its_cfg->event_id};
- e2e::profile_custom::profile_config its_profile_config = e2e::profile_custom::profile_config(its_cfg->crc_offset);
-
- if ((its_cfg->variant == "protector") || (its_cfg->variant == "both")) {
- custom_protectors[its_data_identifier] = std::make_shared<e2e::profile_custom::protector>(its_profile_config);
- }
- if ((its_cfg->variant == "checker") || (its_cfg->variant == "both")) {
- custom_checkers[its_data_identifier] = std::make_shared<e2e::profile_custom::profile_custom_checker>(its_profile_config);
- }
+ if(!e2e_provider_->add_configuration(identifier.second)) {
+ VSOMEIP_INFO << "Unknown E2E profile: " << identifier.second->profile << ", skipping ...";
}
}
}
+#endif
}
void routing_manager_impl::start() {
@@ -186,15 +186,6 @@ void routing_manager_impl::start() {
version_log_timer_.async_wait(std::bind(&routing_manager_impl::log_version_timer_cbk,
this, std::placeholders::_1));
}
-
-#ifndef WITHOUT_SYSTEMD
- {
- std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
- watchdog_timer_.expires_from_now(std::chrono::seconds(0));
- watchdog_timer_.async_wait(std::bind(&routing_manager_impl::watchdog_cbk,
- this, std::placeholders::_1));
- }
-#endif
#ifndef _WIN32
if (configuration_->log_memory()) {
std::lock_guard<std::mutex> its_lock(memory_log_timer_mutex_);
@@ -216,6 +207,26 @@ void routing_manager_impl::start() {
}
void routing_manager_impl::stop() {
+ // Ensure to StopOffer all services that are offered by the application hosting the rm
+ local_services_map_t its_services;
+ {
+ std::lock_guard<std::mutex> its_lock(local_services_mutex_);
+ for (const auto& s : local_services_) {
+ for (const auto& i : s.second) {
+ if (std::get<2>(i.second) == client_) {
+ its_services[s.first][i.first] = i.second;
+ }
+ }
+ }
+
+ }
+ for (const auto& s : its_services) {
+ for (const auto& i : s.second) {
+ on_stop_offer_service(std::get<2>(i.second), s.first, i.first,
+ std::get<0>(i.second), std::get<1>(i.second));
+ }
+ }
+
{
std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_);
version_log_timer_.cancel();
@@ -236,37 +247,119 @@ void routing_manager_impl::stop() {
boost::system::error_code ec;
status_log_timer_.cancel(ec);
}
-#ifndef WITHOUT_SYSTEMD
- {
- std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
- watchdog_timer_.cancel();
- }
- sd_notify(0, "STOPPING=1");
- VSOMEIP_INFO << "Sent STOPPING to systemd watchdog";
-#endif
-
host_->on_state(state_type_e::ST_DEREGISTERED);
if (discovery_)
discovery_->stop();
stub_->stop();
- for (auto client: get_connected_clients()) {
+ for (auto client: ep_mgr_->get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
remove_local(client, true);
}
}
}
-bool routing_manager_impl::offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
+bool routing_manager_impl::insert_offer_command(service_t _service, instance_t _instance, uint8_t _command,
+ client_t _client, major_version_t _major, minor_version_t _minor) {
+ std::lock_guard<std::mutex> its_lock(offer_serialization_mutex_);
+ // flag to indicate whether caller of this function can start directly processing the command
+ bool must_process(false);
+ auto found_service_instance = offer_commands_.find(std::make_pair(_service, _instance));
+ if (found_service_instance != offer_commands_.end()) {
+ // if nothing is queued
+ if (found_service_instance->second.empty()) {
+ must_process = true;
+ }
+ found_service_instance->second.push_back(
+ std::make_tuple(_command, _client, _major, _minor));
+ } else {
+ // nothing is queued -> add command to queue and process command directly
+ offer_commands_[std::make_pair(_service, _instance)].push_back(
+ std::make_tuple(_command, _client, _major, _minor));
+ must_process = true;
+ }
+ return must_process;
+}
+
+bool routing_manager_impl::erase_offer_command(service_t _service, instance_t _instance) {
+ std::lock_guard<std::mutex> its_lock(offer_serialization_mutex_);
+ auto found_service_instance = offer_commands_.find(std::make_pair(_service, _instance));
+ if (found_service_instance != offer_commands_.end()) {
+ // erase processed command
+ if (!found_service_instance->second.empty()) {
+ found_service_instance->second.pop_front();
+ if (!found_service_instance->second.empty()) {
+ // check for other commands to be processed
+ auto its_command = found_service_instance->second.front();
+ if (std::get<0>(its_command) == VSOMEIP_OFFER_SERVICE) {
+ io_.post([&, its_command, _service, _instance](){
+ offer_service(std::get<1>(its_command), _service, _instance,
+ std::get<2>(its_command), std::get<3>(its_command), false);
+ });
+ } else {
+ io_.post([&, its_command, _service, _instance](){
+ stop_offer_service(std::get<1>(its_command), _service, _instance,
+ std::get<2>(its_command), std::get<3>(its_command), false);
+ });
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool routing_manager_impl::offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
+ return offer_service(_client, _service, _instance, _major, _minor, true);
+}
+
+bool routing_manager_impl::offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _must_queue) {
+
VSOMEIP_INFO << "OFFER("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance
- << ":" << std::dec << int(_major) << "." << std::dec << _minor << "]";
+ << ":" << std::dec << int(_major) << "." << std::dec << _minor << "]"
+ << " (" << _must_queue << ")";
+
+ // only queue commands if method was NOT called via erase_offer_command()
+ if (_must_queue) {
+ if (!insert_offer_command(_service, _instance, VSOMEIP_OFFER_SERVICE,
+ _client, _major, _minor)) {
+ return false;
+ }
+ }
+
+ // Check if the application hosted by routing manager is allowed to offer
+ // offer_service requests of local proxies are checked in rms::on:message
+ if (_client == get_client()) {
+#ifdef _WIN32
+ std::uint32_t its_routing_uid = ANY_UID;
+ std::uint32_t its_routing_gid = ANY_GID;
+#else
+ std::uint32_t its_routing_uid = getuid();
+ std::uint32_t its_routing_gid = getgid();
+#endif
+ if (!security::get()->is_offer_allowed(its_routing_uid, its_routing_gid,
+ _client, _service, _instance)) {
+ VSOMEIP_WARNING << "routing_manager_impl::offer_service: "
+ << std::hex << "Security: Client 0x" << _client
+ << " isn't allowed to offer the following service/instance "
+ << _service << "/" << _instance
+ << " ~> Skip offer!";
+ erase_offer_command(_service, _instance);
+ return false;
+ }
+ }
- if(!handle_local_offer_service(_client, _service, _instance, _major, _minor)) {
+ if (!handle_local_offer_service(_client, _service, _instance, _major, _minor)) {
+ erase_offer_command(_service, _instance);
return false;
}
@@ -282,7 +375,7 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
if (discovery_) {
std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
if (its_info) {
- discovery_->offer_service(_service, _instance, its_info);
+ discovery_->offer_service(its_info);
}
}
@@ -290,16 +383,23 @@ bool routing_manager_impl::offer_service(client_t _client, service_t _service,
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
std::set<event_t> its_already_subscribed_events;
for (auto &ps : pending_subscriptions_) {
- if (ps.service_ == _service &&
- ps.instance_ == _instance && ps.major_ == _major) {
+ if (ps.service_ == _service
+ && ps.instance_ == _instance
+ && ps.major_ == _major) {
insert_subscription(ps.service_, ps.instance_,
ps.eventgroup_, ps.event_, client_, &its_already_subscribed_events);
- }
+ VSOMEIP_ERROR << __func__
+ << ": event="
+ << std::hex << ps.service_ << "."
+ << std::hex << ps.instance_ << "."
+ << std::hex << ps.event_; }
}
+
send_pending_subscriptions(_service, _instance, _major);
}
stub_->on_offer_service(_client, _service, _instance, _major, _minor);
on_availability(_service, _instance, true, _major, _minor);
+ erase_offer_command(_service, _instance);
return true;
}
@@ -307,11 +407,28 @@ void routing_manager_impl::stop_offer_service(client_t _client,
service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor) {
+ stop_offer_service(_client, _service, _instance, _major, _minor, true);
+}
+
+void routing_manager_impl::stop_offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _must_queue) {
+
VSOMEIP_INFO << "STOP OFFER("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance
- << ":" << std::dec << int(_major) << "." << _minor << "]";
+ << ":" << std::dec << int(_major) << "." << _minor << "]"
+ << " (" << _must_queue << ")";
+
+ if (_must_queue) {
+ if (!insert_offer_command(_service, _instance, VSOMEIP_STOP_OFFER_SERVICE,
+ _client, _major, _minor)) {
+ return;
+ }
+ }
+
bool is_local(false);
{
std::shared_ptr<serviceinfo> its_info = find_service(_service, _instance);
@@ -340,12 +457,12 @@ void routing_manager_impl::stop_offer_service(client_t _client,
<< std::hex << std::setw(4) << std::setfill('0') << _instance
<< ":" << std::dec << int(_major) << "." << _minor << "] "
<< "for remote service --> ignore";
+ erase_offer_command(_service, _instance);
}
}
void routing_manager_impl::request_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor,
- bool _use_exclusive_proxy) {
+ instance_t _instance, major_version_t _major, minor_version_t _minor) {
VSOMEIP_INFO << "REQUEST("
<< std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
@@ -353,8 +470,8 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
<< std::hex << std::setw(4) << std::setfill('0') << _instance << ":"
<< std::dec << int(_major) << "." << std::dec << _minor << "]";
- routing_manager_base::request_service(_client, _service, _instance, _major,
- _minor, _use_exclusive_proxy);
+ routing_manager_base::request_service(_client,
+ _service, _instance, _major, _minor);
auto its_info = find_service(_service, _instance);
if (!its_info) {
@@ -381,27 +498,22 @@ void routing_manager_impl::request_service(client_t _client, service_t _service,
|| _minor == ANY_MINOR)) {
if(!its_info->is_local()) {
requested_service_add(_client, _service, _instance, _major, _minor);
- its_info->add_client(_client);
- find_or_create_remote_client(_service, _instance, true, VSOMEIP_ROUTING_CLIENT);
- if (_use_exclusive_proxy) {
- std::shared_ptr<endpoint> its_endpoint = its_info->get_endpoint(true);
- if(its_endpoint) {
- find_or_create_remote_client(_service, _instance, true, _client);
- }
+ if (discovery_) {
+ // Non local service instance ~> tell SD to find it!
+ discovery_->request_service(_service, _instance, _major,
+ _minor, DEFAULT_TTL);
}
+ its_info->add_client(_client);
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, true, VSOMEIP_ROUTING_CLIENT);
}
}
}
- if (_use_exclusive_proxy) {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- specific_endpoint_clients_[_service][_instance].insert(_client);
- }
-
if (_client == get_client()) {
stub_->create_local_receiver();
- service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy };
+ service_data_t request = { _service, _instance, _major, _minor };
std::set<service_data_t> requests;
requests.insert(request);
stub_->handle_requests(_client, requests);
@@ -424,36 +536,28 @@ void routing_manager_impl::release_service(client_t _client, service_t _service,
requested_service_remove(_client, _service, _instance);
std::shared_ptr<serviceinfo> its_info(find_service(_service, _instance));
- if(its_info && !its_info->is_local()) {
- unsubscribe_specific_client_at_sd(_service, _instance, _client);
- if(!its_info->get_requesters_size()) {
- if(discovery_) {
+ if (its_info && !its_info->is_local()) {
+ if (!its_info->get_requesters_size()) {
+ if (discovery_) {
discovery_->release_service(_service, _instance);
- discovery_->unsubscribe_client(_service, _instance, VSOMEIP_ROUTING_CLIENT);
+ discovery_->unsubscribe_all(_service, _instance);
}
- clear_client_endpoints(_service, _instance, true);
- clear_client_endpoints(_service, _instance, false);
+ ep_mgr_impl_->clear_client_endpoints(_service, _instance, true);
+ ep_mgr_impl_->clear_client_endpoints(_service, _instance, false);
its_info->set_endpoint(nullptr, true);
its_info->set_endpoint(nullptr, false);
- clear_identified_clients(_service, _instance);
- clear_identifying_clients( _service, _instance);
unset_all_eventpayloads(_service, _instance);
- } else {
- remove_identified_client(_service, _instance, _client);
- remove_identifying_client(_service, _instance, _client);
- remove_specific_client_endpoint(_service, _instance, _client, true);
- remove_specific_client_endpoint(_service, _instance, _client, false);
}
} else {
- if(discovery_) {
+ if (discovery_) {
discovery_->release_service(_service, _instance);
}
}
}
-void routing_manager_impl::subscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, subscription_type_e _subscription_type) {
+void routing_manager_impl::subscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, event_t _event) {
VSOMEIP_INFO << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
@@ -464,14 +568,16 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
<< std::dec << (uint16_t)_major << "]";
const client_t its_local_client = find_local_client(_service, _instance);
if (get_client() == its_local_client) {
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::set_incoming_subscription_state(_client, _service, _instance,
_eventgroup, _event, subscription_state_e::IS_SUBSCRIBING);
+#endif
auto self = shared_from_this();
- host_->on_subscription(_service, _instance, _eventgroup, _client, true,
- [this, self, _client, _service, _instance, _eventgroup,
- _event, _major, _subscription_type]
+ host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, true,
+ [this, self, _client, _uid, _gid, _service, _instance, _eventgroup,
+ _event, _major]
(const bool _subscription_accepted) {
- (void) find_or_create_local(_client);
+ (void) ep_mgr_->find_or_create_local(_client);
if (!_subscription_accepted) {
stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup, _event);
VSOMEIP_INFO << "Subscription request from client: 0x" << std::hex
@@ -481,58 +587,52 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
} else {
stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event);
}
- routing_manager_base::subscribe(_client, _service, _instance, _eventgroup, _major, _event, _subscription_type);
+ routing_manager_base::subscribe(_client, _uid, _gid, _service, _instance, _eventgroup, _major, _event);
+#ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(_service, _instance, _eventgroup, _client);
routing_manager_base::erase_incoming_subscription_state(_client, _service, _instance,
_eventgroup, _event);
+#endif
});
} else {
if (discovery_) {
- client_t subscriber = VSOMEIP_ROUTING_CLIENT;
- if (0 == its_local_client) {
- subscriber = is_specific_endpoint_client(_client, _service, _instance);
- if (subscriber != VSOMEIP_ROUTING_CLIENT) {
- if (supports_selective(_service, _instance)) {
- identify_for_subscribe(_client, _service, _instance,
- _major, _subscription_type);
- } else {
- VSOMEIP_INFO << "Subcribe to legacy selective service: " << std::hex
- << _service << ":" << _instance << ".";
- }
- }
- }
- std::unique_lock<std::mutex> eventgroup_lock;
- auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
- if (its_eventgroup) {
- eventgroup_lock = its_eventgroup->get_subscription_lock();
- }
std::set<event_t> its_already_subscribed_events;
+
+ // Note: The calls to insert_subscription & handle_subscription_state must not
+ // run concurrently to a call to on_subscribe_ack. Therefore the lock is acquired
+ // before calling insert_subscription and released after the call to
+ // handle_subscription_state.
+ std::unique_lock<std::mutex> its_critical(remote_subscription_state_mutex_);
bool inserted = insert_subscription(_service, _instance, _eventgroup,
_event, _client, &its_already_subscribed_events);
if (inserted) {
if (0 == its_local_client) {
handle_subscription_state(_client, _service, _instance, _eventgroup, _event);
- if (its_eventgroup) {
- eventgroup_lock.unlock();
- }
+ its_critical.unlock();
static const ttl_t configured_ttl(configuration_->get_sd_ttl());
notify_one_current_value(_client, _service, _instance,
_eventgroup, _event, its_already_subscribed_events);
- discovery_->subscribe(_service, _instance, _eventgroup,
- _major, configured_ttl, subscriber, _subscription_type);
+
+ auto its_info = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_info) {
+ discovery_->subscribe(_service, _instance, _eventgroup,
+ _major, configured_ttl,
+ its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT);
+ }
} else {
+ its_critical.unlock();
if (is_available(_service, _instance, _major)) {
- stub_->send_subscribe(find_local(_service, _instance),
- _client, _service, _instance, _eventgroup, _major, _event, DEFAULT_SUBSCRIPTION);
+ stub_->send_subscribe(ep_mgr_->find_local(_service, _instance),
+ _client, _service, _instance, _eventgroup, _major, _event,
+ PENDING_SUBSCRIPTION_ID);
}
}
- } else if (its_eventgroup) {
- eventgroup_lock.unlock();
}
if (get_client() == _client) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
- subscription_data_t subscription = { _service, _instance, _eventgroup, _major,
- _event, _subscription_type};
+ subscription_data_t subscription = {
+ _service, _instance, _eventgroup, _major, _event, _uid, _gid
+ };
pending_subscriptions_.insert(subscription);
}
} else {
@@ -541,8 +641,8 @@ void routing_manager_impl::subscribe(client_t _client, service_t _service,
}
}
-void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+void routing_manager_impl::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
VSOMEIP_INFO << "UNSUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
@@ -552,14 +652,16 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
<< std::hex << std::setw(4) << std::setfill('0') << _event << "]";
bool last_subscriber_removed(true);
+
+ auto its_event = find_event(_service, _instance, _event);
std::shared_ptr<eventgroupinfo> its_info
= find_eventgroup(_service, _instance, _eventgroup);
if (its_info) {
- for (auto e : its_info->get_events()) {
+ for (const auto& e : its_info->get_events()) {
if (e->get_event() == _event || ANY_EVENT == _event)
e->remove_subscriber(_eventgroup, _client);
}
- for (auto e : its_info->get_events()) {
+ for (const auto& e : its_info->get_events()) {
if (e->has_subscriber(_eventgroup, ANY_CLIENT)) {
last_subscriber_removed = false;
break;
@@ -568,40 +670,36 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
}
if (discovery_) {
- host_->on_subscription(_service, _instance, _eventgroup, _client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ host_->on_subscription(_service, _instance, _eventgroup, _client, _uid, _gid, false,
+ [](const bool _subscription_accepted){ (void)_subscription_accepted; });
if (0 == find_local_client(_service, _instance)) {
- client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
if (last_subscriber_removed) {
unset_all_eventpayloads(_service, _instance, _eventgroup);
- }
- if (subscriber == VSOMEIP_ROUTING_CLIENT && last_subscriber_removed) {
{
- auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
+ auto tuple = std::make_tuple(_service, _instance, _eventgroup, _client);
std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
remote_subscription_state_.erase(tuple);
}
- // for normal subscribers only unsubscribe via SD if last
- // subscriber was removed
- discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
- } else if (subscriber != VSOMEIP_ROUTING_CLIENT) {
- {
- auto tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
- std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
- remote_subscription_state_.erase(tuple);
+ }
+
+ if (last_subscriber_removed
+ || (its_event && its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT)) {
+ if (its_info) {
+ discovery_->unsubscribe(_service, _instance, _eventgroup,
+ its_info->is_selective() ? _client : VSOMEIP_ROUTING_CLIENT);
}
- // for selective subscribers always unsubscribe at the SD
- discovery_->unsubscribe(_service, _instance, _eventgroup, subscriber);
}
} else {
if (get_client() == _client) {
std::lock_guard<std::mutex> ist_lock(pending_subscription_mutex_);
remove_pending_subscription(_service, _instance, _eventgroup, _event);
- stub_->send_unsubscribe(find_local(_service, _instance),
+ stub_->send_unsubscribe(
+ ep_mgr_->find_local(_service, _instance),
_client, _service, _instance, _eventgroup, _event,
- DEFAULT_SUBSCRIPTION);
+ PENDING_SUBSCRIPTION_ID);
}
}
- clear_multicast_endpoints(_service, _instance);
+ ep_mgr_impl_->clear_multicast_endpoints(_service, _instance);
} else {
VSOMEIP_ERROR<< "SOME/IP eventgroups require SD to be enabled!";
@@ -609,18 +707,21 @@ void routing_manager_impl::unsubscribe(client_t _client, service_t _service,
}
bool routing_manager_impl::send(client_t _client,
- std::shared_ptr<message> _message, bool _flush) {
- return routing_manager_base::send(_client, _message, _flush);
+ std::shared_ptr<message> _message) {
+ return routing_manager_base::send(_client, _message);
}
bool routing_manager_impl::send(client_t _client, const byte_t *_data,
- length_t _size, instance_t _instance, bool _flush, bool _reliable,
- client_t _bound_client, bool _is_valid_crc, bool _sent_from_remote) {
+ length_t _size, instance_t _instance, bool _reliable,
+ client_t _bound_client,
+ credentials_t _credentials,
+ uint8_t _status_check, bool _sent_from_remote) {
bool is_sent(false);
if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
std::shared_ptr<endpoint> its_target;
bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
bool is_notification = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]);
+ bool is_response = utility::is_response(_data[VSOMEIP_MESSAGE_TYPE_POS]);
client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
_data[VSOMEIP_CLIENT_POS_MAX]);
@@ -629,21 +730,14 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
method_t its_method = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
- bool is_service_discovery = (its_service == vsomeip::sd::service
- && its_method == vsomeip::sd::method);
-
-#ifdef USE_DLT
- bool is_response(false);
-#endif
+ bool is_service_discovery
+ = (its_service == sd::service && its_method == sd::method);
if (is_request) {
- its_target = find_local(its_service, _instance);
+ its_target = ep_mgr_->find_local(its_service, _instance);
} else if (!is_notification) {
-#ifdef USE_DLT
- is_response = true;
-#endif
its_target = find_local(its_client);
- } else if (is_notification && _client) { // Selective notifications!
+ } else if (is_notification && _client && !is_service_discovery) { // Selective notifications!
if (_client == get_client()) {
#ifdef USE_DLT
const uint16_t its_data_size
@@ -654,7 +748,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- deliver_message(_data, _size, _instance, _reliable, _bound_client, _is_valid_crc, _sent_from_remote);
+ deliver_message(_data, _size, _instance, _reliable, _bound_client, _credentials, _status_check, _sent_from_remote);
return true;
}
its_target = find_local(_client);
@@ -673,36 +767,39 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
_data, its_data_size);
}
#endif
- is_sent = send_local(its_target, get_client(), _data, _size, _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
+ is_sent = send_local(its_target, get_client(), _data, _size, _instance, _reliable, VSOMEIP_SEND, _status_check);
} else {
// Check whether hosting application should get the message
// If not, check routes to external
- if ((its_client == host_->get_client() && !is_request)
+ if ((its_client == host_->get_client() && is_response)
|| (find_local_client(its_service, _instance)
== host_->get_client() && is_request)) {
- // TODO: find out how to handle session id here
- is_sent = deliver_message(_data, _size, _instance, _reliable, _bound_client, _is_valid_crc, _sent_from_remote);
+ // TODO: Find out how to handle session id here
+ is_sent = deliver_message(_data, _size, _instance, _reliable, VSOMEIP_ROUTING_CLIENT, _credentials, _status_check);
} else {
e2e_buffer outputBuffer;
- if( configuration_->is_e2e_enabled()) {
+ if (e2e_provider_) {
if ( !is_service_discovery) {
service_t its_service = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
method_t its_method = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
- if( custom_protectors.count({its_service, its_method})) {
+#ifndef ANDROID
+ if (e2e_provider_->is_protected({its_service, its_method})) {
outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS);
e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size);
- custom_protectors[{its_service, its_method}]->protect( inputBuffer);
+ e2e_provider_->protect({its_service, its_method}, inputBuffer);
outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS);
std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS);
_data = outputBuffer.data();
}
+#endif
}
}
if (is_request) {
- client_t client = is_specific_endpoint_client(its_client, its_service, _instance);
- its_target = find_or_create_remote_client(its_service, _instance, _reliable, client);
+ client_t client = VSOMEIP_ROUTING_CLIENT;
+ its_target = ep_mgr_impl_->find_or_create_remote_client(
+ its_service, _instance, _reliable, client);
if (its_target) {
#ifdef USE_DLT
const uint16_t its_data_size
@@ -713,7 +810,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- is_sent = its_target->send(_data, _size, _flush);
+ is_sent = its_target->send(_data, _size);
} else {
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SESSION_POS_MIN],
@@ -729,7 +826,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
std::shared_ptr<serviceinfo> its_info(find_service(its_service, _instance));
if (its_info || is_service_discovery) {
if (is_notification && !is_service_discovery) {
- send_local_notification(get_client(), _data, _size, _instance, _flush, _reliable, _is_valid_crc);
+ send_local_notification(get_client(), _data, _size, _instance, _reliable, _status_check);
method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
_data[VSOMEIP_METHOD_POS_MAX]);
std::shared_ptr<event> its_event = find_event(its_service, _instance, its_method);
@@ -741,42 +838,49 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
// we need both endpoints as clients can subscribe to events via TCP and UDP
std::shared_ptr<endpoint> its_udp_server_endpoint = its_info->get_endpoint(false);
std::shared_ptr<endpoint> its_tcp_server_endpoint = its_info->get_endpoint(true);
- bool is_offered_both(false);
- if (its_udp_server_endpoint && its_tcp_server_endpoint) {
- is_offered_both = true;
- }
+
if (its_udp_server_endpoint || its_tcp_server_endpoint) {
+ const auto its_reliability = its_event->get_reliability();
for (auto its_group : its_event->get_eventgroups()) {
auto its_eventgroup = find_eventgroup(its_service, _instance, its_group);
if (its_eventgroup) {
// Unicast targets
- for (const auto &its_remote : its_eventgroup->get_targets()) {
- if(its_remote.endpoint_->is_reliable() && its_tcp_server_endpoint) {
- if (!is_offered_both || (is_offered_both && its_event->is_reliable())) {
- its_targets.insert(its_remote.endpoint_);
+ for (const auto &its_remote : its_eventgroup->get_unicast_targets()) {
+ if (its_remote->is_reliable() && its_tcp_server_endpoint) {
+ if (its_reliability == reliability_type_e::RT_RELIABLE
+ || its_reliability == reliability_type_e::RT_BOTH) {
+ its_targets.insert(its_remote);
}
} else if (its_udp_server_endpoint && !its_eventgroup->is_sending_multicast()) {
- if (!is_offered_both || (is_offered_both && !its_event->is_reliable())) {
- its_targets.insert(its_remote.endpoint_);
+ if (its_reliability == reliability_type_e::RT_UNRELIABLE
+ || its_reliability == reliability_type_e::RT_BOTH) {
+ its_targets.insert(its_remote);
}
}
}
// Send to multicast targets if subscribers are still interested
if (its_eventgroup->is_sending_multicast()) {
- for (auto its_multicast_target : its_eventgroup->get_multicast_targets()) {
- if (!is_offered_both || (is_offered_both && !its_event->is_reliable())) {
- its_targets.insert(its_multicast_target.endpoint_);
+ if (its_reliability == reliability_type_e::RT_UNRELIABLE
+ || its_reliability == reliability_type_e::RT_BOTH) {
+ boost::asio::ip::address its_address;
+ uint16_t its_port;
+ if (its_eventgroup->get_multicast(its_address, its_port)) {
+ std::shared_ptr<endpoint_definition> its_multicast_target;
+ its_multicast_target = endpoint_definition::get(its_address,
+ its_port, false, its_service, _instance);
+ its_targets.insert(its_multicast_target);
}
}
}
}
}
}
+
for (auto const &target : its_targets) {
if (target->is_reliable()) {
- its_tcp_server_endpoint->send_to(target, _data, _size, _flush);
+ its_tcp_server_endpoint->send_to(target, _data, _size);
} else {
- its_udp_server_endpoint->send_to(target, _data, _size, _flush);
+ its_udp_server_endpoint->send_to(target, _data, _size);
}
#ifdef USE_DLT
has_sent = true;
@@ -798,7 +902,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
if ((utility::is_response(_data[VSOMEIP_MESSAGE_TYPE_POS])
|| utility::is_error(_data[VSOMEIP_MESSAGE_TYPE_POS]))
&& !its_info->is_local()) {
- // we received a response/error but neither the hosting application
+ // We received a response/error but neither the hosting application
// nor another local client could be found --> drop
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SESSION_POS_MIN],
@@ -824,7 +928,7 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
_data, its_data_size);
#endif
- is_sent = its_target->send(_data, _size, _flush);
+ is_sent = its_target->send(_data, _size);
} else {
const session_t its_session = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_SESSION_POS_MIN],
@@ -860,30 +964,43 @@ bool routing_manager_impl::send(client_t _client, const byte_t *_data,
}
bool routing_manager_impl::send_to(
+ const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message, bool _flush) {
+ std::shared_ptr<message> _message) {
bool is_sent(false);
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- if (serializer_->serialize(_message.get())) {
- const byte_t *_data = serializer_->get_data();
- length_t _size = serializer_->get_size();
- e2e_buffer outputBuffer;
- if( configuration_->is_e2e_enabled()) {
+
+ std::shared_ptr<serializer> its_serializer(get_serializer());
+ if (its_serializer->serialize(_message.get())) {
+ const byte_t *its_data = its_serializer->get_data();
+ length_t its_size = its_serializer->get_size();
+ e2e_buffer its_output_buffer;
+ if (e2e_provider_) {
service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
+ its_data[VSOMEIP_SERVICE_POS_MIN],
+ its_data[VSOMEIP_SERVICE_POS_MAX]);
method_t its_method = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
- if( custom_protectors.count({its_service, its_method})) {
- outputBuffer.assign(_data, _data + VSOMEIP_PAYLOAD_POS);
- e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data +_size);
- custom_protectors[{its_service, its_method}]->protect( inputBuffer);
- outputBuffer.resize(inputBuffer.size() + VSOMEIP_PAYLOAD_POS);
- std::copy(inputBuffer.begin(), inputBuffer.end(), outputBuffer.begin() + VSOMEIP_PAYLOAD_POS);
- _data = outputBuffer.data();
+ its_data[VSOMEIP_METHOD_POS_MIN],
+ its_data[VSOMEIP_METHOD_POS_MAX]);
+#ifndef ANDROID
+ if(e2e_provider_->is_protected({its_service, its_method})) {
+ its_output_buffer.assign(its_data, its_data + VSOMEIP_PAYLOAD_POS);
+ e2e_buffer its_input_buffer(its_data + VSOMEIP_PAYLOAD_POS, its_data + its_size);
+ e2e_provider_->protect({its_service, its_method}, its_input_buffer);
+ its_output_buffer.resize(its_input_buffer.size() + VSOMEIP_PAYLOAD_POS);
+ std::copy(its_input_buffer.begin(), its_input_buffer.end(),
+ its_output_buffer.begin() + VSOMEIP_PAYLOAD_POS);
+ its_data = its_output_buffer.data();
}
+#endif
}
- is_sent = send_to(_target, _data, _size, _message->get_instance(), _flush);
- serializer_->reset();
+
+ const_cast<byte_t*>(its_data)[VSOMEIP_CLIENT_POS_MIN] = VSOMEIP_WORD_BYTE1(_client);
+ const_cast<byte_t*>(its_data)[VSOMEIP_CLIENT_POS_MAX] = VSOMEIP_WORD_BYTE0(_client);
+
+ is_sent = send_to(_target, its_data, its_size, _message->get_instance());
+
+ its_serializer->reset();
+ put_serializer(its_serializer);
} else {
VSOMEIP_ERROR<< "routing_manager_impl::send_to: serialization failed.";
}
@@ -892,10 +1009,10 @@ bool routing_manager_impl::send_to(
bool routing_manager_impl::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush) {
- std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
- _target->get_remote_port(), _target->is_reliable());
+ const byte_t *_data, uint32_t _size, instance_t _instance) {
+ std::shared_ptr<endpoint> its_endpoint =
+ ep_mgr_impl_->find_server_endpoint(
+ _target->get_remote_port(), _target->is_reliable());
if (its_endpoint) {
#ifdef USE_DLT
@@ -909,26 +1026,30 @@ bool routing_manager_impl::send_to(
#else
(void) _instance;
#endif
- return its_endpoint->send_to(_target, _data, _size, _flush);
+ return its_endpoint->send_to(_target, _data, _size);
}
return false;
}
-bool routing_manager_impl::send_to(
+bool routing_manager_impl::send_via_sd(
const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port) {
- std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(
- _sd_port, _target->is_reliable());
+ std::shared_ptr<endpoint> its_endpoint =
+ ep_mgr_impl_->find_server_endpoint(_sd_port,
+ _target->is_reliable());
if (its_endpoint) {
#ifdef USE_DLT
- const uint16_t its_data_size
- = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
+ if (tc_->is_sd_enabled()) {
+ const uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
- trace::header its_header;
- if (its_header.prepare(its_endpoint, true, 0x0))
- tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
- _data, its_data_size);
+ trace::header its_header;
+ if (its_header.prepare(its_endpoint, true, 0x0))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+
+ }
#endif
return its_endpoint->send_to(_target, _data, _size);
}
@@ -936,13 +1057,16 @@ bool routing_manager_impl::send_to(
return false;
}
-void routing_manager_impl::register_event(
- client_t _client, service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, std::chrono::milliseconds _cycle,
- bool _change_resets_cycle, epsilon_change_func_t _epsilon_change_func,
+void routing_manager_impl::register_event(client_t _client,
+ service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, const event_type_e _type,
+ reliability_type_e _reliability,
+ std::chrono::milliseconds _cycle, bool _change_resets_cycle,
+ bool _update_on_change,
+ epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
- auto its_event = find_event(_service, _instance, _event);
+ auto its_event = find_event(_service, _instance, _notifier);
bool is_first(false);
if (its_event) {
if (!its_event->has_ref(_client, _is_provided)) {
@@ -952,8 +1076,11 @@ void routing_manager_impl::register_event(
is_first = true;
}
if (is_first) {
- routing_manager_base::register_event(_client, _service, _instance,
- _event, _eventgroups, _is_field, _cycle, _change_resets_cycle,
+ routing_manager_base::register_event(_client,
+ _service, _instance,
+ _notifier,
+ _eventgroups, _type, _reliability,
+ _cycle, _change_resets_cycle, _update_on_change,
_epsilon_change_func, _is_provided, _is_shadow,
_is_cache_placeholder);
}
@@ -961,17 +1088,20 @@ void routing_manager_impl::register_event(
<< std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _event
+ << std::hex << std::setw(4) << std::setfill('0') << _notifier
<< ":is_provider=" << _is_provided << "]";
}
void routing_manager_impl::register_shadow_event(client_t _client,
service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, bool _is_provided) {
- routing_manager_base::register_event(_client, _service, _instance,
- _event, _eventgroups, _is_field,
- std::chrono::milliseconds::zero(), false,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, event_type_e _type,
+ reliability_type_e _reliability, bool _is_provided) {
+ routing_manager_base::register_event(_client,
+ _service, _instance,
+ _notifier,
+ _eventgroups, _type, _reliability,
+ std::chrono::milliseconds::zero(), false, true,
nullptr,
_is_provided, true);
}
@@ -985,56 +1115,49 @@ void routing_manager_impl::unregister_shadow_event(client_t _client,
void routing_manager_impl::notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
- bool _force, bool _flush, bool _remote_subscriber) {
+ bool _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , bool _remote_subscriber
+#endif
+ ) {
if (find_local(_client)) {
routing_manager_base::notify_one(_service, _instance, _event, _payload,
- _client, _force, _flush, _remote_subscriber);
+ _client, _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , _remote_subscriber
+#endif
+ );
} else {
std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
if (its_event) {
- // Event is valid for service/instance
- bool found_eventgroup(false);
- // Iterate over all groups of the event to ensure at least
- // one valid eventgroup for service/instance exists.
- for (auto its_group : its_event->get_eventgroups()) {
- auto its_eventgroup = find_eventgroup(_service, _instance, its_group);
+ std::set<std::shared_ptr<endpoint_definition> > its_targets;
+ const auto its_reliability = its_event->get_reliability();
+ for (const auto g : its_event->get_eventgroups()) {
+ const auto its_eventgroup = find_eventgroup(_service, _instance, g);
if (its_eventgroup) {
- // Eventgroup is valid for service/instance
- found_eventgroup = true;
- break;
- }
- }
- if (found_eventgroup) {
- const bool is_offered_both =
- (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT &&
- configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT);
-
- std::set<std::shared_ptr<endpoint_definition>> its_targets;
- // Now set event's payload!
- // Either with endpoint_definition (remote) or with client (local).
- {
- std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
- auto its_service = remote_subscribers_.find(_service);
- if (its_service != remote_subscribers_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- auto its_subscriber = its_instance->second.find(_client);
- if (its_subscriber != its_instance->second.end()) {
- its_targets = its_subscriber->second;
+ const auto its_subscriptions = its_eventgroup->get_remote_subscriptions();
+ for (const auto &s : its_subscriptions) {
+ if (s->has_client(_client)) {
+ if (its_reliability == reliability_type_e::RT_RELIABLE
+ || its_reliability == reliability_type_e::RT_BOTH) {
+ const auto its_reliable = s->get_reliable();
+ if (its_reliable)
+ its_targets.insert(its_reliable);
+ }
+ if (its_reliability == reliability_type_e::RT_UNRELIABLE
+ || its_reliability == reliability_type_e::RT_BOTH) {
+ const auto its_unreliable = s->get_unreliable();
+ if (its_unreliable)
+ its_targets.insert(its_unreliable);
}
}
}
}
+ }
+
+ if (its_targets.size() > 0) {
for (const auto &its_target : its_targets) {
- if (!is_offered_both) {
- its_event->set_payload(_payload, its_target, _force, _flush);
- } else {
- if (its_event->is_reliable() && its_target->is_reliable()) {
- its_event->set_payload(_payload, its_target, _force, _flush);
- } else if (!its_event->is_reliable() && !its_target->is_reliable()) {
- its_event->set_payload(_payload, its_target, _force, _flush);
- }
- }
+ its_event->set_payload(_payload, _client, its_target, _force);
}
}
} else {
@@ -1050,24 +1173,6 @@ void routing_manager_impl::on_availability(service_t _service, instance_t _insta
host_->on_availability(_service, _instance, _is_available, _major, _minor);
}
-void routing_manager_impl::on_error(
- const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port) {
- instance_t its_instance = 0;
- if (_length >= VSOMEIP_SERVICE_POS_MAX) {
- service_t its_service = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
- its_instance = find_instance(its_service, _receiver);
- }
- send_error(return_code_e::E_MALFORMED_MESSAGE, _data, _length, its_instance,
- _receiver->is_reliable(), _receiver, _remote_address, _remote_port);
-}
-
-void routing_manager_impl::release_port(uint16_t _port, bool _reliable) {
- std::lock_guard<std::mutex> its_lock(used_client_ports_mutex_);
- used_client_ports_[_reliable].erase(_port);
-}
bool routing_manager_impl::offer_service_remotely(service_t _service,
instance_t _instance,
@@ -1156,7 +1261,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service,
clear_remote_subscriber(_service, _instance);
if (discovery_ && its_info) {
- discovery_->stop_offer_service(_service, _instance, its_info);
+ discovery_->stop_offer_service(its_info);
its_info->set_endpoint(std::shared_ptr<endpoint>(), _reliable);
}
} else {
@@ -1168,7 +1273,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service,
// ensure to not send StopOffer for endpoint on which the service is
// still offered
its_copied_info->set_endpoint(std::shared_ptr<endpoint>(), !_reliable);
- discovery_->stop_offer_service(_service, _instance, its_copied_info);
+ discovery_->stop_offer_service(its_copied_info);
}
}
@@ -1178,7 +1283,7 @@ bool routing_manager_impl::stop_offer_service_remotely(service_t _service,
void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
endpoint *_receiver, const boost::asio::ip::address &_destination,
- client_t _bound_client,
+ client_t _bound_client, credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
#if 0
@@ -1191,7 +1296,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
(void)_bound_client;
service_t its_service;
method_t its_method;
- bool its_is_crc_valid(true);
+ uint8_t its_check_status = e2e::profile_interface::generic_check_status::E2E_OK;
instance_t its_instance(0x0);
#ifdef USE_DLT
bool is_forwarded(true);
@@ -1215,7 +1320,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
}
} else {
- its_instance = find_instance(its_service, _receiver);
+ its_instance = ep_mgr_impl_->find_instance(its_service, _receiver);
if (its_instance == 0xFFFF) {
its_method = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_METHOD_POS_MIN],
@@ -1256,7 +1361,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
// Security checks if enabled!
- if (configuration_->is_security_enabled()) {
+ if (security::get()->is_enabled()) {
if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
client_t requester = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_CLIENT_POS_MIN],
@@ -1276,7 +1381,7 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
<< " which is already used locally ~> Skip message!";
return;
}
- if (!configuration_->is_remote_client_allowed()) {
+ if (!security::get()->is_remote_client_allowed()) {
// check if policy allows remote requests.
VSOMEIP_WARNING << "routing_manager_impl::on_message: "
<< std::hex << "Security: Remote client with client ID 0x" << requester
@@ -1287,37 +1392,28 @@ void routing_manager_impl::on_message(const byte_t *_data, length_t _size,
}
}
}
- if( configuration_->is_e2e_enabled()) {
+ if (e2e_provider_) {
its_method = VSOMEIP_BYTES_TO_WORD(
_data[VSOMEIP_METHOD_POS_MIN],
_data[VSOMEIP_METHOD_POS_MAX]);
- if( custom_checkers.count({its_service, its_method})) {
+#ifndef ANDROID
+ if( e2e_provider_->is_checked({its_service, its_method})) {
e2e_buffer inputBuffer(_data + VSOMEIP_PAYLOAD_POS, _data + _size);
- e2e::profile_interface::generic_check_status check_status;
- custom_checkers[{its_service, its_method}]->check( inputBuffer, check_status);
+ e2e_provider_->check({its_service, its_method}, inputBuffer, its_check_status);
- if ( check_status != e2e::profile_interface::generic_check_status::E2E_OK ) {
+ if ( its_check_status != e2e::profile_interface::generic_check_status::E2E_OK ) {
VSOMEIP_INFO << std::hex << "E2E protection: CRC check failed for service: " << its_service << " method: " << its_method;
- its_is_crc_valid = false;
}
}
+#endif
}
- if (!deliver_specific_endpoint_message(
- its_service, its_instance, _data, _size, _receiver)) {
- // set client ID to zero for all messages
- if( utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- byte_t *its_data = const_cast<byte_t *>(_data);
- its_data[VSOMEIP_CLIENT_POS_MIN] = 0x0;
- its_data[VSOMEIP_CLIENT_POS_MAX] = 0x0;
- }
- // Common way of message handling
+
+ // Common way of message handling
#ifdef USE_DLT
- is_forwarded =
+ is_forwarded =
#endif
- on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(),
- _bound_client, its_is_crc_valid, true);
-
- }
+ on_message(its_service, its_instance, _data, _size, _receiver->is_reliable(),
+ _bound_client, _credentials, its_check_status, true);
}
}
#ifdef USE_DLT
@@ -1345,7 +1441,8 @@ bool routing_manager_impl::on_message(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _size,
bool _reliable, client_t _bound_client,
- bool _is_valid_crc,
+ credentials_t _credentials,
+ uint8_t _check_status,
bool _is_from_remote) {
#if 0
std::stringstream msg;
@@ -1367,15 +1464,15 @@ bool routing_manager_impl::on_message(
_data[VSOMEIP_CLIENT_POS_MAX]);
}
- if (its_client == VSOMEIP_ROUTING_CLIENT
- && utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
+ if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
is_forwarded = deliver_notification(_service, _instance, _data, _size,
- _reliable, _bound_client, _is_valid_crc, _is_from_remote);
+ _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
} else if (its_client == host_->get_client()) {
deliver_message(_data, _size, _instance,
- _reliable, _bound_client, _is_valid_crc, _is_from_remote);
+ _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
} else {
- send(its_client, _data, _size, _instance, true, _reliable, _bound_client, _is_valid_crc, _is_from_remote); //send to proxy
+ send(its_client, _data, _size, _instance, _reliable,
+ _bound_client, _credentials, _check_status, _is_from_remote); //send to proxy
}
return is_forwarded;
}
@@ -1384,9 +1481,7 @@ void routing_manager_impl::on_notification(client_t _client,
service_t _service, instance_t _instance,
const byte_t *_data, length_t _size, bool _notify_one) {
event_t its_event_id = VSOMEIP_BYTES_TO_WORD(
- _data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
-
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
std::shared_ptr<event> its_event = find_event(_service, _instance, its_event_id);
if (its_event) {
uint32_t its_length = utility::get_payload_size(_data, _size);
@@ -1396,197 +1491,37 @@ void routing_manager_impl::on_notification(client_t _client,
its_length);
if (_notify_one) {
- notify_one(_service, _instance, its_event->get_event(), its_payload, _client, true, true, false);
+ notify_one(_service, _instance, its_event->get_event(),
+ its_payload, _client, true
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , false
+#endif
+ );
} else {
if (its_event->is_field()) {
- if (its_event->is_set()) {
- its_event->set_payload(its_payload, false, true);
- } else {
- // new subscribers will be notified by SD via sent_initiale_events;
- if (its_event->get_remote_notification_pending()) {
- // Set payload first time ~> notify all remote subscriber per unicast (initial field)
- std::vector<std::unique_lock<std::mutex>> its_locks;
- std::vector<std::shared_ptr<eventgroupinfo>> its_eventgroupinfos;
- for (auto its_group : its_event->get_eventgroups()) {
- auto its_eventgroup = find_eventgroup(_service, _instance, its_group);
- if (its_eventgroup) {
- its_locks.push_back(its_eventgroup->get_subscription_lock());
- its_eventgroupinfos.push_back(its_eventgroup);
- }
- }
-
- bool is_offered_both(false);
- if (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT &&
- configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT) {
- is_offered_both = true;
- }
- for (const auto &its_eventgroup : its_eventgroupinfos) {
- //Unicast targets
- for (auto its_remote : its_eventgroup->get_targets()) {
- if (!is_offered_both) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
- } else {
- bool was_set(false);
- if (its_event->is_reliable() && its_remote.endpoint_->is_reliable()) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
- was_set = true;
- }
- if (!its_event->is_reliable() && !its_remote.endpoint_->is_reliable()) {
- its_event->set_payload(its_payload, its_remote.endpoint_, true, true);
- was_set = true;
- }
- if (!was_set) {
- its_event->set_payload_dont_notify(its_payload);
- }
- }
- }
- }
- its_event->set_remote_notification_pending(false);
- } else {
- its_event->set_payload_dont_notify(its_payload);
- }
+ if (!its_event->set_payload_notify_pending(its_payload)) {
+ its_event->set_payload(its_payload, false);
}
} else {
- its_event->set_payload(its_payload, false, true);
+ its_event->set_payload(its_payload, false, true);
}
}
}
}
-void routing_manager_impl::on_connect(std::shared_ptr<endpoint> _endpoint) {
- // Is called when endpoint->connect succeeded!
- struct service_info {
- service_t service_id_;
- instance_t instance_id_;
- major_version_t major_;
- minor_version_t minor_;
- bool reliable_;
- std::shared_ptr<endpoint> endpoint_;
- };
-
- // Set to state CONNECTED as connection is not yet fully established in remote side POV
- // but endpoint is ready to send / receive. Set to ESTABLISHED after timer expires
- // to prevent inserting subscriptions twice or send out subscription before remote side
- // is finished with TCP 3 way handshake
- _endpoint->set_connected(true);
-
- std::forward_list<struct service_info> services_to_report_;
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- for (auto &its_service : remote_services_) {
- for (auto &its_instance : its_service.second) {
- for (auto &its_client : its_instance.second) {
- if (its_client.first == VSOMEIP_ROUTING_CLIENT ||
- its_client.first == get_client()) {
- auto found_endpoint = its_client.second.find(false);
- if (found_endpoint != its_client.second.end()) {
- if (found_endpoint->second.get() == _endpoint.get()) {
- std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
- if (!its_info) {
- _endpoint->set_established(true);
- return;
- }
- services_to_report_.push_front(
- { its_service.first,
- its_instance.first,
- its_info->get_major(),
- its_info->get_minor(),
- false, _endpoint });
- }
- }
- found_endpoint = its_client.second.find(true);
- if (found_endpoint != its_client.second.end()) {
- if (found_endpoint->second.get() == _endpoint.get()) {
- std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
- if (!its_info) {
- _endpoint->set_established(true);
- return;
- }
- services_to_report_.push_front(
- { its_service.first,
- its_instance.first,
- its_info->get_major(),
- its_info->get_minor(),
- true, _endpoint });
- }
- }
- }
- }
- }
+bool routing_manager_impl::is_last_stop_callback(const uint32_t _callback_id) {
+ bool last_callback(false);
+ auto found_id = callback_counts_.find(_callback_id);
+ if (found_id != callback_counts_.end()) {
+ found_id->second--;
+ if (found_id->second == 0) {
+ last_callback = true;
}
}
-
- for (const auto &s : services_to_report_) {
- on_availability(s.service_id_, s.instance_id_, true, s.major_, s.minor_);
- if (s.reliable_) {
- stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, s.service_id_,
- s.instance_id_, s.major_, s.minor_);
- }
- std::shared_ptr<boost::asio::steady_timer> its_timer =
- std::make_shared<boost::asio::steady_timer>(io_);
- boost::system::error_code ec;
- its_timer->expires_from_now(std::chrono::milliseconds(3), ec);
- if (!ec) {
- its_timer->async_wait(
- std::bind(
- &routing_manager_impl::call_sd_endpoint_connected,
- std::static_pointer_cast<routing_manager_impl>(
- shared_from_this()),
- std::placeholders::_1, s.service_id_,
- s.instance_id_, s.endpoint_, its_timer));
- } else {
- VSOMEIP_ERROR<< "routing_manager_impl::on_connect: " << ec.message();
- }
- }
- if (services_to_report_.empty()) {
- _endpoint->set_established(true);
- }
-}
-
-void routing_manager_impl::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
- // Is called when endpoint->connect fails!
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- for (auto &its_service : remote_services_) {
- for (auto &its_instance : its_service.second) {
- for (auto &its_client : its_instance.second) {
- if (its_client.first == VSOMEIP_ROUTING_CLIENT ||
- its_client.first == get_client()) {
- auto found_endpoint = its_client.second.find(false);
- if (found_endpoint != its_client.second.end()) {
- if (found_endpoint->second.get() == _endpoint.get()) {
-
- std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
- if(!its_info){
- return;
- }
- on_availability(its_service.first, its_instance.first,
- false, its_info->get_major(), its_info->get_minor());
- }
- }
- found_endpoint = its_client.second.find(true);
- if (found_endpoint != its_client.second.end()) {
- if (found_endpoint->second.get() == _endpoint.get()) {
-
- std::shared_ptr<serviceinfo> its_info(find_service(its_service.first, its_instance.first));
- if(!its_info){
- return;
- }
- on_availability(its_service.first, its_instance.first,
- false, its_info->get_major(), its_info->get_minor());
- stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT,
- its_service.first, its_instance.first,
- its_info->get_major(),
- its_info->get_minor());
- VSOMEIP_WARNING << __func__
- << ": lost connection to remote service: "
- << std::hex << std::setw(4) << std::setfill('0') << its_service.first << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_instance.first;
- }
- }
- }
- }
- }
+ if (last_callback) {
+ callback_counts_.erase(_callback_id);
}
+ return last_callback;
}
void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _service,
@@ -1643,47 +1578,133 @@ void routing_manager_impl::on_stop_offer_service(client_t _client, service_t _se
if (its_info) {
its_reliable_endpoint = its_info->get_endpoint(true);
its_unreliable_endpoint = its_info->get_endpoint(false);
- }
+ static std::atomic<uint32_t> callback_id(0);
+ const uint32_t its_callback_id = ++callback_id;
+
+ struct ready_to_stop_t {
+ ready_to_stop_t() : reliable_(false), unreliable_(false){}
+ std::atomic<bool> reliable_;
+ std::atomic<bool> unreliable_;
+ };
+ auto ready_to_stop = std::make_shared<ready_to_stop_t>();
+ auto ptr = shared_from_this();
+
+ auto callback = [&, its_callback_id, ptr, its_info, its_reliable_endpoint, its_unreliable_endpoint,
+ ready_to_stop, _service, _instance, _major, _minor]
+ (std::shared_ptr<endpoint> _endpoint, service_t _stopped_service) {
+ (void)_stopped_service;
+ if (its_reliable_endpoint && its_reliable_endpoint == _endpoint) {
+ ready_to_stop->reliable_ = true;
+ }
+ if (its_unreliable_endpoint && its_unreliable_endpoint == _endpoint) {
+ ready_to_stop->unreliable_ = true;
+ }
+ if ((its_unreliable_endpoint && !ready_to_stop->unreliable_) ||
+ (its_reliable_endpoint && !ready_to_stop->reliable_)) {
+ {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ if (is_last_stop_callback(its_callback_id)) {
+ erase_offer_command(_service, _instance);
+ }
+ }
+ return;
+ }
- if (discovery_) {
- if (its_info) {
- if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
- discovery_->stop_offer_service(_service, _instance, its_info);
+ if (discovery_) {
+ if (its_info->get_major() == _major && its_info->get_minor() == _minor) {
+ discovery_->stop_offer_service(its_info);
+ }
}
- }
- }
- del_routing_info(_service, _instance, (its_reliable_endpoint != nullptr),
- (its_unreliable_endpoint != nullptr));
+ del_routing_info(_service, _instance, (its_reliable_endpoint != nullptr),
+ (its_unreliable_endpoint != nullptr));
- // Cleanup reliable & unreliable server endpoints hold before
- if (its_info) {
- if (its_unreliable_endpoint) {
- cleanup_server_endpoint(_service, its_unreliable_endpoint);
- // Clear service info and service group
- clear_service_info(_service, _instance, false);
+ for (const auto& ep: {its_reliable_endpoint, its_unreliable_endpoint}) {
+ if (ep) {
+ if (ep_mgr_impl_->remove_instance(_service, ep.get())) {
+ {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ callback_counts_[its_callback_id]++;
+ }
+ // last instance -> pass ANY_INSTANCE and shutdown completely
+ ep->prepare_stop(
+ [&, _service, _instance, its_callback_id, ptr, its_reliable_endpoint, its_unreliable_endpoint]
+ (std::shared_ptr<endpoint> _endpoint,
+ service_t _stopped_service) {
+ (void)_stopped_service;
+ if (ep_mgr_impl_->remove_server_endpoint(
+ _endpoint->get_local_port(),
+ _endpoint->is_reliable())) {
+ _endpoint->stop();
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ if (is_last_stop_callback(its_callback_id)) {
+ erase_offer_command(_service, _instance);
+ }
+ }
+ }, ANY_SERVICE);
+ }
+ // Clear service info and service group
+ clear_service_info(_service, _instance, ep->is_reliable());
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ if (is_last_stop_callback(its_callback_id)) {
+ erase_offer_command(_service, _instance);
+ }
+ }
+ };
+
+ // determine callback count
+ for (const auto& ep : {its_reliable_endpoint, its_unreliable_endpoint}) {
+ if (ep) {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ auto found_id = callback_counts_.find(its_callback_id);
+ if (found_id != callback_counts_.end()) {
+ found_id->second++;
+ } else {
+ callback_counts_[its_callback_id] = 1;
+ }
+ }
}
- if (its_reliable_endpoint) {
- cleanup_server_endpoint(_service, its_reliable_endpoint);
- // Clear service info and service group
- clear_service_info(_service, _instance, true);
+ for (const auto& ep : {its_reliable_endpoint, its_unreliable_endpoint}) {
+ if (ep) {
+ ep->prepare_stop(callback, _service);
+ }
+ }
+
+ if (!its_reliable_endpoint && !its_unreliable_endpoint) {
+ {
+ std::lock_guard<std::mutex> its_lock(callback_counts_mutex_);
+ callback_counts_.erase(its_callback_id);
+ }
+ erase_offer_command(_service, _instance);
}
+ } else {
+ erase_offer_command(_service, _instance);
}
}
bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
- instance_t _instance, bool _reliable, client_t _bound_client, bool _is_valid_crc, bool _is_from_remote) {
+ instance_t _instance, bool _reliable, client_t _bound_client, credentials_t _credentials,
+ uint8_t _status_check, bool _is_from_remote) {
bool is_delivered(false);
+ std::uint32_t its_sender_uid = std::get<0>(_credentials);
+ std::uint32_t its_sender_gid = std::get<1>(_credentials);
- auto a_deserializer = get_deserializer();
- a_deserializer->set_data(_data, _size);
- std::shared_ptr<message> its_message(a_deserializer->deserialize_message());
- a_deserializer->reset();
- put_deserializer(a_deserializer);
+ auto its_deserializer = get_deserializer();
+ its_deserializer->set_data(_data, _size);
+ std::shared_ptr<message_impl> its_message(its_deserializer->deserialize_message());
+ its_deserializer->reset();
+ put_deserializer(its_deserializer);
if (its_message) {
its_message->set_instance(_instance);
its_message->set_reliable(_reliable);
- its_message->set_is_valid_crc(_is_valid_crc);
+ its_message->set_check_result(_status_check);
+ its_message->set_uid(std::get<0>(_credentials));
+ its_message->set_gid(std::get<1>(_credentials));
if (!_is_from_remote) {
if (utility::is_notification(its_message->get_message_type())) {
@@ -1698,7 +1719,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return false;
} else {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ if (!security::get()->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
@@ -1711,7 +1733,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
}
}
} else if (utility::is_request(its_message->get_message_type())) {
- if (configuration_->is_security_enabled()
+ if (security::get()->is_enabled()
&& its_message->get_client() != _bound_client) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message:"
@@ -1720,12 +1742,13 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< its_message->get_service() << "/" << its_message->get_instance()
<< "/" << its_message->get_method() << " which doesn't match the bound client 0x"
<< std::setw(4) << std::setfill('0') << _bound_client
- << " ~> skip message!";
+ << " ~> Skip message!";
return false;
}
- if (!configuration_->is_client_allowed(its_message->get_client(),
- its_message->get_service(), its_message->get_instance(), its_message->get_method())) {
+ if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_message->get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
<< " isn't allowed to send a request to service/instance/method "
@@ -1746,8 +1769,9 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return false;
} else {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
- its_message->get_instance(), its_message->get_method())) {
+ if (!security::get()->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
<< " isn't allowed to receive a response from service/instance/method "
@@ -1760,7 +1784,7 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
}
}
} else {
- if (!configuration_->is_remote_client_allowed()) {
+ if (!security::get()->is_remote_client_allowed()) {
// if the message is from remote, check if
// policy allows remote requests.
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
@@ -1773,7 +1797,8 @@ bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return false;
} else if (utility::is_notification(its_message->get_message_type())) {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ if (!security::get()->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_impl::deliver_message: "
@@ -1800,11 +1825,14 @@ bool routing_manager_impl::deliver_notification(
service_t _service, instance_t _instance,
const byte_t *_data, length_t _length,
bool _reliable, client_t _bound_client,
- bool _is_valid_crc, bool _is_from_remote) {
- method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],
- _data[VSOMEIP_METHOD_POS_MAX]);
+ credentials_t _credentials,
+ uint8_t _status_check, bool _is_from_remote) {
+ event_t its_event_id = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
+ client_t its_client_id = VSOMEIP_BYTES_TO_WORD(
+ _data[VSOMEIP_CLIENT_POS_MIN], _data[VSOMEIP_CLIENT_POS_MAX]);
- std::shared_ptr<event> its_event = find_event(_service, _instance, its_method);
+ std::shared_ptr<event> its_event = find_event(_service, _instance, its_event_id);
if (its_event) {
if (!its_event->is_provided()) {
if (its_event->get_subscribers().size() == 0) {
@@ -1843,17 +1871,46 @@ bool routing_manager_impl::deliver_notification(
}
}
- for (const auto its_local_client : its_event->get_subscribers()) {
- if (its_local_client == host_->get_client()) {
- deliver_message(_data, _length, _instance, _reliable, _bound_client, _is_valid_crc, _is_from_remote);
- } else {
- std::shared_ptr<endpoint> its_local_target = find_local(its_local_client);
- if (its_local_target) {
- send_local(its_local_target, VSOMEIP_ROUTING_CLIENT,
- _data, _length, _instance, true, _reliable, VSOMEIP_SEND, _is_valid_crc);
+ if (its_event->get_type() != event_type_e::ET_SELECTIVE_EVENT) {
+ for (const auto its_local_client : its_event->get_subscribers()) {
+ if (its_local_client == host_->get_client()) {
+ deliver_message(_data, _length, _instance, _reliable,
+ _bound_client, _credentials, _status_check, _is_from_remote);
+ } else {
+ std::shared_ptr<endpoint> its_local_target = find_local(its_local_client);
+ if (its_local_target) {
+ send_local(its_local_target, VSOMEIP_ROUTING_CLIENT,
+ _data, _length, _instance, _reliable, VSOMEIP_SEND, _status_check);
+ }
+ }
+ }
+ } else {
+ // TODO: Check whether it makes more sense to set the client id
+ // for internal selective events. This would create some extra
+ // effort but we could avoid this hack.
+ if (its_client_id == VSOMEIP_ROUTING_CLIENT)
+ its_client_id = get_client();
+
+ auto its_subscribers = its_event->get_subscribers();
+ if (its_subscribers.find(its_client_id) != its_subscribers.end()) {
+ if (its_client_id == host_->get_client()) {
+ deliver_message(_data, _length, _instance, _reliable,
+ _bound_client, _credentials, _status_check, _is_from_remote);
+ } else {
+ std::shared_ptr<endpoint> its_local_target = find_local(its_client_id);
+ if (its_local_target) {
+ send_local(its_local_target, VSOMEIP_ROUTING_CLIENT,
+ _data, _length, _instance, _reliable, VSOMEIP_SEND, _status_check);
+ }
}
}
}
+ } else {
+ VSOMEIP_WARNING << __func__ << ": Event ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_event_id << "]"
+ << " is not registered. The message is dropped.";
}
return true;
@@ -1865,34 +1922,40 @@ std::shared_ptr<eventgroupinfo> routing_manager_impl::find_eventgroup(
return routing_manager_base::find_eventgroup(_service, _instance, _eventgroup);
}
-const std::shared_ptr<configuration> routing_manager_impl::get_configuration() const {
- return (host_->get_configuration());
-}
-
std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoint(
const std::string &_address, uint16_t _port, bool _reliable) {
- std::shared_ptr<endpoint> its_service_endpoint = find_server_endpoint(_port,
- _reliable);
+ std::shared_ptr<endpoint> its_service_endpoint =
+ ep_mgr_impl_->find_server_endpoint(_port, _reliable);
if (!its_service_endpoint) {
try {
- its_service_endpoint = create_server_endpoint(_port, _reliable,
- true);
+ its_service_endpoint =
+ ep_mgr_impl_->create_server_endpoint(_port,
+ _reliable, true);
if (its_service_endpoint) {
- sd_info_ = std::make_shared<serviceinfo>(ANY_MAJOR, ANY_MINOR,
- DEFAULT_TTL, false); // false, because we do _not_ want to announce it...
+ sd_info_ = std::make_shared<serviceinfo>(
+ VSOMEIP_SD_SERVICE, VSOMEIP_SD_INSTANCE,
+ ANY_MAJOR, ANY_MINOR, DEFAULT_TTL,
+ false); // false, because we do _not_ want to announce it...
sd_info_->set_endpoint(its_service_endpoint, _reliable);
its_service_endpoint->add_default_target(VSOMEIP_SD_SERVICE,
_address, _port);
- its_service_endpoint->join(_address);
+ if (!_reliable) {
+#if defined(_WIN32) || defined(ANDROID)
+ dynamic_cast<udp_server_endpoint_impl*>(
+ its_service_endpoint.get())->join(_address);
+#else
+ reinterpret_cast<udp_server_endpoint_impl*>(
+ its_service_endpoint.get())->join(_address);
+#endif
+ }
} else {
VSOMEIP_ERROR<< "Service Discovery endpoint could not be created. "
"Please check your network configuration.";
}
} catch (const std::exception &e) {
- host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
- VSOMEIP_ERROR << "Service Discovery endpoint could not be created: "
- << e.what();
+ VSOMEIP_ERROR << "Server endpoint creation failed: Service "
+ "Discovery endpoint could not be created: " << e.what();
}
}
return its_service_endpoint;
@@ -1900,8 +1963,8 @@ std::shared_ptr<endpoint> routing_manager_impl::create_service_discovery_endpoin
services_t routing_manager_impl::get_offered_services() const {
services_t its_services;
- for (auto s : get_services()) {
- for (auto i : s.second) {
+ for (const auto& s : get_services()) {
+ for (const auto& i : s.second) {
if (i.second->is_local()) {
its_services[s.first][i.first] = i.second;
}
@@ -1926,7 +1989,7 @@ routing_manager_impl::get_offered_service_instances(service_t _service) const {
const services_t its_services(get_services());
const auto found_service = its_services.find(_service);
if (found_service != its_services.end()) {
- for (const auto i : found_service->second) {
+ for (const auto& i : found_service->second) {
if (i.second->is_local()) {
its_instances[i.first] = i.second;
}
@@ -1935,25 +1998,6 @@ routing_manager_impl::get_offered_service_instances(service_t _service) const {
return its_instances;
}
-std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
- service_t _service, instance_t _instance, bool _reliable, client_t _client) {
- std::shared_ptr<endpoint> its_endpoint;
- bool start_endpoint(false);
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- its_endpoint = find_remote_client(_service, _instance, _reliable, _client);
- if (!its_endpoint) {
- its_endpoint = create_remote_client(_service, _instance, _reliable, _client);
- start_endpoint = true;
- }
- }
- if (start_endpoint && its_endpoint
- && configuration_->is_someip(_service, _instance)) {
- its_endpoint->start();
- }
- return its_endpoint;
-}
-
///////////////////////////////////////////////////////////////////////////////
// PRIVATE
///////////////////////////////////////////////////////////////////////////////
@@ -1969,39 +2013,29 @@ void routing_manager_impl::init_service_info(
return;
}
if (configuration_) {
- std::shared_ptr<endpoint> its_reliable_endpoint;
- std::shared_ptr<endpoint> its_unreliable_endpoint;
-
- uint16_t its_reliable_port = configuration_->get_reliable_port(_service,
- _instance);
- uint16_t its_unreliable_port = configuration_->get_unreliable_port(
- _service, _instance);
-
- bool is_someip = configuration_->is_someip(_service, _instance);
-
// Create server endpoints for local services only
if (_is_local_service) {
+ const bool is_someip = configuration_->is_someip(_service, _instance);
+ uint16_t its_reliable_port = configuration_->get_reliable_port(
+ _service, _instance);
if (ILLEGAL_PORT != its_reliable_port) {
- its_reliable_endpoint = find_or_create_server_endpoint(
- its_reliable_port, true, is_someip);
+ std::shared_ptr<endpoint> its_reliable_endpoint =
+ ep_mgr_impl_->find_or_create_server_endpoint(
+ its_reliable_port, true, is_someip, _service,
+ _instance);
if (its_reliable_endpoint) {
its_info->set_endpoint(its_reliable_endpoint, true);
- its_reliable_endpoint->increment_use_count();
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- service_instances_[_service][its_reliable_endpoint.get()] =
- _instance;
}
}
-
+ uint16_t its_unreliable_port = configuration_->get_unreliable_port(
+ _service, _instance);
if (ILLEGAL_PORT != its_unreliable_port) {
- its_unreliable_endpoint = find_or_create_server_endpoint(
- its_unreliable_port, false, is_someip);
+ std::shared_ptr<endpoint> its_unreliable_endpoint =
+ ep_mgr_impl_->find_or_create_server_endpoint(
+ its_unreliable_port, false, is_someip, _service,
+ _instance);
if (its_unreliable_endpoint) {
its_info->set_endpoint(its_unreliable_endpoint, false);
- its_unreliable_endpoint->increment_use_count();
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- service_instances_[_service][its_unreliable_endpoint.get()] =
- _instance;
}
}
@@ -2013,143 +2047,8 @@ void routing_manager_impl::init_service_info(
}
}
} else {
- host_->on_error(error_code_e::CONFIGURATION_MISSING);
- }
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::create_client_endpoint(
- const boost::asio::ip::address &_address,
- uint16_t _local_port, uint16_t _remote_port,
- bool _reliable, client_t _client) {
- (void)_client;
-
- std::shared_ptr<endpoint> its_endpoint;
- try {
- if (_reliable) {
- its_endpoint = std::make_shared<tcp_client_endpoint_impl>(
- shared_from_this(),
- boost::asio::ip::tcp::endpoint(
- (_address.is_v4() ?
- boost::asio::ip::tcp::v4() :
- boost::asio::ip::tcp::v6()),
- _local_port),
- boost::asio::ip::tcp::endpoint(_address, _remote_port),
- io_,
- configuration_->get_max_message_size_reliable(
- _address.to_string(), _remote_port),
- configuration_->get_buffer_shrink_threshold(),
- // send timeout after 2/3 of configured ttl, warning after 1/3
- std::chrono::milliseconds(configuration_->get_sd_ttl() * 666),
- configuration_->get_endpoint_queue_limit(
- _address.to_string(), _remote_port),
- configuration_->get_max_tcp_restart_aborts(),
- configuration_->get_max_tcp_connect_time());
-
- if (configuration_->has_enabled_magic_cookies(_address.to_string(),
- _remote_port)) {
- its_endpoint->enable_magic_cookies();
- }
- } else {
- its_endpoint = std::make_shared<udp_client_endpoint_impl>(
- shared_from_this(),
- boost::asio::ip::udp::endpoint(
- (_address.is_v4() ?
- boost::asio::ip::udp::v4() :
- boost::asio::ip::udp::v6()),
- _local_port),
- boost::asio::ip::udp::endpoint(_address, _remote_port),
- io_, configuration_->get_endpoint_queue_limit(
- _address.to_string(), _remote_port),
- configuration_->get_udp_receive_buffer_size());
- }
- } catch (...) {
- host_->on_error(error_code_e::CLIENT_ENDPOINT_CREATION_FAILED);
+ VSOMEIP_ERROR << "Missing vsomeip configuration.";
}
-
- return (its_endpoint);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::create_server_endpoint(
- uint16_t _port, bool _reliable, bool _start) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- std::shared_ptr<endpoint> its_endpoint;
- try {
- boost::asio::ip::address its_unicast = configuration_->get_unicast_address();
- if (_start) {
- if (_reliable) {
- its_endpoint = std::make_shared<tcp_server_endpoint_impl>(
- shared_from_this(),
- boost::asio::ip::tcp::endpoint(its_unicast, _port), io_,
- configuration_->get_max_message_size_reliable(
- its_unicast.to_string(), _port),
- configuration_->get_buffer_shrink_threshold(),
- // send timeout after 2/3 of configured ttl, warning after 1/3
- std::chrono::milliseconds(configuration_->get_sd_ttl() * 666),
- configuration_->get_endpoint_queue_limit(
- its_unicast.to_string(), _port));
- if (configuration_->has_enabled_magic_cookies(
- its_unicast.to_string(), _port) ||
- configuration_->has_enabled_magic_cookies(
- "local", _port)) {
- its_endpoint->enable_magic_cookies();
- }
- } else {
- configuration::endpoint_queue_limit_t its_limit =
- configuration_->get_endpoint_queue_limit(
- its_unicast.to_string(), _port);
-#ifndef _WIN32
- if (its_unicast.is_v4()) {
- its_unicast = boost::asio::ip::address_v4::any();
- } else if (its_unicast.is_v6()) {
- its_unicast = boost::asio::ip::address_v6::any();
- }
-#endif
- boost::asio::ip::udp::endpoint ep(its_unicast, _port);
- its_endpoint = std::make_shared<udp_server_endpoint_impl>(
- shared_from_this(), ep, io_, its_limit,
- configuration_->get_udp_receive_buffer_size());
- }
-
- } else {
- its_endpoint = std::make_shared<virtual_server_endpoint_impl>(
- its_unicast.to_string(), _port, _reliable);
- }
-
- if (its_endpoint) {
- server_endpoints_[_port][_reliable] = its_endpoint;
- its_endpoint->start();
- }
- } catch (const std::exception &e) {
- host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
- VSOMEIP_ERROR << e.what();
- }
-
- return (its_endpoint);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::find_server_endpoint(
- uint16_t _port, bool _reliable) const {
- std::shared_ptr<endpoint> its_endpoint;
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- auto found_port = server_endpoints_.find(_port);
- if (found_port != server_endpoints_.end()) {
- auto found_endpoint = found_port->second.find(_reliable);
- if (found_endpoint != found_port->second.end()) {
- its_endpoint = found_endpoint->second;
- }
- }
-
- return (its_endpoint);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::find_or_create_server_endpoint(
- uint16_t _port, bool _reliable, bool _start) {
- std::shared_ptr<endpoint> its_endpoint = find_server_endpoint(_port,
- _reliable);
- if (!its_endpoint) {
- its_endpoint = create_server_endpoint(_port, _reliable, _start);
- }
- return (its_endpoint);
}
void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) {
@@ -2167,8 +2066,8 @@ void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
auto its_client = requested_services_.find(_client);
if (its_client != requested_services_.end()) {
- for (auto its_service : its_client->second) {
- for (auto its_instance : its_service.second) {
+ for (const auto& its_service : its_client->second) {
+ for (const auto& its_instance : its_service.second) {
services_to_release_.push_front(
{ its_service.first, its_instance.first });
}
@@ -2180,162 +2079,6 @@ void routing_manager_impl::remove_local(client_t _client, bool _remove_uid) {
}
}
-instance_t routing_manager_impl::find_instance(service_t _service,
- endpoint * _endpoint) {
- instance_t its_instance(0xFFFF);
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- auto found_service = service_instances_.find(_service);
- if (found_service != service_instances_.end()) {
- auto found_endpoint = found_service->second.find(_endpoint);
- if (found_endpoint != found_service->second.end()) {
- its_instance = found_endpoint->second;
- }
- }
- }
- return (its_instance);
-}
-
-std::shared_ptr<endpoint> routing_manager_impl::create_remote_client(
- service_t _service, instance_t _instance, bool _reliable, client_t _client) {
- std::shared_ptr<endpoint> its_endpoint;
- std::shared_ptr<endpoint_definition> its_endpoint_def;
- uint16_t its_local_port;
- uint16_t its_remote_port = ILLEGAL_PORT;
-
- auto found_service = remote_service_info_.find(_service);
- if (found_service != remote_service_info_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_reliability = found_instance->second.find(_reliable);
- if (found_reliability != found_instance->second.end()) {
- its_endpoint_def = found_reliability->second;
- its_remote_port = its_endpoint_def->get_port();
- }
- }
- }
-
- if( its_remote_port != ILLEGAL_PORT) {
- // if client port range for remote service port range is configured
- // and remote port is in range, determine unused client port
- std::unique_lock<std::mutex> its_lock(used_client_ports_mutex_);
- if (configuration_->get_client_port(_service, _instance, its_remote_port, _reliable,
- used_client_ports_, its_local_port)) {
- if(its_endpoint_def) {
- its_endpoint = create_client_endpoint(
- its_endpoint_def->get_address(),
- its_local_port,
- its_endpoint_def->get_port(),
- _reliable, _client
- );
- }
-
- if (its_endpoint) {
- used_client_ports_[_reliable].insert(its_local_port);
- its_lock.unlock();
- service_instances_[_service][its_endpoint.get()] = _instance;
- remote_services_[_service][_instance][_client][_reliable] = its_endpoint;
- if (_client == VSOMEIP_ROUTING_CLIENT) {
- client_endpoints_by_ip_[its_endpoint_def->get_address()]
- [its_endpoint_def->get_port()]
- [_reliable] = its_endpoint;
- // Set the basic route to the service in the service info
- auto found_service_info = find_service(_service, _instance);
- if (found_service_info) {
- found_service_info->set_endpoint(its_endpoint, _reliable);
- }
- }
- }
- }
- }
- return its_endpoint;
-}
-
-
-std::shared_ptr<endpoint> routing_manager_impl::find_remote_client(
- service_t _service, instance_t _instance, bool _reliable, client_t _client) {
- std::shared_ptr<endpoint> its_endpoint;
- auto found_service = remote_services_.find(_service);
- if (found_service != remote_services_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if (found_client != found_instance->second.end()) {
- auto found_reliability = found_client->second.find(_reliable);
- if (found_reliability != found_client->second.end()) {
- its_endpoint = found_reliability->second;
- }
- }
- }
- }
- if (its_endpoint || _client != VSOMEIP_ROUTING_CLIENT) {
- return its_endpoint;
- }
-
- // If another service is hosted on the same server_endpoint
- // reuse the existing client_endpoint.
- auto found_service_info = remote_service_info_.find(_service);
- if(found_service_info != remote_service_info_.end()) {
- auto found_instance = found_service_info->second.find(_instance);
- if(found_instance != found_service_info->second.end()) {
- auto found_reliable = found_instance->second.find(_reliable);
- if(found_reliable != found_instance->second.end()) {
- std::shared_ptr<endpoint_definition> its_ep_def =
- found_reliable->second;
- auto found_address = client_endpoints_by_ip_.find(
- its_ep_def->get_address());
- if(found_address != client_endpoints_by_ip_.end()) {
- auto found_port = found_address->second.find(
- its_ep_def->get_remote_port());
- if(found_port != found_address->second.end()) {
- auto found_reliable2 = found_port->second.find(
- _reliable);
- if(found_reliable2 != found_port->second.end()) {
- its_endpoint = found_reliable2->second;
- // store the endpoint under this service/instance id
- // as well - needed for later cleanup
- remote_services_[_service][_instance][_client][_reliable] =
- its_endpoint;
- service_instances_[_service][its_endpoint.get()] = _instance;
- // add endpoint to serviceinfo object
- auto found_service_info = find_service(_service,_instance);
- if (found_service_info) {
- found_service_info->set_endpoint(its_endpoint, _reliable);
- }
- }
- }
- }
- }
- }
- }
- return its_endpoint;
-}
-
-client_t routing_manager_impl::find_client(
- service_t _service, instance_t _instance,
- const std::shared_ptr<eventgroupinfo> &_eventgroup,
- const std::shared_ptr<endpoint_definition> &_target) const {
- client_t its_client = VSOMEIP_ROUTING_CLIENT;
- if (!_eventgroup->is_multicast()) {
- if (!_target->is_reliable()) {
- uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance);
- auto endpoint = find_server_endpoint(unreliable_port, false);
- if (endpoint) {
- its_client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)->
- get_client(_target);
- }
- } else {
- uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance);
- auto endpoint = find_server_endpoint(reliable_port, true);
- if (endpoint) {
- its_client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)->
- get_client(_target);
- }
- }
- }
- return its_client;
-}
-
bool routing_manager_impl::is_field(service_t _service, instance_t _instance,
event_t _event) const {
std::lock_guard<std::mutex> its_lock(events_mutex_);
@@ -2398,60 +2141,12 @@ void routing_manager_impl::add_routing_info(
// Check whether remote services are unchanged
bool is_reliable_known(false);
bool is_unreliable_known(false);
-
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- auto found_service = remote_service_info_.find(_service);
- if (found_service != remote_service_info_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- std::shared_ptr<endpoint_definition> its_definition;
- if (_reliable_port != ILLEGAL_PORT) {
- auto found_reliable = found_instance->second.find(true);
- if (found_reliable != found_instance->second.end()) {
- its_definition = found_reliable->second;
- if (its_definition->get_address() == _reliable_address
- && its_definition->get_port() == _reliable_port) {
- is_reliable_known = true;
- } else {
- VSOMEIP_WARNING << "Reliable service endpoint has changed: ["
- << std::hex << std::setfill('0') << std::setw(4) << _service << "."
- << std::hex << std::setfill('0') << std::setw(4) << _instance << "."
- << std::dec << static_cast<std::uint32_t>(_major) << "."
- << std::dec << _minor << "] old: "
- << its_definition->get_address().to_string() << ":"
- << its_definition->get_port() << " new: "
- << _reliable_address.to_string() << ":"
- << _reliable_port;
- }
- }
- }
- if (_unreliable_port != ILLEGAL_PORT) {
- auto found_unreliable = found_instance->second.find(false);
- if (found_unreliable != found_instance->second.end()) {
- its_definition = found_unreliable->second;
- if (its_definition->get_address() == _unreliable_address
- && its_definition->get_port() == _unreliable_port) {
- is_unreliable_known = true;
- } else {
- VSOMEIP_WARNING << "Unreliable service endpoint has changed: ["
- << std::hex << std::setfill('0') << std::setw(4) << _service << "."
- << std::hex << std::setfill('0') << std::setw(4) << _instance << "."
- << std::dec << static_cast<std::uint32_t>(_major) << "."
- << std::dec << _minor << "] old: "
- << its_definition->get_address().to_string() << ":"
- << its_definition->get_port() << " new: "
- << _unreliable_address.to_string() << ":"
- << _unreliable_port;
- }
- }
- }
- }
- }
- }
+ ep_mgr_impl_->is_remote_service_known(_service, _instance, _major,
+ _minor, _reliable_address, _reliable_port, &is_reliable_known,
+ _unreliable_address, _unreliable_port, &is_unreliable_known);
bool udp_inserted(false);
-
+ bool tcp_inserted(false);
// Add endpoint(s) if necessary
if (_reliable_port != ILLEGAL_PORT && !is_reliable_known) {
std::shared_ptr<endpoint_definition> endpoint_def_tcp
@@ -2459,15 +2154,14 @@ void routing_manager_impl::add_routing_info(
if (_unreliable_port != ILLEGAL_PORT && !is_unreliable_known) {
std::shared_ptr<endpoint_definition> endpoint_def_udp
= endpoint_definition::get(_unreliable_address, _unreliable_port, false, _service, _instance);
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- remote_service_info_[_service][_instance][false] = endpoint_def_udp;
- remote_service_info_[_service][_instance][true] = endpoint_def_tcp;
- }
+ ep_mgr_impl_->add_remote_service_info(_service, _instance,
+ endpoint_def_tcp, endpoint_def_udp);
udp_inserted = true;
+ tcp_inserted = true;
} else {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- remote_service_info_[_service][_instance][true] = endpoint_def_tcp;
+ ep_mgr_impl_->add_remote_service_info(_service, _instance,
+ endpoint_def_tcp);
+ tcp_inserted = true;
}
// check if service was requested and establish TCP connection if necessary
@@ -2489,11 +2183,13 @@ void routing_manager_impl::add_routing_info(
// SWS_SD_00376 establish TCP connection to service
// service is marked as available later in on_connect()
if(!connected) {
- find_or_create_remote_client(_service, _instance,
- true, VSOMEIP_ROUTING_CLIENT);
if (udp_inserted) {
- find_or_create_remote_client(_service, _instance,
- false, VSOMEIP_ROUTING_CLIENT);
+ // atomically create reliable and unreliable endpoint
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, VSOMEIP_ROUTING_CLIENT);
+ } else {
+ ep_mgr_impl_->find_or_create_remote_client(
+ _service, _instance, true, VSOMEIP_ROUTING_CLIENT);
}
connected = true;
}
@@ -2505,10 +2201,6 @@ void routing_manager_impl::add_routing_info(
}
}
}
- auto specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance);
- for (const client_t& c : specific_endpoint_clients) {
- find_or_create_remote_client(_service, _instance, true, c);
- }
} else if (_reliable_port != ILLEGAL_PORT && is_reliable_known) {
std::lock_guard<std::mutex> its_lock(requested_services_mutex_);
for(const auto &client_id : requested_services_) {
@@ -2523,7 +2215,9 @@ void routing_manager_impl::add_routing_info(
&& (major_minor_pair.second <= _minor
|| _minor == DEFAULT_MINOR
|| major_minor_pair.second == ANY_MINOR)) {
- if (!stub_->contained_in_routing_info(
+ std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
+ if (ep && ep->is_established() &&
+ !stub_->contained_in_routing_info(
VSOMEIP_ROUTING_CLIENT, _service, _instance,
its_info->get_major(),
its_info->get_minor())) {
@@ -2534,12 +2228,8 @@ void routing_manager_impl::add_routing_info(
its_info->get_major(),
its_info->get_minor());
if (discovery_) {
- std::shared_ptr<endpoint> ep = its_info->get_endpoint(true);
- if (ep && ep->is_established()) {
- discovery_->on_endpoint_connected(
- _service, _instance,
- ep);
- }
+ discovery_->on_endpoint_connected(
+ _service, _instance, ep);
}
}
break;
@@ -2554,10 +2244,7 @@ void routing_manager_impl::add_routing_info(
if (!udp_inserted) {
std::shared_ptr<endpoint_definition> endpoint_def
= endpoint_definition::get(_unreliable_address, _unreliable_port, false, _service, _instance);
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- remote_service_info_[_service][_instance][false] = endpoint_def;
- }
+ ep_mgr_impl_->add_remote_service_info(_service, _instance, endpoint_def);
// check if service was requested and increase requester count if necessary
{
bool connected(false);
@@ -2577,7 +2264,7 @@ void routing_manager_impl::add_routing_info(
|| major_minor_pair.second
== ANY_MINOR)) {
if(!connected) {
- find_or_create_remote_client(_service, _instance,
+ ep_mgr_impl_->find_or_create_remote_client(_service, _instance,
false, VSOMEIP_ROUTING_CLIENT);
connected = true;
}
@@ -2590,7 +2277,8 @@ void routing_manager_impl::add_routing_info(
}
}
}
- if (!is_reliable_known) {
+ if (!is_reliable_known && !tcp_inserted) {
+ // UDP only service can be marked as available instantly
on_availability(_service, _instance, true, _major, _minor);
stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, _major, _minor);
}
@@ -2649,26 +2337,81 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
if(!its_info)
return;
- on_availability(_service, _instance, false, its_info->get_major(), its_info->get_minor());
- stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance, its_info->get_major(), its_info->get_minor());
+ on_availability(_service, _instance, false,
+ its_info->get_major(), its_info->get_minor());
+ stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ its_info->get_major(), its_info->get_minor());
// Implicit unsubscribe
- clear_targets_and_pending_sub_from_eventgroups(_service, _instance);
- clear_identified_clients( _service, _instance);
- clear_identifying_clients( _service, _instance);
+ std::vector<std::shared_ptr<event>> its_events;
+ {
+ std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
+ auto found_service = eventgroups_.find(_service);
+ if (found_service != eventgroups_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ for (auto &its_eventgroup : found_instance->second) {
+ // As the service is gone, all subscriptions to its events
+ // do no longer exist and the last received payload is no
+ // longer valid.
+ for (auto &its_event : its_eventgroup.second->get_events()) {
+ const auto its_subscribers = its_event->get_subscribers();
+ for (const auto its_subscriber : its_subscribers) {
+ if (its_subscriber != get_client()) {
+ its_event->remove_subscriber(
+ its_eventgroup.first, its_subscriber);
+ }
+ }
+ its_events.push_back(its_event);
+ remove_pending_subscription(_service, _instance,
+ its_eventgroup.first, its_event->get_event());
+ }
+
+ }
+ }
+ }
+ }
+ for (const auto& e : its_events) {
+ e->unset_payload(true);
+ }
- clear_remote_subscriber(_service, _instance);
+ {
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ std::set<std::tuple<
+ service_t, instance_t, eventgroup_t, client_t> > its_invalid;
+
+ for (const auto its_state : remote_subscription_state_) {
+ if (std::get<0>(its_state.first) == _service
+ && std::get<1>(its_state.first) == _instance) {
+ its_invalid.insert(its_state.first);
+ }
+ }
+
+ for (const auto its_key : its_invalid)
+ remote_subscription_state_.erase(its_key);
+ }
+
+ {
+ std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
+ auto found_service = remote_subscribers_.find(_service);
+ if (found_service != remote_subscribers_.end()) {
+ if (found_service->second.erase(_instance) > 0 &&
+ !found_service->second.size()) {
+ remote_subscribers_.erase(found_service);
+ }
+ }
+ }
if (_has_reliable) {
- clear_client_endpoints(_service, _instance, true);
- clear_remote_service_info(_service, _instance, true);
+ ep_mgr_impl_->clear_client_endpoints(_service, _instance, true);
+ ep_mgr_impl_->clear_remote_service_info(_service, _instance, true);
}
if (_has_unreliable) {
- clear_client_endpoints(_service, _instance, false);
- clear_remote_service_info(_service, _instance, false);
+ ep_mgr_impl_->clear_client_endpoints(_service, _instance, false);
+ ep_mgr_impl_->clear_remote_service_info(_service, _instance, false);
}
- clear_multicast_endpoints(_service, _instance);
+ ep_mgr_impl_->clear_multicast_endpoints(_service, _instance);
if (_has_reliable)
clear_service_info(_service, _instance, true);
@@ -2677,8 +2420,8 @@ void routing_manager_impl::del_routing_info(service_t _service, instance_t _inst
// For expired services using only unreliable endpoints that have never been created before
if (!_has_reliable && !_has_unreliable) {
- clear_remote_service_info(_service, _instance, true);
- clear_remote_service_info(_service, _instance, false);
+ ep_mgr_impl_->clear_remote_service_info(_service, _instance, true);
+ ep_mgr_impl_->clear_remote_service_info(_service, _instance, false);
clear_service_info(_service, _instance, true);
clear_service_info(_service, _instance, false);
}
@@ -2764,83 +2507,57 @@ void routing_manager_impl::expire_services(const boost::asio::ip::address &_addr
}
}
-void routing_manager_impl::expire_subscriptions(const boost::asio::ip::address &_address) {
- struct subscriptions_info {
- service_t service_id_;
- instance_t instance_id_;
- eventgroup_t eventgroup_id_;
- std::shared_ptr<endpoint_definition> invalid_endpoint_;
- client_t client_;
- std::set<std::shared_ptr<event>> events_;
- std::shared_ptr<eventgroupinfo> eventgroupinfo_;
- };
- std::vector<struct subscriptions_info> subscriptions_to_expire_;
+void
+routing_manager_impl::expire_subscriptions(
+ const boost::asio::ip::address &_address) {
{
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
- for (auto &its_service : eventgroups_) {
- for (auto &its_instance : its_service.second) {
- for (auto &its_eventgroup : its_instance.second) {
- std::set<std::shared_ptr<endpoint_definition>> its_invalid_endpoints;
- for (auto &its_target : its_eventgroup.second->get_targets()) {
- if (its_target.endpoint_->get_address() == _address)
- its_invalid_endpoints.insert(its_target.endpoint_);
- }
+ for (const auto &its_service : eventgroups_) {
+ for (const auto &its_instance : its_service.second) {
+ for (const auto &its_eventgroup : its_instance.second) {
+ const auto its_info = its_eventgroup.second;
+ for (auto its_subscription
+ : its_info->get_remote_subscriptions()) {
+ // Note: get_remote_subscription delivers a copied
+ // set of subscriptions. Thus, its is possible to
+ // to remove them within the loop.
+ const auto its_reliable = its_subscription->get_reliable();
+ const auto its_unreliable = its_subscription->get_unreliable();
+ if ((its_reliable && its_reliable->get_address() == _address)
+ || (its_unreliable && its_unreliable->get_address() == _address)) {
+
+ // TODO: Check whether subscriptions to different hosts are valid.
+ // IF yes, we probably need to simply reset the corresponding
+ // endpoint instead of removing the subscription...
+
+ if (its_reliable) {
+ VSOMEIP_ERROR << __func__
+ << ": removing subscription to "
+ << std::hex << its_info->get_service() << "."
+ << std::hex << its_info->get_instance() << "."
+ << std::hex << its_info->get_eventgroup()
+ << " from target "
+ << its_reliable->get_address().to_string() << ":"
+ << std::dec << its_reliable->get_port();
+ }
+ if (its_unreliable) {
+ VSOMEIP_ERROR << __func__
+ << ": removing subscription to "
+ << std::hex << its_info->get_service() << "."
+ << std::hex << its_info->get_instance() << "."
+ << std::hex << its_info->get_eventgroup()
+ << " from target "
+ << its_unreliable->get_address().to_string() << ":"
+ << std::dec << its_unreliable->get_port();
+ }
- for (auto &its_endpoint : its_invalid_endpoints) {
- its_eventgroup.second->remove_target(its_endpoint);
- client_t its_client = find_client(its_service.first,
- its_instance.first, its_eventgroup.second,
- its_endpoint);
- clear_remote_subscriber(its_service.first,
- its_instance.first, its_client, its_endpoint);
-
- std::set<std::shared_ptr<event> > its_events;
- if (its_eventgroup.second->get_targets().size() == 0) {
- its_events = its_eventgroup.second->get_events();
+ on_remote_unsubscribe(its_subscription);
}
- subscriptions_to_expire_.push_back({its_service.first,
- its_instance.first,
- its_eventgroup.first,
- its_endpoint,
- its_client,
- its_events,
- its_eventgroup.second});
- }
- if(its_eventgroup.second->is_multicast() && its_invalid_endpoints.size() &&
- 0 == its_eventgroup.second->get_unreliable_target_count() ) {
- //clear multicast targets if no subscriber is left for multicast eventgroup
- its_eventgroup.second->clear_multicast_targets();
}
}
}
}
}
-
- for (const auto &s : subscriptions_to_expire_) {
- if (s.invalid_endpoint_) {
- for (const auto e: s.events_) {
- if (e->is_shadow()) {
- e->unset_payload();
- }
- }
- const client_t its_hosting_client = find_local_client(
- s.service_id_, s.instance_id_);
- if (its_hosting_client != VSOMEIP_ROUTING_CLIENT) {
- const pending_subscription_t its_pending_unsubscription(
- std::shared_ptr<sd_message_identifier_t>(),
- s.invalid_endpoint_, s.invalid_endpoint_,
- 0, s.client_);
- pending_subscription_id_t its_pending_unsubscription_id =
- s.eventgroupinfo_->add_pending_subscription(
- its_pending_unsubscription);
- if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) {
- send_unsubscription(its_hosting_client, s.client_,
- s.service_id_, s.instance_id_, s.eventgroup_id_,
- its_pending_unsubscription_id);
- }
- }
- }
- }
}
void routing_manager_impl::init_routing_info() {
@@ -2863,200 +2580,194 @@ void routing_manager_impl::init_routing_info() {
its_address, its_unreliable_port);
if(its_reliable_port != ILLEGAL_PORT) {
- find_or_create_remote_client(i.first, i.second, true, VSOMEIP_ROUTING_CLIENT);
+ ep_mgr_impl_->find_or_create_remote_client(
+ i.first, i.second, true, VSOMEIP_ROUTING_CLIENT);
}
if(its_unreliable_port != ILLEGAL_PORT) {
- find_or_create_remote_client(i.first, i.second, false, VSOMEIP_ROUTING_CLIENT);
+ ep_mgr_impl_->find_or_create_remote_client(
+ i.first, i.second, false, VSOMEIP_ROUTING_CLIENT);
}
}
}
}
-void routing_manager_impl::on_remote_subscription(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<endpoint_definition> &_subscriber,
- const std::shared_ptr<endpoint_definition> &_target, ttl_t _ttl,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id,
- const std::function<void(remote_subscription_state_e, client_t)>& _callback) {
- std::shared_ptr<eventgroupinfo> its_eventgroup
- = find_eventgroup(_service, _instance, _eventgroup);
- client_t its_subscribing_client(ILLEGAL_CLIENT);
- if (!its_eventgroup) {
- VSOMEIP_ERROR << "REMOTE SUBSCRIBE: attempt to subscribe to unknown eventgroup ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << _subscriber->get_address().to_string()
- << ":" << std::dec << _subscriber->get_port()
- << (_subscriber->is_reliable() ? " reliable" : " unreliable");
- _callback(remote_subscription_state_e::SUBSCRIPTION_ERROR, its_subscribing_client);
+void routing_manager_impl::on_remote_subscribe(
+ std::shared_ptr<remote_subscription> &_subscription,
+ const remote_subscription_callback_t &_callback) {
+ auto its_eventgroupinfo = _subscription->get_eventgroupinfo();
+ if (!its_eventgroupinfo) {
+ VSOMEIP_ERROR << __func__ << " eventgroupinfo is invalid";
return;
}
- // find out client id for selective subscriber
- if (!_subscriber->is_reliable()) {
- uint16_t unreliable_port = configuration_->get_unreliable_port(_service, _instance);
- _subscriber->set_remote_port(unreliable_port);
- if (!its_eventgroup->is_multicast()) {
- auto endpoint = find_server_endpoint(unreliable_port, false);
- if (endpoint) {
- its_subscribing_client = std::dynamic_pointer_cast<udp_server_endpoint_impl>(endpoint)->
- get_client(_subscriber);
- }
- }
- } else {
- uint16_t reliable_port = configuration_->get_reliable_port(_service, _instance);
- _subscriber->set_remote_port(reliable_port);
- auto endpoint = find_server_endpoint(reliable_port, true);
- if (endpoint) {
- its_subscribing_client = std::dynamic_pointer_cast<tcp_server_endpoint_impl>(endpoint)->
- get_client(_subscriber);
- }
- }
- std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock());
- const std::chrono::steady_clock::time_point its_expiration =
- std::chrono::steady_clock::now() + std::chrono::seconds(_ttl);
- if (its_eventgroup->update_target(_subscriber, its_expiration)) {
- _callback(remote_subscription_state_e::SUBSCRIPTION_ACKED,its_subscribing_client);
- return;
- } else {
- const pending_subscription_id_t its_subscription_id =
- its_eventgroup->add_pending_subscription(
- pending_subscription_t(_sd_message_id, _subscriber,
- _target, _ttl, its_subscribing_client));
- if (its_subscription_id != DEFAULT_SUBSCRIPTION) {
- // only sent subscription to rm_proxy / hosting application if there's
- // no subscription for this eventgroup from the same remote subscriber
- // already pending
- const client_t its_offering_client = find_local_client(_service, _instance);
- send_subscription(its_offering_client, its_subscribing_client,
- _service, _instance, _eventgroup,
- its_eventgroup->get_major(), its_subscription_id);
- } else {
- VSOMEIP_WARNING << __func__ << " a remote subscription is already pending ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << _subscriber->get_address().to_string()
- << ":" << std::dec << _subscriber->get_port()
- << (_subscriber->is_reliable() ? " reliable" : " unreliable");
- }
- _callback(remote_subscription_state_e::SUBSCRIPTION_PENDING, its_subscribing_client);
+ const ttl_t its_ttl = _subscription->get_ttl();
+
+ const auto its_service = its_eventgroupinfo->get_service();
+ const auto its_instance = its_eventgroupinfo->get_instance();
+ const auto its_eventgroup = its_eventgroupinfo->get_eventgroup();
+ const auto its_major = its_eventgroupinfo->get_major();
+
+ // Get remote port(s)
+ auto its_reliable = _subscription->get_reliable();
+ if (its_reliable) {
+ uint16_t its_port
+ = configuration_->get_reliable_port(its_service, its_instance);
+ its_reliable->set_remote_port(its_port);
+ }
+
+ auto its_unreliable = _subscription->get_unreliable();
+ if (its_unreliable) {
+ uint16_t its_port
+ = configuration_->get_unreliable_port(its_service, its_instance);
+ its_unreliable->set_remote_port(its_port);
+ }
+
+ // Calculate expiration time
+ const std::chrono::steady_clock::time_point its_expiration
+ = std::chrono::steady_clock::now() + std::chrono::seconds(its_ttl);
+
+ // Try to update the subscription. This will fail, if the subscription does
+ // not exist or is still (partly) pending.
+ remote_subscription_id_t its_id;
+ std::set<client_t> its_added;
+ auto its_result = its_eventgroupinfo->update_remote_subscription(
+ _subscription, its_expiration, its_added, its_id, true);
+ if (its_result) {
+ if (!_subscription->is_pending()) { // resubscription without change
+ _callback(_subscription);
+ } else if (!its_added.empty()) { // new clients for a selective subscription
+ const client_t its_offering_client
+ = find_local_client(its_service, its_instance);
+ send_subscription(its_offering_client,
+ its_service, its_instance, its_eventgroup, its_major,
+ its_added, _subscription->get_id());
+ } else { // identical subscription is not yet processed
+ std::stringstream its_warning;
+ its_warning << __func__ << " a remote subscription is already pending ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "]"
+ << " from ";
+ if (its_reliable && its_unreliable)
+ its_warning << "[";
+ if (its_reliable)
+ its_warning << its_reliable->get_address().to_string()
+ << ":" << std::dec << its_reliable->get_port();
+ if (its_reliable && its_unreliable)
+ its_warning << ", ";
+ if (its_unreliable)
+ its_warning << its_unreliable->get_address().to_string()
+ << ":" << std::dec << its_unreliable->get_port();
+ if (its_reliable && its_unreliable)
+ its_warning << "]";
+ VSOMEIP_WARNING << its_warning.str();
+ }
+ } else { // new subscription
+ auto its_id
+ = its_eventgroupinfo->add_remote_subscription(_subscription);
+
+ const client_t its_offering_client
+ = find_local_client(its_service, its_instance);
+ send_subscription(its_offering_client,
+ its_service, its_instance, its_eventgroup, its_major,
+ _subscription->get_clients(), its_id);
+ }
+}
+
+void routing_manager_impl::on_remote_unsubscribe(
+ std::shared_ptr<remote_subscription> &_subscription) {
+ std::shared_ptr<eventgroupinfo> its_info
+ = _subscription->get_eventgroupinfo();
+ if (!its_info) {
+ VSOMEIP_ERROR << __func__
+ << ": Received Unsubscribe for unregistered eventgroup.";
return;
}
- _callback(remote_subscription_state_e::SUBSCRIPTION_ERROR, its_subscribing_client);
-}
-void routing_manager_impl::on_unsubscribe(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<endpoint_definition> _target) {
- std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service,
- _instance, _eventgroup);
- if (its_eventgroup) {
- client_t its_client = find_client(_service, _instance, its_eventgroup, _target);
- const pending_subscription_t its_pending_unsubscription(
- std::shared_ptr<sd_message_identifier_t>(), _target, _target,
- 0, its_client);
- pending_subscription_id_t its_pending_unsubscription_id =
- its_eventgroup->add_pending_subscription(
- its_pending_unsubscription);
-
- its_eventgroup->remove_target(_target);
- clear_remote_subscriber(_service, _instance, its_client, _target);
-
- if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) {
- // there are no pending (un)subscriptions
- const client_t its_offering_client = find_local_client(_service, _instance);
- send_unsubscription(its_offering_client, its_client, _service,
- _instance, _eventgroup, its_pending_unsubscription_id);
- }
+ const auto its_service = its_info->get_service();
+ const auto its_instance = its_info->get_instance();
+ const auto its_eventgroup = its_info->get_eventgroup();
+ const auto its_major = its_info->get_major();
- if (its_eventgroup->get_targets().size() == 0) {
- std::set<std::shared_ptr<event> > its_events
- = its_eventgroup->get_events();
- for (auto e : its_events) {
- if (e->is_shadow()) {
- e->unset_payload();
- }
- }
- }
- VSOMEIP_INFO << "REMOTE UNSUBSCRIBE("
- << std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << _target->get_address().to_string()
- << ":" << std::dec <<_target->get_port()
- << (_target->is_reliable() ? " reliable" : " unreliable");
+ auto its_subscriber = _subscription->get_subscriber();
- } else {
- VSOMEIP_ERROR << "REMOTE UNSUBSCRIBE: attempt to subscribe to unknown eventgroup ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << _target->get_address().to_string()
- << ":" << std::dec <<_target->get_port()
- << (_target->is_reliable() ? " reliable" : " unreliable");
+ // Get remote port(s)
+ auto its_reliable = _subscription->get_reliable();
+ if (its_reliable) {
+ uint16_t its_port
+ = configuration_->get_reliable_port(its_service, its_instance);
+ its_reliable->set_remote_port(its_port);
}
-}
-
-void routing_manager_impl::on_subscribe_ack(service_t _service,
- instance_t _instance, const boost::asio::ip::address &_address,
- uint16_t _port) {
- bool multicast_known(false);
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- const auto found_service = multicast_info.find(_service);
- if (found_service != multicast_info.end()) {
- const auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- const auto& endpoint_def = found_instance->second;
- if (endpoint_def->get_address() == _address &&
- endpoint_def->get_port() == _port) {
- // Multicast info and endpoint already created before
- // This can happen when more than one client subscribe on the same instance!
- multicast_known = true;
- }
- }
- }
- if (!multicast_known) {
- // Save multicast info to be able to delete the endpoint
- // as soon as the instance stops offering its service
- std::shared_ptr<endpoint_definition> endpoint_def =
- endpoint_definition::get(_address, _port, false, _service, _instance);
- multicast_info[_service][_instance] = endpoint_def;
- }
+ auto its_unreliable = _subscription->get_unreliable();
+ if (its_unreliable) {
+ uint16_t its_port
+ = configuration_->get_unreliable_port(its_service, its_instance);
+ its_unreliable->set_remote_port(its_port);
}
- const bool is_someip = configuration_->is_someip(_service, _instance);
- // Create multicast endpoint & join multicase group
- std::shared_ptr<endpoint> its_endpoint
- = find_or_create_server_endpoint(_port, false, is_someip);
- if (its_endpoint) {
- if (!multicast_known) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- service_instances_[_service][its_endpoint.get()] = _instance;
- }
- its_endpoint->join(_address.to_string());
- } else {
- VSOMEIP_ERROR<<"Could not find/create multicast endpoint!";
+ remote_subscription_id_t its_id(0);
+ std::set<client_t> its_removed;
+ auto its_result = its_info->update_remote_subscription(
+ _subscription, std::chrono::steady_clock::now(),
+ its_removed, its_id, false);
+
+ if (its_result) {
+ const client_t its_offering_client
+ = find_local_client(its_service, its_instance);
+ send_unsubscription(its_offering_client,
+ its_service, its_instance, its_eventgroup, its_major,
+ its_removed, its_id);
}
}
+void routing_manager_impl::on_subscribe_ack_with_multicast(
+ service_t _service, instance_t _instance,
+ const boost::asio::ip::address &_address, uint16_t _port) {
+ ep_mgr_impl_->find_or_create_multicast_endpoint(_service,
+ _instance, _address, _port);
+}
+
void routing_manager_impl::on_subscribe_ack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) {
- client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
- bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT;
+ event_t _event, remote_subscription_id_t _id) {
+ std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock());
- if (_subscription_id == DEFAULT_SUBSCRIPTION) {
- // ACK coming in via SD from remote or as answer to a subscription
- // of the application hosting the rm_impl to a local service
- auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client);
- std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
- auto its_state = remote_subscription_state_.find(its_tuple);
+ auto its_subscription = its_eventgroup->get_remote_subscription(_id);
+ if (its_subscription) {
+ its_subscription->set_client_state(_client,
+ remote_subscription_state_e::SUBSCRIPTION_ACKED);
+
+ auto its_parent = its_subscription->get_parent();
+ if (its_parent) {
+ its_parent->set_client_state(_client,
+ remote_subscription_state_e::SUBSCRIPTION_ACKED);
+ if (!its_subscription->is_pending()) {
+ its_eventgroup->remove_remote_subscription(_id);
+ }
+ }
+
+ if (discovery_) {
+ std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
+ remote_subscribers_[_service][_instance][VSOMEIP_ROUTING_CLIENT].insert(
+ its_subscription->get_subscriber());
+ discovery_->update_remote_subscription(its_subscription);
+
+ VSOMEIP_INFO << "REMOTE SUBSCRIBE("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
+ << " from " << its_subscription->get_subscriber()->get_address()
+ << ":" << std::dec << its_subscription->get_subscriber()->get_port()
+ << (its_subscription->get_subscriber()->is_reliable() ? " reliable" : " unreliable")
+ << " was accepted";
+
+ return;
+ }
+ } else {
+ const auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, _client);
+ const auto its_state = remote_subscription_state_.find(its_tuple);
if (its_state != remote_subscription_state_.end()) {
if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) {
// Already notified!
@@ -3064,385 +2775,79 @@ void routing_manager_impl::on_subscribe_ack(client_t _client,
}
}
remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED;
- } else { // ACK sent back from local client as answer to a remote subscription
- const client_t its_offering_client = find_local_client(_service, _instance);
- if (its_offering_client == VSOMEIP_ROUTING_CLIENT) {
- // service was stopped while subscription was pending
- // send subscribe_nack back instead
- eventgroup_lock.unlock();
- on_subscribe_nack(_client, _service, _instance, _eventgroup,
- _event, _subscription_id);
- return;
- }
- if (discovery_) {
- std::vector<pending_subscription_t> its_pending_subscriptions =
- its_eventgroup->remove_pending_subscription(_subscription_id);
- for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) {
- if (its_sd_message_id.ttl_ > 0) {
- if (its_sd_message_id.sd_message_identifier_
- && its_sd_message_id.subscriber_
- && its_sd_message_id.target_) {
- {
- std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
- remote_subscribers_[_service][_instance][_client].insert(its_sd_message_id.subscriber_);
- }
- const std::chrono::steady_clock::time_point its_expiration =
- std::chrono::steady_clock::now()
- + std::chrono::seconds(
- its_sd_message_id.ttl_);
- // IP address of target is a multicast address if the event is in a multicast eventgroup
- if (its_eventgroup->is_multicast()
- && !its_sd_message_id.subscriber_->is_reliable()) {
- // Event is in multicast eventgroup and subscribe for UDP
- its_eventgroup->add_target(
- { its_sd_message_id.target_, its_expiration },
- { its_sd_message_id.subscriber_, its_expiration });
- } else {
- // subscribe for TCP or UDP
- its_eventgroup->add_target(
- { its_sd_message_id.subscriber_, its_expiration });
- }
- discovery_->remote_subscription_acknowledge(_service,
- _instance, _eventgroup, _client, true,
- its_sd_message_id.sd_message_identifier_);
+ }
- VSOMEIP_INFO << "REMOTE SUBSCRIBE("
- << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << its_sd_message_id.subscriber_->get_address().to_string()
- << ":" << std::dec << its_sd_message_id.subscriber_->get_port()
- << (its_sd_message_id.subscriber_->is_reliable() ? " reliable" : " unreliable")
- << " was accepted";
- }
- } else { // unsubscription was queued while subscription was pending -> send it to client
- send_unsubscription(its_offering_client,
- its_sd_message_id.subscribing_client_,
- _service, _instance, _eventgroup,
- its_sd_message_id.pending_subscription_id_);
- }
+ std::set<client_t> subscribed_clients;
+ if (_client == VSOMEIP_ROUTING_CLIENT) {
+ for (const auto &its_event : its_eventgroup->get_events()) {
+ if (_event == ANY_EVENT || _event == its_event->get_event()) {
+ const auto &its_subscribers = its_event->get_subscribers();
+ subscribed_clients.insert(its_subscribers.begin(), its_subscribers.end());
}
}
- return;
+ } else {
+ subscribed_clients.insert(_client);
}
- if (specific_endpoint_client) {
- if (_client == get_client()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ for (const auto &its_subscriber : subscribed_clients) {
+ if (its_subscriber == get_client()) {
if (_event == ANY_EVENT) {
- for (const auto &its_event : its_eventgroup->get_events())
- host_->on_subscription_status(_service, _instance,
- _eventgroup, its_event->get_event(), 0x0 /*OK*/);
- } else {
- host_->on_subscription_status(_service, _instance,
- _eventgroup, _event, 0x0 /*OK*/);
- }
- } else {
- stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup,
- _event);
- }
- } else {
- std::set<client_t> subscribed_clients;
- for (auto its_event : its_eventgroup->get_events()) {
- for (auto its_client : its_event->get_subscribers()) {
- subscribed_clients.insert(its_client);
- }
- }
- for (auto its_subscriber : subscribed_clients) {
- if (its_subscriber == get_client()) {
- host_->on_subscription_error(_service, _instance,
- _eventgroup, 0x0 /*OK*/);
- for (auto its_event : its_eventgroup->get_events()) {
+ for (const auto &its_event : its_eventgroup->get_events()) {
host_->on_subscription_status(_service, _instance,
_eventgroup, its_event->get_event(),
0x0 /*OK*/);
}
} else {
- stub_->send_subscribe_ack(its_subscriber, _service,
- _instance, _eventgroup, _event);
- }
- }
- }
- }
-}
-
-void routing_manager_impl::on_subscribe_nack(client_t _client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) {
- client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
- bool specific_endpoint_client = its_client != VSOMEIP_ROUTING_CLIENT;
- auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
- if (its_eventgroup) {
- std::unique_lock<std::mutex> eventgroup_lock(its_eventgroup->get_subscription_lock());
- if (_subscription_id == DEFAULT_SUBSCRIPTION) {
- // NACK coming in via SD from remote or as answer to a subscription
- // of the application hosting the rm_impl to a local service
- auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, its_client);
- std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
- auto its_state = remote_subscription_state_.find(its_tuple);
- if (its_state != remote_subscription_state_.end()) {
- if (its_state->second == subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED) {
- // Already notified!
- return;
- }
- }
- remote_subscription_state_[its_tuple] = subscription_state_e::SUBSCRIPTION_NOT_ACKNOWLEDGED;
- } else { // NACK sent back from local client as answer to a remote subscription
- if (discovery_) {
- std::vector<pending_subscription_t> its_pending_subscriptions =
- its_eventgroup->remove_pending_subscription(_subscription_id);
- for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) {
- if (its_sd_message_id.ttl_ > 0) {
- if (its_sd_message_id.sd_message_identifier_ && its_sd_message_id.subscriber_) {
- discovery_->remote_subscription_acknowledge(_service, _instance,
- _eventgroup, _client, false, its_sd_message_id.sd_message_identifier_);
- VSOMEIP_INFO << "REMOTE SUBSCRIBE("
- << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " from " << its_sd_message_id.subscriber_->get_address().to_string()
- << ":" << std::dec <<its_sd_message_id.subscriber_->get_port()
- << (its_sd_message_id.subscriber_->is_reliable() ? " reliable" : " unreliable")
- << " was not accepted";
- }
- } else { // unsubscription was queued while subscription was pending -> send it to client
- const client_t its_offering_client = find_local_client(_service, _instance);
- send_unsubscription(its_offering_client,
- its_sd_message_id.subscribing_client_, _service,
- _instance, _eventgroup,
- its_sd_message_id.pending_subscription_id_);
- }
+ host_->on_subscription_status(_service, _instance,
+ _eventgroup, _event, 0x0 /*OK*/);
}
- }
- return;
- }
- if (specific_endpoint_client) {
- if (_client == get_client()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
- host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
} else {
- stub_->send_subscribe_nack(_client, _service, _instance, _eventgroup,
- _event);
- }
- } else {
- std::set<client_t> subscribed_clients;
- for (auto its_event : its_eventgroup->get_events()) {
- for (auto its_client : its_event->get_subscribers()) {
- subscribed_clients.insert(its_client);
- }
- }
- for (auto its_subscriber : subscribed_clients) {
- if (its_subscriber == get_client()) {
- host_->on_subscription_error(_service, _instance,
- _eventgroup, 0x7 /*Rejected*/);
- for (auto its_event : its_eventgroup->get_events()) {
- host_->on_subscription_status(_service, _instance,
- _eventgroup, its_event->get_event(),
- 0x7 /*Rejected*/);
- }
- } else {
- stub_->send_subscribe_nack(its_subscriber, _service,
- _instance, _eventgroup, _event);
- }
+ stub_->send_subscribe_ack(its_subscriber, _service,
+ _instance, _eventgroup, _event);
}
}
- }
+ }
}
-bool routing_manager_impl::deliver_specific_endpoint_message(service_t _service,
- instance_t _instance, const byte_t *_data, length_t _size, endpoint *_receiver) {
- client_t its_client(0x0);
-
- // Try to deliver specific endpoint message (for selective subscribers)
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- auto found_servic = remote_services_.find(_service);
- if (found_servic != remote_services_.end()) {
- auto found_instance = found_servic->second.find(_instance);
- if (found_instance != found_servic->second.end()) {
- for (auto client_entry : found_instance->second) {
- if (!client_entry.first) {
- continue;
- }
- auto found_reliability = client_entry.second.find(_receiver->is_reliable());
- if (found_reliability != client_entry.second.end()) {
- auto found_enpoint = found_reliability->second;
- if (found_enpoint.get() == _receiver) {
- its_client = client_entry.first;
- break;
- }
- }
- }
- }
- }
- }
- if (its_client) {
- if (its_client != get_client()) {
- auto local_endpoint = find_local(its_client);
- if (local_endpoint) {
- send_local(local_endpoint, its_client, _data, _size, _instance, true,
- _receiver->is_reliable(), VSOMEIP_SEND);
- }
- } else {
- deliver_message(_data, _size, _instance, _receiver->is_reliable(), VSOMEIP_ROUTING_CLIENT, true, true);
- }
- return true;
- }
-
- return false;
+std::shared_ptr<endpoint> routing_manager_impl::find_or_create_remote_client(
+ service_t _service, instance_t _instance, bool _reliable,
+ client_t _client) {
+ return ep_mgr_impl_->find_or_create_remote_client(_service,
+ _instance, _reliable, _client);
}
-void routing_manager_impl::clear_client_endpoints(service_t _service, instance_t _instance,
- bool _reliable) {
- auto its_specific_endpoint_clients = get_specific_endpoint_clients(_service, _instance);
- std::shared_ptr<endpoint> endpoint_to_delete;
- bool other_services_reachable_through_endpoint(false);
- std::vector<std::shared_ptr<endpoint>> its_specific_endpoints;
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- // Clear client endpoints for remote services (generic and specific ones)
- if (remote_services_.find(_service) != remote_services_.end()) {
- if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
- auto endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT][_reliable];
- if (endpoint) {
- service_instances_[_service].erase(endpoint.get());
- endpoint_to_delete = endpoint;
- }
- remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].erase(_reliable);
- auto found_endpoint = remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].find(
- !_reliable);
- if (found_endpoint == remote_services_[_service][_instance][VSOMEIP_ROUTING_CLIENT].end()) {
- remote_services_[_service][_instance].erase(VSOMEIP_ROUTING_CLIENT);
- }
- // erase specific client endpoints
- for (const client_t &client : its_specific_endpoint_clients) {
- auto endpoint = remote_services_[_service][_instance][client][_reliable];
- if (endpoint) {
- service_instances_[_service].erase(endpoint.get());
- its_specific_endpoints.push_back(endpoint);
- }
- remote_services_[_service][_instance][client].erase(_reliable);
- auto found_endpoint = remote_services_[_service][_instance][client].find(!_reliable);
- if (found_endpoint == remote_services_[_service][_instance][client].end()) {
- remote_services_[_service][_instance].erase(client);
- }
- }
- }
- }
- if (remote_services_.find(_service) != remote_services_.end()) {
- if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
- if (!remote_services_[_service][_instance].size()) {
- remote_services_[_service].erase(_instance);
- if (0 >= remote_services_[_service].size()) {
- remote_services_.erase(_service);
- }
- }
- }
- }
-
- if (!service_instances_[_service].size()) {
- service_instances_.erase(_service);
- }
-
- // Only stop and delete the endpoint if none of the services
- // reachable through it is online anymore.
- if (endpoint_to_delete) {
- for (const auto& service : remote_services_) {
- for (const auto& instance : service.second) {
- const auto& client = instance.second.find(VSOMEIP_ROUTING_CLIENT);
- if (client != instance.second.end()) {
- for (const auto& reliable : client->second) {
- if (reliable.second == endpoint_to_delete) {
- other_services_reachable_through_endpoint = true;
- break;
- }
- }
- }
- if (other_services_reachable_through_endpoint) { break; }
- }
- if (other_services_reachable_through_endpoint) { break; }
- }
+void routing_manager_impl::on_subscribe_nack(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ event_t _event, remote_subscription_id_t _id) {
+ (void)_event; // TODO: Remove completely?
- if (!other_services_reachable_through_endpoint) {
- std::uint16_t its_port(0);
- boost::asio::ip::address its_address;
- if (_reliable) {
- std::shared_ptr<tcp_client_endpoint_impl> ep =
- std::dynamic_pointer_cast<tcp_client_endpoint_impl>(endpoint_to_delete);
- if (ep) {
- its_port = ep->get_remote_port();
- ep->get_remote_address(its_address);
- }
- } else {
- std::shared_ptr<udp_client_endpoint_impl> ep =
- std::dynamic_pointer_cast<udp_client_endpoint_impl>(endpoint_to_delete);
- if (ep) {
- its_port = ep->get_remote_port();
- ep->get_remote_address(its_address);
- }
- }
- const auto found_ip = client_endpoints_by_ip_.find(its_address);
- if (found_ip != client_endpoints_by_ip_.end()) {
- const auto found_port = found_ip->second.find(its_port);
- if (found_port != found_ip->second.end()) {
- const auto found_reliable = found_port->second.find(_reliable);
- if (found_reliable != found_port->second.end()) {
- if (found_reliable->second == endpoint_to_delete) {
- found_port->second.erase(_reliable);
- // delete if necessary
- if (!found_port->second.size()) {
- found_ip->second.erase(found_port);
- if (!found_ip->second.size()) {
- client_endpoints_by_ip_.erase(found_ip);
- }
- }
- }
- }
- }
+ auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ auto its_subscription = its_eventgroup->get_remote_subscription(_id);
+ if (its_subscription) {
+ its_subscription->set_client_state(_client,
+ remote_subscription_state_e::SUBSCRIPTION_NACKED);
+
+ auto its_parent = its_subscription->get_parent();
+ if (its_parent) {
+ its_parent->set_client_state(_client,
+ remote_subscription_state_e::SUBSCRIPTION_NACKED);
+ if (!its_subscription->is_pending()) {
+ its_eventgroup->remove_remote_subscription(_id);
}
}
- }
- }
- if (!other_services_reachable_through_endpoint && endpoint_to_delete) {
- endpoint_to_delete->stop();
- }
- for (const auto &specific_endpoint : its_specific_endpoints) {
- specific_endpoint->stop();
- }
-}
-void routing_manager_impl::clear_multicast_endpoints(service_t _service, instance_t _instance) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- // Clear multicast info and endpoint and multicast instance (remote service)
- if (multicast_info.find(_service) != multicast_info.end()) {
- if (multicast_info[_service].find(_instance) != multicast_info[_service].end()) {
- std::string address = multicast_info[_service][_instance]->get_address().to_string();
- uint16_t port = multicast_info[_service][_instance]->get_port();
- std::shared_ptr<endpoint> multicast_endpoint;
- auto found_port = server_endpoints_.find(port);
- if (found_port != server_endpoints_.end()) {
- auto found_unreliable = found_port->second.find(false);
- if (found_unreliable != found_port->second.end()) {
- multicast_endpoint = found_unreliable->second;
- multicast_endpoint->leave(address);
- multicast_endpoint->stop();
- server_endpoints_[port].erase(false);
- }
- if (found_port->second.find(true) == found_port->second.end()) {
- server_endpoints_.erase(port);
- }
- }
- multicast_info[_service].erase(_instance);
- if (0 >= multicast_info[_service].size()) {
- multicast_info.erase(_service);
- }
- // Clear service_instances_ for multicase endpoint
- if (1 >= service_instances_[_service].size()) {
- service_instances_.erase(_service);
- } else if (multicast_endpoint) {
- service_instances_[_service].erase(multicast_endpoint.get());
+ if (discovery_) {
+ discovery_->update_remote_subscription(its_subscription);
+ VSOMEIP_INFO << "REMOTE SUBSCRIBE("
+ << std::hex << std::setw(4) << std::setfill('0') << _client <<"): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
+ << " from " << its_subscription->get_subscriber()->get_address()
+ << ":" << std::dec << its_subscription->get_subscriber()->get_port()
+ << (its_subscription->get_subscriber()->is_reliable() ? " reliable" : " unreliable")
+ << " was not accepted";
}
}
}
@@ -3495,7 +2900,7 @@ return_code_e routing_manager_impl::check_error(const byte_t *_data, length_t _s
void routing_manager_impl::send_error(return_code_e _return_code,
const byte_t *_data, length_t _size,
instance_t _instance, bool _reliable,
- endpoint *_receiver,
+ endpoint* const _receiver,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
@@ -3535,150 +2940,39 @@ void routing_manager_impl::send_error(return_code_e _return_code,
error_message->set_service(its_service);
error_message->set_session(its_session);
{
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- if (serializer_->serialize(error_message.get())) {
+ std::shared_ptr<serializer> its_serializer(get_serializer());
+ if (its_serializer->serialize(error_message.get())) {
if (_receiver) {
auto its_endpoint_def = std::make_shared<endpoint_definition>(
_remote_address, _remote_port,
_receiver->is_reliable());
its_endpoint_def->set_remote_port(_receiver->get_local_port());
- send_to(its_endpoint_def, serializer_->get_data(),
- serializer_->get_size(), _instance, true);
- }
- serializer_->reset();
- } else {
- VSOMEIP_ERROR<< "Failed to serialize error message.";
- }
- }
-}
-
-void routing_manager_impl::on_identify_response(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) {
- {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identifying_clients_.find(_service);
- if (its_service != identifying_clients_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- auto its_reliable = its_instance->second.find(_reliable);
- if (its_reliable != its_instance->second.end()) {
- its_reliable->second.erase(_client);
- }
- }
- }
- identified_clients_[_service][_instance][_reliable].insert(_client);
- }
- discovery_->send_subscriptions(_service, _instance, _client, _reliable);
-}
-
-void routing_manager_impl::identify_for_subscribe(client_t _client,
- service_t _service, instance_t _instance, major_version_t _major,
- subscription_type_e _subscription_type) {
- (void)_subscription_type;
- if (!has_identified(_client, _service, _instance, false)
- && !is_identifying(_client, _service, _instance, false)) {
- send_identify_message(_client, _service, _instance, _major, false);
- }
- if (!has_identified(_client, _service, _instance, true)
- && !is_identifying(_client, _service, _instance, true)) {
- send_identify_message(_client, _service, _instance, _major, true);
- }
-}
-
-bool routing_manager_impl::send_identify_message(client_t _client,
- service_t _service,
- instance_t _instance,
- major_version_t _major,
- bool _reliable) {
- auto its_endpoint = find_or_create_remote_client(_service, _instance,
- _reliable, _client);
- if (!its_endpoint) {
- VSOMEIP_WARNING << "routing_manager_impl::send_identify_message: "
- << "No " << (_reliable ? "reliable" : "unreliable")
- << " route for identify message to service/instance "
- << std::hex << _service << "/" << _instance << " for client "
- << _client;
- return false;
- }
- {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- identifying_clients_[_service][_instance][_reliable].insert(_client);
- }
-
- if (_client == get_client()) {
- send_identify_request(_service, _instance, _major, _reliable);
- } else {
- stub_->send_identify_request_command(find_local(_client),
- _service, _instance, _major, _reliable);
- }
-
- return true;
-}
-
-
-bool routing_manager_impl::supports_selective(service_t _service, instance_t _instance) {
- bool supports_selective(false);
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- auto its_service = remote_service_info_.find(_service);
- if (its_service != remote_service_info_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- for (auto its_reliable : its_instance->second) {
- supports_selective |= configuration_->
- supports_selective_broadcasts(
- its_reliable.second->get_address());
- }
- }
- }
- return supports_selective;
-}
-
-bool routing_manager_impl::is_identifying(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) {
- if (!supports_selective(_service, _instance)) {
- // For legacy selective services clients can't be identified!
- return false;
- }
- bool is_identifieing(false);
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identifying_clients_.find(_service);
- if (its_service != identifying_clients_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- auto its_reliable = its_instance->second.find(_reliable);
- if (its_reliable != its_instance->second.end()) {
- auto its_client = its_reliable->second.find(_client);
- if (its_client != its_reliable->second.end()) {
- is_identifieing = true;
- }
- }
- }
- }
- return is_identifieing;
-}
+ std::shared_ptr<endpoint> its_endpoint =
+ ep_mgr_impl_->find_server_endpoint(
+ its_endpoint_def->get_remote_port(),
+ its_endpoint_def->is_reliable());
+ if (its_endpoint) {
+ #ifdef USE_DLT
+ const uint16_t its_data_size
+ = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);
-bool routing_manager_impl::has_identified(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) {
- if (!supports_selective(_service, _instance)) {
- // For legacy selective services clients can't be identified!
- return true;
- }
- bool has_identified(false);
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identified_clients_.find(_service);
- if (its_service != identified_clients_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- auto its_reliable = its_instance->second.find(_reliable);
- if (its_reliable != its_instance->second.end()) {
- auto its_client = its_reliable->second.find(_client);
- if (its_client != its_reliable->second.end()) {
- has_identified = true;
+ trace::header its_header;
+ if (its_header.prepare(its_endpoint, true, _instance))
+ tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
+ _data, its_data_size);
+ #else
+ (void) _instance;
+ #endif
+ its_endpoint->send_error(its_endpoint_def,
+ its_serializer->get_data(), its_serializer->get_size());
}
}
+ its_serializer->reset();
+ put_serializer(its_serializer);
+ } else {
+ VSOMEIP_ERROR<< "Failed to serialize error message.";
}
}
- return has_identified;
}
void routing_manager_impl::clear_remote_subscriber(
@@ -3703,19 +2997,12 @@ void routing_manager_impl::clear_remote_subscriber(
std::chrono::steady_clock::time_point
routing_manager_impl::expire_subscriptions(bool _force) {
- struct subscriptions_info {
- service_t service_id_;
- instance_t instance_id_;
- eventgroup_t eventgroup_id_;
- std::shared_ptr<endpoint_definition> invalid_endpoint_;
- client_t client_;
- std::set<std::shared_ptr<event>> events_;
- std::shared_ptr<eventgroupinfo> eventgroupinfo_;
- };
- std::vector<struct subscriptions_info> subscriptions_to_expire_;
+ std::map<std::shared_ptr<remote_subscription>,
+ std::set<client_t> > its_expired_subscriptions;
+
std::chrono::steady_clock::time_point now
= std::chrono::steady_clock::now();
- std::chrono::steady_clock::time_point next_expiration
+ std::chrono::steady_clock::time_point its_next_expiration
= std::chrono::steady_clock::now() + std::chrono::hours(24);
{
std::lock_guard<std::mutex> its_lock(eventgroups_mutex_);
@@ -3723,86 +3010,70 @@ routing_manager_impl::expire_subscriptions(bool _force) {
for (auto &its_service : eventgroups_) {
for (auto &its_instance : its_service.second) {
for (auto &its_eventgroup : its_instance.second) {
- std::set<std::shared_ptr<endpoint_definition>> its_expired_endpoints;
- for (auto &its_target : its_eventgroup.second->get_targets()) {
- if (_force) {
- its_expired_endpoints.insert(its_target.endpoint_);
- } else {
- if (its_target.expiration_ < now) {
- its_expired_endpoints.insert(its_target.endpoint_);
- } else if (its_target.expiration_ < next_expiration) {
- next_expiration = its_target.expiration_;
+ auto its_subscriptions
+ = its_eventgroup.second->get_remote_subscriptions();
+ for (auto &s : its_subscriptions) {
+ for (auto its_client : s->get_clients()) {
+ if (_force) {
+ its_expired_subscriptions[s].insert(its_client);
+ } else {
+ auto its_expiration = s->get_expiration(its_client);
+ if (its_expiration != std::chrono::steady_clock::time_point()) {
+ if (its_expiration < now) {
+ its_expired_subscriptions[s].insert(its_client);
+ } else if (its_expiration < its_next_expiration) {
+ its_next_expiration = its_expiration;
+ }
+ }
}
}
}
-
- for (auto its_endpoint : its_expired_endpoints) {
- its_eventgroup.second->remove_target(its_endpoint);
-
- client_t its_client
- = find_client(its_service.first, its_instance.first,
- its_eventgroup.second, its_endpoint);
- clear_remote_subscriber(its_service.first, its_instance.first,
- its_client, its_endpoint);
-
- std::set<std::shared_ptr<event> > its_events;
- if (its_eventgroup.second->get_targets().size() == 0) {
- its_events = its_eventgroup.second->get_events();
- }
- subscriptions_to_expire_.push_back({its_service.first,
- its_instance.first,
- its_eventgroup.first,
- its_endpoint,
- its_client,
- its_events,
- its_eventgroup.second});
- }
- if(its_eventgroup.second->is_multicast() && its_expired_endpoints.size() &&
- 0 == its_eventgroup.second->get_unreliable_target_count() ) {
- //clear multicast targets if no unreliable subscriber is left for multicast eventgroup
- its_eventgroup.second->clear_multicast_targets();
- }
}
}
}
}
- for (const auto &s : subscriptions_to_expire_) {
- if (s.invalid_endpoint_) {
- for (const auto e: s.events_) {
- if (e->is_shadow()) {
- e->unset_payload();
- }
+ for (auto &s : its_expired_subscriptions) {
+ auto its_info = s.first->get_eventgroupinfo();
+ if (its_info) {
+ auto its_service = its_info->get_service();
+ auto its_instance = its_info->get_instance();
+ auto its_eventgroup = its_info->get_eventgroup();
+ auto its_major = its_info->get_major();
+
+ remote_subscription_id_t its_id;
+ auto its_result = its_info->update_remote_subscription(
+ s.first, std::chrono::steady_clock::now(),
+ s.second, its_id, false);
+ if (its_result) {
+ const client_t its_offering_client
+ = find_local_client(its_service, its_instance);
+ send_unsubscription(its_offering_client,
+ its_service, its_instance, its_eventgroup, its_major,
+ s.second, s.first->get_id());
}
- const client_t its_hosting_client = find_local_client(s.service_id_,
- s.instance_id_);
-
- if (its_hosting_client != VSOMEIP_ROUTING_CLIENT) {
- const pending_subscription_t its_pending_unsubscription(
- std::shared_ptr<sd_message_identifier_t>(),
- s.invalid_endpoint_, s.invalid_endpoint_,
- 0, s.client_);
- pending_subscription_id_t its_pending_unsubscription_id =
- s.eventgroupinfo_->add_pending_subscription(
- its_pending_unsubscription);
- if (its_pending_unsubscription_id != DEFAULT_SUBSCRIPTION) {
- send_unsubscription(its_hosting_client, s.client_, s.service_id_,
- s.instance_id_, s.eventgroup_id_,
- its_pending_unsubscription_id);
- }
+
+ if (s.first->get_unreliable()) {
+ VSOMEIP_INFO << "Expired subscription ["
+ << std::hex << std::setfill('0') << std::setw(4) << its_service << "."
+ << std::hex << std::setfill('0') << std::setw(4) << its_instance << "."
+ << std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] unreliable from "
+ << s.first->get_unreliable()->get_address() << ":"
+ << std::dec << s.first->get_unreliable()->get_port();
}
- VSOMEIP_INFO << "Expired subscription ["
- << std::hex << std::setfill('0') << std::setw(4) << s.service_id_ << "."
- << std::hex << std::setfill('0') << std::setw(4) << s.instance_id_ << "."
- << std::hex << std::setfill('0') << std::setw(4) << s.eventgroup_id_ << "] from "
- << s.invalid_endpoint_->get_address() << ":"
- << std::dec << s.invalid_endpoint_->get_port()
- << "(" << std::hex << std::setfill('0') << std::setw(4) << s.client_ << ") "
- << _force;
+ if (s.first->get_reliable()) {
+ VSOMEIP_INFO << "Expired subscription ["
+ << std::hex << std::setfill('0') << std::setw(4) << its_service << "."
+ << std::hex << std::setfill('0') << std::setw(4) << its_instance << "."
+ << std::hex << std::setfill('0') << std::setw(4) << its_eventgroup << "] reliable from "
+ << s.first->get_reliable()->get_address() << ":"
+ << std::dec << s.first->get_reliable()->get_port();
+ }
}
}
- return next_expiration;
+
+ return its_next_expiration;
}
void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const & _error) {
@@ -3811,6 +3082,9 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const
#ifndef VSOMEIP_VERSION
#define VSOMEIP_VERSION "unknown version"
#endif
+ static int counter(0);
+ static uint32_t its_interval = configuration_->get_log_version_interval();
+
bool is_diag_mode(false);
if (discovery_) {
@@ -3825,62 +3099,24 @@ void routing_manager_impl::log_version_timer_cbk(boost::system::error_code const
std::chrono::steady_clock::now() - last_resume_).count() << "s";
}
}
+
VSOMEIP_INFO << "vSomeIP " << VSOMEIP_VERSION << " | ("
<< ((is_diag_mode == true) ? "diagnosis)" : "default)")
<< its_last_resume.str();
- {
- std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_);
- version_log_timer_.expires_from_now(
- std::chrono::seconds(configuration_->get_log_version_interval()));
- version_log_timer_.async_wait(std::bind(&routing_manager_impl::log_version_timer_cbk,
- this, std::placeholders::_1));
- }
- }
-}
-
-#ifndef WITHOUT_SYSTEMD
-void routing_manager_impl::watchdog_cbk(boost::system::error_code const &_error) {
- if (!_error) {
- static bool is_ready(false);
- static bool has_interval(false);
- static uint64_t its_interval(0);
-
- if (is_ready) {
- sd_notify(0, "WATCHDOG=1");
- VSOMEIP_INFO << "Triggered systemd watchdog";
- } else {
- is_ready = true;
- sd_notify(0, "READY=1");
- VSOMEIP_INFO << "Sent READY to systemd watchdog";
- if (0 < sd_watchdog_enabled(0, &its_interval)) {
- has_interval = true;
- VSOMEIP_INFO << "systemd watchdog is enabled";
- }
- }
- if (has_interval) {
- std::lock_guard<std::mutex> its_lock(watchdog_timer_mutex_);
- watchdog_timer_.expires_from_now(std::chrono::microseconds(its_interval / 2));
- watchdog_timer_.async_wait(std::bind(&routing_manager_impl::watchdog_cbk,
- this, std::placeholders::_1));
+ counter++;
+ if (counter == 6) {
+ ep_mgr_->log_client_states();
+ ep_mgr_impl_->log_client_states();
+ counter = 0;
}
- }
-}
-#endif
-void routing_manager_impl::clear_remote_service_info(service_t _service, instance_t _instance, bool _reliable) {
- // Clear remote_service_info_
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- if (remote_service_info_.find(_service) != remote_service_info_.end()) {
- if (remote_service_info_[_service].find(_instance) != remote_service_info_[_service].end()) {
- remote_service_info_[_service][_instance].erase(_reliable);
- auto found_endpoint_def = remote_service_info_[_service][_instance].find(!_reliable);
- if (found_endpoint_def == remote_service_info_[_service][_instance].end()) {
- remote_service_info_[_service].erase(_instance);
- if (0 >= remote_service_info_[_service].size()) {
- remote_service_info_.erase(_service);
- }
- }
+ {
+ std::lock_guard<std::mutex> its_lock(version_log_timer_mutex_);
+ version_log_timer_.expires_from_now(std::chrono::seconds(its_interval));
+ version_log_timer_.async_wait(
+ std::bind(&routing_manager_impl::log_version_timer_cbk,
+ this, std::placeholders::_1));
}
}
}
@@ -4123,135 +3359,28 @@ void routing_manager_impl::handle_client_error(client_t _client) {
}
for (const auto &offer : its_offers) {
offer_service(std::get<0>(offer), std::get<1>(offer), std::get<2>(offer),
- std::get<3>(offer), std::get<4>(offer));
+ std::get<3>(offer), std::get<4>(offer), true);
}
}
-void routing_manager_impl::remove_specific_client_endpoint(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) {
- client_t its_client = is_specific_endpoint_client(_client, _service, _instance);
- if (its_client != VSOMEIP_ROUTING_CLIENT) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- if (remote_services_.find(_service) != remote_services_.end()) {
- if (remote_services_[_service].find(_instance) != remote_services_[_service].end()) {
- auto endpoint = remote_services_[_service][_instance][_client][_reliable];
- if (endpoint) {
- service_instances_[_service].erase(endpoint.get());
- endpoint->stop();
- }
- remote_services_[_service][_instance][_client].erase(_reliable);
- auto found_endpoint = remote_services_[_service][_instance][_client].find(!_reliable);
- if (found_endpoint == remote_services_[_service][_instance][_client].end()) {
- remote_services_[_service][_instance].erase(_client);
- }
- }
- }
- }
-}
-
-void routing_manager_impl::clear_identified_clients( service_t _service, instance_t _instance) {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identified_clients_.find(_service);
- if (its_service != identified_clients_.end()) {
- auto found_instance = its_service->second.find(_instance);
- if (found_instance != its_service->second.end()) {
- auto found_reliable = found_instance->second.find(true);
- if (found_reliable != found_instance->second.end()) {
- found_reliable->second.clear();
- }
- auto found_unreliable = found_instance->second.find(false);
- if (found_unreliable != found_instance->second.end()) {
- found_unreliable->second.clear();
- }
- }
- }
-}
-
-void routing_manager_impl::clear_identifying_clients( service_t _service, instance_t _instance) {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identifying_clients_.find(_service);
- if (its_service != identifying_clients_.end()) {
- auto found_instance = its_service->second.find(_instance);
- if (found_instance != its_service->second.end()) {
- auto found_reliable = found_instance->second.find(true);
- if (found_reliable != found_instance->second.end()) {
- found_reliable->second.clear();
- }
- auto found_unreliable = found_instance->second.find(false);
- if (found_unreliable != found_instance->second.end()) {
- found_unreliable->second.clear();
- }
- }
- }
-}
-
-void routing_manager_impl::remove_identified_client(service_t _service, instance_t _instance, client_t _client) {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identified_clients_.find(_service);
- if (its_service != identified_clients_.end()) {
- auto found_instance = its_service->second.find(_instance);
- if (found_instance != its_service->second.end()) {
- auto found_reliable = found_instance->second.find(true);
- if (found_reliable != found_instance->second.end()) {
- auto found_client = found_reliable->second.find(_client);
- if(found_client != found_reliable->second.end())
- found_reliable->second.erase(_client);
- }
- auto found_unreliable = found_instance->second.find(false);
- if (found_unreliable != found_instance->second.end()) {
- auto found_client = found_unreliable->second.find(_client);
- if(found_client != found_unreliable->second.end())
- found_unreliable->second.erase(_client);
- }
- }
- }
-}
-
-void routing_manager_impl::remove_identifying_client(service_t _service, instance_t _instance, client_t _client) {
- std::lock_guard<std::mutex> its_lock(identified_clients_mutex_);
- auto its_service = identifying_clients_.find(_service);
- if (its_service != identifying_clients_.end()) {
- auto found_instance = its_service->second.find(_instance);
- if (found_instance != its_service->second.end()) {
- auto found_reliable = found_instance->second.find(true);
- if (found_reliable != found_instance->second.end()) {
- auto found_client = found_reliable->second.find(_client);
- if(found_client != found_reliable->second.end())
- found_reliable->second.erase(_client);
- }
- auto found_unreliable = found_instance->second.find(false);
- if (found_unreliable != found_instance->second.end()) {
- auto found_client = found_unreliable->second.find(_client);
- if(found_client != found_unreliable->second.end())
- found_unreliable->second.erase(_client);
- }
- }
- }
-}
-
-void routing_manager_impl::unsubscribe_specific_client_at_sd(
- service_t _service, instance_t _instance, client_t _client) {
- client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
- if (subscriber != VSOMEIP_ROUTING_CLIENT && discovery_) {
- discovery_->unsubscribe_client(_service, _instance, _client);
- }
+std::shared_ptr<endpoint_manager_impl> routing_manager_impl::get_endpoint_manager() const {
+ return ep_mgr_impl_;
}
void routing_manager_impl::send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, subscription_type_e _subscription_type) {
- (void)_subscription_type;
- auto endpoint = find_local(_service, _instance);
+ event_t _event) {
+ auto endpoint = ep_mgr_->find_local(_service, _instance);
if (endpoint) {
stub_->send_subscribe(endpoint, _client,
- _service, _instance, _eventgroup, _major, _event, DEFAULT_SUBSCRIPTION);
+ _service, _instance, _eventgroup, _major, _event, PENDING_SUBSCRIPTION_ID);
}
}
void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
if(discovery_) {
switch (_routing_state) {
- case vsomeip::routing_state_e::RS_SUSPENDED:
+ case routing_state_e::RS_SUSPENDED:
{
VSOMEIP_INFO << "Set routing to suspend mode, diagnosis mode is "
<< ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
@@ -4271,7 +3400,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
<< std::hex << std::setw(4) << std::setfill('0') << its_instance.first << " still offered by "
<< std::hex << std::setw(4) << std::setfill('0') << its_client;
}
- discovery_->stop_offer_service(its_service.first, its_instance.first, its_instance.second);
+ discovery_->stop_offer_service(its_instance.second);
}
}
{
@@ -4289,13 +3418,6 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
// determine existing subscriptions to remote service and send StopSubscribe
for (auto its_eventgroup : get_subscribed_eventgroups(s.first, i.first)) {
discovery_->unsubscribe(s.first, i.first, its_eventgroup, VSOMEIP_ROUTING_CLIENT);
- auto specific_endpoint_clients = get_specific_endpoint_clients(s.first, i.first);
- for (auto its_client : specific_endpoint_clients) {
- discovery_->unsubscribe(s.first, i.first, its_eventgroup, its_client);
- }
- for (const auto &e : find_events(s.first, i.first, its_eventgroup)) {
- e->clear_subscribers();
- }
}
const bool has_reliable(i.second->get_endpoint(true));
@@ -4308,7 +3430,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
}
break;
}
- case vsomeip::routing_state_e::RS_RESUMED:
+ case routing_state_e::RS_RESUMED:
{
VSOMEIP_INFO << "Set routing to resume mode, diagnosis mode was "
<< ((discovery_->get_diagnosis_mode() == true) ? "active." : "inactive.");
@@ -4337,8 +3459,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
// Trigger initial offer phase for relevant services
for (const auto &its_service : get_offered_services()) {
for (const auto &its_instance : its_service.second) {
- discovery_->offer_service(its_service.first,
- its_instance.first, its_instance.second);
+ discovery_->offer_service(its_instance.second);
}
}
break;
@@ -4353,8 +3474,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
for (const auto &its_instance : its_service.second) {
if (host_->get_configuration()->is_someip(
its_service.first, its_instance.first)) {
- discovery_->stop_offer_service(
- its_service.first, its_instance.first, its_instance.second);
+ discovery_->stop_offer_service(its_instance.second);
}
}
}
@@ -4382,8 +3502,7 @@ void routing_manager_impl::set_routing_state(routing_state_e _routing_state) {
for (const auto &its_instance : its_service.second) {
if (host_->get_configuration()->is_someip(
its_service.first, its_instance.first)) {
- discovery_->offer_service(its_service.first,
- its_instance.first, its_instance.second);
+ discovery_->offer_service(its_instance.second);
}
}
}
@@ -4446,6 +3565,10 @@ void routing_manager_impl::on_net_interface_or_route_state_changed(
}
void routing_manager_impl::start_ip_routing() {
+#ifdef _WIN32
+ if_state_running_ = true;
+#endif
+
if (routing_ready_handler_) {
routing_ready_handler_();
}
@@ -4506,8 +3629,8 @@ routing_manager_impl::get_subscribed_eventgroups(
if (found_service != eventgroups_.end()) {
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
- for (auto its_group : found_instance->second) {
- for (auto its_event : its_group.second->get_events()) {
+ for (const auto& its_group : found_instance->second) {
+ for (const auto& its_event : its_group.second->get_events()) {
if (its_event->has_subscriber(its_group.first, ANY_CLIENT)) {
its_eventgroups.insert(its_group.first);
}
@@ -4540,7 +3663,7 @@ void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups(
its_eventgroup.first, its_subscriber);
}
- client_t its_client = is_specific_endpoint_client(its_subscriber, _service, _instance);
+ client_t its_client = VSOMEIP_ROUTING_CLIENT; //is_specific_endpoint_client(its_subscriber, _service, _instance);
{
std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
const auto its_tuple =
@@ -4551,8 +3674,9 @@ void routing_manager_impl::clear_targets_and_pending_sub_from_eventgroups(
}
its_events.push_back(its_event);
}
- its_eventgroup.second->clear_targets();
- its_eventgroup.second->clear_pending_subscriptions();
+ // TODO dn: find out why this was commented out
+ //its_eventgroup.second->clear_targets();
+ //its_eventgroup.second->clear_pending_subscriptions();
}
}
}
@@ -4578,7 +3702,7 @@ void routing_manager_impl::clear_remote_subscriber(service_t _service,
void routing_manager_impl::call_sd_endpoint_connected(
const boost::system::error_code& _error,
service_t _service, instance_t _instance,
- std::shared_ptr<endpoint> _endpoint,
+ const std::shared_ptr<endpoint>& _endpoint,
std::shared_ptr<boost::asio::steady_timer> _timer) {
(void)_timer;
if (_error) {
@@ -4604,14 +3728,20 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
if (its_local_client == host_->get_client()) {
// received subscription for event of a service instance hosted by
// application acting as rm_impl register with own client id and shadow = false
- register_event(host_->get_client(), _service, _instance, _event,
- its_eventgroups, true, std::chrono::milliseconds::zero(), false,
+ register_event(host_->get_client(),
+ _service, _instance,
+ _event,
+ its_eventgroups, event_type_e::ET_UNKNOWN, reliability_type_e::RT_UNKNOWN,
+ std::chrono::milliseconds::zero(), false, true,
nullptr, false, false, true);
} else if (its_local_client != VSOMEIP_ROUTING_CLIENT) {
// received subscription for event of a service instance hosted on
// this node register with client id of local_client and set shadow to true
- register_event(its_local_client, _service, _instance, _event,
- its_eventgroups, true, std::chrono::milliseconds::zero(), false,
+ register_event(its_local_client,
+ _service, _instance,
+ _event, its_eventgroups, event_type_e::ET_UNKNOWN,
+ reliability_type_e::RT_UNKNOWN,
+ std::chrono::milliseconds::zero(), false, true,
nullptr, false, true, true);
} else {
// received subscription for event of a unknown or remote service instance
@@ -4620,9 +3750,12 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
if (its_info && !its_info->is_local()) {
// remote service, register shadow event with client ID of subscriber
// which should have called register_event
- register_event(_client, _service, _instance, _event,
- its_eventgroups, true, std::chrono::milliseconds::zero(),
- false, nullptr, false, true, true);
+ register_event(_client,
+ _service, _instance,
+ _event, its_eventgroups, event_type_e::ET_UNKNOWN,
+ reliability_type_e::RT_UNKNOWN,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, false, true, true);
} else {
VSOMEIP_WARNING
<< "routing_manager_impl::create_placeholder_event_and_subscribe("
@@ -4642,126 +3775,84 @@ bool routing_manager_impl::create_placeholder_event_and_subscribe(
return is_inserted;
}
-void routing_manager_impl::handle_subscription_state(client_t _client, service_t _service, instance_t _instance,
+void routing_manager_impl::handle_subscription_state(
+ client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event) {
+#if 0
+ VSOMEIP_ERROR << "routing_manager_impl::" << __func__
+ << "(" << std::hex << _client << "): "
+ << "event="
+ << std::hex << _service << "."
+ << std::hex << _instance << "."
+ << std::hex << _eventgroup << "."
+ << std::hex << _event
+ << " me="
+ << std::hex << get_client();
+#endif
+ // Note: remote_subscription_state_mutex_ is already locked as this
+ // method builds a critical section together with insert_subscription
+ // from routing_manager_base.
+ // Todo: Improve this situation...
+ auto its_event = find_event(_service, _instance, _event);
+ client_t its_client(VSOMEIP_ROUTING_CLIENT);
+ if (its_event &&
+ its_event->get_type() == event_type_e::ET_SELECTIVE_EVENT) {
+ its_client = _client;
+ }
- client_t subscriber = is_specific_endpoint_client(_client, _service, _instance);
- auto its_tuple = std::make_tuple(_service, _instance, _eventgroup, subscriber);
-
- std::lock_guard<std::mutex> its_lock(remote_subscription_state_mutex_);
+ auto its_tuple
+ = std::make_tuple(_service, _instance, _eventgroup, its_client);
auto its_state = remote_subscription_state_.find(its_tuple);
if (its_state != remote_subscription_state_.end()) {
+#if 0
+ VSOMEIP_ERROR << "routing_manager_impl::" << __func__
+ << "(" << std::hex << _client << "): "
+ << "event="
+ << std::hex << _service << "."
+ << std::hex << _instance << "."
+ << std::hex << _eventgroup << "."
+ << std::hex << _event
+ << " state=" << std::hex << (int)its_state->second
+ << " me="
+ << std::hex << get_client();
+#endif
if (its_state->second == subscription_state_e::SUBSCRIPTION_ACKNOWLEDGED) {
// Subscription already acknowledged!
if (_client == get_client()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
} else {
stub_->send_subscribe_ack(_client, _service, _instance, _eventgroup, _event);
}
}
- } else {
- remote_subscription_state_[its_tuple] = subscription_state_e::IS_SUBSCRIBING;
}
}
-client_t routing_manager_impl::is_specific_endpoint_client(client_t _client,
- service_t _service, instance_t _instance) {
- client_t result = VSOMEIP_ROUTING_CLIENT;
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if (found_service != specific_endpoint_clients_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_client = found_instance->second.find(_client);
- if(found_client != found_instance->second.end()) {
- result = _client;
- }
- }
- }
- }
- // A client_t != VSOMEIP_ROUTING_CLIENT implies true
- return result;
-}
-
-std::unordered_set<client_t> routing_manager_impl::get_specific_endpoint_clients(
- service_t _service, instance_t _instance) {
- std::unordered_set<client_t> result;
- {
- std::lock_guard<std::mutex> its_lock(specific_endpoint_clients_mutex_);
- auto found_service = specific_endpoint_clients_.find(_service);
- if (found_service != specific_endpoint_clients_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- result = found_instance->second;
- }
- }
- }
- return result;
-}
-
-void routing_manager_impl::send_initial_events(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<endpoint_definition> &_subscriber) {
- std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service,
- _instance, _eventgroup);
- if (!its_eventgroup) {
- return;
- }
- bool is_offered_both(false);
- if (configuration_->get_reliable_port(_service, _instance) != ILLEGAL_PORT &&
- configuration_->get_unreliable_port(_service, _instance) != ILLEGAL_PORT) {
- is_offered_both = true;
- }
- // send initial events if we already have a cached field (is_set)
- for (const auto &its_event : its_eventgroup->get_events()) {
- if (its_event->is_field()) {
- if (its_event->is_set()) {
- if (!is_offered_both) {
- its_event->notify_one(_subscriber, true);
- } else {
- if (its_event->is_reliable() && _subscriber->is_reliable()) {
- its_event->notify_one(_subscriber, true);
- }
- if (!its_event->is_reliable() && !_subscriber->is_reliable()) {
- its_event->notify_one(_subscriber, true);
- }
- }
- } else {
- // received a subscription but can't notify due to missing payload
- its_event->set_remote_notification_pending(true);
- }
- }
- }
-}
-
-void routing_manager_impl::register_offer_acceptance_handler(
- vsomeip::offer_acceptance_handler_t _handler) const {
+void routing_manager_impl::register_sd_acceptance_handler(
+ const sd_acceptance_handler_t& _handler) const {
if (discovery_) {
- discovery_->register_offer_acceptance_handler(_handler);
+ discovery_->register_sd_acceptance_handler(_handler);
}
}
void routing_manager_impl::register_reboot_notification_handler(
- vsomeip::reboot_notification_handler_t _handler) const {
+ const reboot_notification_handler_t& _handler) const {
if (discovery_) {
discovery_->register_reboot_notification_handler(_handler);
}
}
void routing_manager_impl::register_routing_ready_handler(
- routing_ready_handler_t _handler) {
+ const routing_ready_handler_t& _handler) {
routing_ready_handler_ = _handler;
}
void routing_manager_impl::register_routing_state_handler(
- routing_state_handler_t _handler) {
+ const routing_state_handler_t& _handler) {
routing_state_handler_ = _handler;
}
-void routing_manager_impl::offer_acceptance_enabled(
- boost::asio::ip::address _address) {
+void routing_manager_impl::sd_acceptance_enabled(
+ const boost::asio::ip::address& _address) {
boost::system::error_code ec;
VSOMEIP_INFO << "ipsec-plugin-mgu: expire subscriptions and services: "
<< _address.to_string(ec);
@@ -4775,7 +3866,7 @@ void routing_manager_impl::memory_log_timer_cbk(
return;
}
#ifndef _WIN32
- static const std::uint32_t its_pagesize = getpagesize() / 1024;
+ static const std::uint32_t its_pagesize = static_cast<std::uint32_t>(getpagesize() / 1024);
#else
static const std::uint32_t its_pagesize = 4096 / 1024;
#endif
@@ -4836,75 +3927,7 @@ void routing_manager_impl::status_log_timer_cbk(
return;
}
- // local client endpoints
- {
- std::map<client_t, std::shared_ptr<endpoint>> lces = get_local_endpoints();
- VSOMEIP_INFO << "status local client endpoints: " << std::dec << lces.size();
- for (const auto lce : lces) {
- lce.second->print_status();
- }
- }
-
- // udp and tcp client endpoints
- {
- client_endpoints_by_ip_t client_endpoints_by_ip;
- remote_services_t remote_services;
- server_endpoints_t server_endpoints;
- {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- client_endpoints_by_ip = client_endpoints_by_ip_;
- remote_services = remote_services_;
- server_endpoints = server_endpoints_;
- }
- VSOMEIP_INFO << "status start remote client endpoints:";
- std::uint32_t num_remote_client_endpoints(0);
- // normal endpoints
- for (const auto &a : client_endpoints_by_ip) {
- for (const auto p : a.second) {
- for (const auto ru : p.second) {
- ru.second->print_status();
- num_remote_client_endpoints++;
- }
- }
- }
- VSOMEIP_INFO << "status end remote client endpoints: " << std::dec
- << num_remote_client_endpoints;
-
- // selective client endpoints
- VSOMEIP_INFO << "status start selective remote client endpoints:";
- std::uint32_t num_remote_selectiv_client_endpoints(0);
- for (const auto s : remote_services) {
- for (const auto i : s.second) {
- for (const auto c : i.second) {
- if (c.first != VSOMEIP_ROUTING_CLIENT) {
- for (const auto ur : c.second) {
- ur.second->print_status();
- num_remote_selectiv_client_endpoints++;
- }
- }
- }
- }
- }
- VSOMEIP_INFO << "status end selective remote client endpoints: "
- << std::dec << num_remote_selectiv_client_endpoints;
-
- VSOMEIP_INFO << "status start server endpoints:";
- std::uint32_t num_server_endpoints(1);
- // local server endpoints
- stub_->print_endpoint_status();
-
- // server endpoints
- for (const auto p : server_endpoints) {
- for (const auto ru : p.second ) {
- ru.second->print_status();
- num_server_endpoints++;
- }
- }
- VSOMEIP_INFO << "status end server endpoints:"
- << std::dec << num_server_endpoints;
- }
-
-
+ ep_mgr_impl_->print_status();
{
std::lock_guard<std::mutex> its_lock(status_log_timer_mutex_);
boost::system::error_code ec;
@@ -4916,138 +3939,107 @@ void routing_manager_impl::status_log_timer_cbk(
}
}
-void routing_manager_impl::on_unsubscribe_ack(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _unsubscription_id) {
- std::shared_ptr<eventgroupinfo> its_eventgroup = find_eventgroup(_service,
- _instance, _eventgroup);
- if (!its_eventgroup) {
- VSOMEIP_ERROR << __func__ << ": Received UNSUBSCRIBE_ACK for unknown "
- << "eventgroup: ("
- << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- return;
- }
- // there will only be one or zero subscriptions returned here
- std::vector<pending_subscription_t> its_pending_subscriptions =
- its_eventgroup->remove_pending_subscription(_unsubscription_id);
- for (const pending_subscription_t& its_sd_message_id : its_pending_subscriptions) {
- if (its_sd_message_id.pending_subscription_id_ == _unsubscription_id) {
- its_eventgroup->remove_target(its_sd_message_id.target_);
- clear_remote_subscriber(_service, _instance,
- its_sd_message_id.subscribing_client_,
- its_sd_message_id.target_);
- if (its_eventgroup->get_targets().size() == 0) {
- for (auto e : its_eventgroup->get_events()) {
- if (e->is_shadow()) {
- e->unset_payload();
+void
+routing_manager_impl::on_unsubscribe_ack(client_t _client,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ remote_subscription_id_t _id) {
+ std::shared_ptr<eventgroupinfo> its_info
+ = find_eventgroup(_service, _instance, _eventgroup);
+ if (its_info) {
+ const auto its_subscription = its_info->get_remote_subscription(_id);
+ if (its_subscription) {
+ its_info->remove_remote_subscription(_id);
+
+ std::lock_guard<std::mutex> its_lock(remote_subscribers_mutex_);
+ remote_subscribers_[_service][_instance].erase(_client);
+
+ if (its_info->get_remote_subscriptions().size() == 0) {
+ for (const auto &its_event : its_info->get_events()) {
+ bool has_remote_subscriber(false);
+ for (const auto &its_eventgroup : its_event->get_eventgroups()) {
+ const auto its_eventgroup_info
+ = find_eventgroup(_service, _instance, its_eventgroup);
+ if (its_eventgroup_info
+ && its_eventgroup_info->get_remote_subscriptions().size() > 0) {
+ has_remote_subscriber = true;
+ }
+ }
+
+ if (!has_remote_subscriber && its_event->is_shadow()) {
+ its_event->unset_payload();
}
}
}
} else {
- const pending_subscription_id_t its_subscription_id =
- its_sd_message_id.pending_subscription_id_;
- const client_t its_subscribing_client = its_sd_message_id.subscribing_client_;
- const client_t its_offering_client = find_local_client(_service, _instance);
- send_subscription(its_offering_client, its_subscribing_client, _service,
- _instance, _eventgroup, its_eventgroup->get_major(),
- its_subscription_id);
+ VSOMEIP_ERROR << __func__
+ << ": Unknown StopSubscribe " << std::dec << _id << " for eventgroup ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
+ } else {
+ VSOMEIP_ERROR << __func__
+ << ": Received StopSubscribe for unknown eventgroup: ("
+ << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
}
}
-void routing_manager_impl::send_unsubscription(
- client_t _offering_client, client_t _subscribing_client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _pending_unsubscription_id) {
+void routing_manager_impl::on_connect(const std::shared_ptr<endpoint>& _endpoint) {
+ (void)_endpoint;
+}
+void routing_manager_impl::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) {
+ (void)_endpoint;
+}
+void routing_manager_impl::send_subscription(
+ const client_t _offering_client,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup, const major_version_t _major,
+ const std::set<client_t> &_clients,
+ const remote_subscription_id_t _id) {
if (host_->get_client() == _offering_client) {
auto self = shared_from_this();
- host_->on_subscription(_service, _instance, _eventgroup,
- _subscribing_client, false,
- [this, self, _service, _instance, _eventgroup,
- _subscribing_client, _pending_unsubscription_id, _offering_client]
- (const bool _subscription_accepted) {
- (void)_subscription_accepted;
+ for (const auto its_client : _clients) {
+ host_->on_subscription(_service, _instance, _eventgroup, its_client, own_uid_, own_gid_, true,
+ [this, self, _service, _instance, _eventgroup, its_client, _id]
+ (const bool _is_accepted) {
try {
- const auto its_callback = std::bind(
- &routing_manager_stub_host::on_unsubscribe_ack,
- std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
- _offering_client, _service, _instance,
- _eventgroup, _pending_unsubscription_id);
- io_.post(its_callback);
+ if (!_is_accepted) {
+ const auto its_callback = std::bind(
+ &routing_manager_stub_host::on_subscribe_nack,
+ std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
+ its_client, _service, _instance,
+ _eventgroup, ANY_EVENT, _id);
+ io_.post(its_callback);
+ } else {
+ const auto its_callback = std::bind(
+ &routing_manager_stub_host::on_subscribe_ack,
+ std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
+ its_client, _service, _instance,
+ _eventgroup, ANY_EVENT, _id);
+ io_.post(its_callback);
+ }
} catch (const std::exception &e) {
VSOMEIP_ERROR << __func__ << e.what();
}
- }
- );
- } else {
- if (!stub_->send_unsubscribe(find_local(_offering_client),
- _subscribing_client,
- _service, _instance, _eventgroup, ANY_EVENT,
- _pending_unsubscription_id)) {
- try {
- const auto its_callback = std::bind(
- &routing_manager_stub_host::on_unsubscribe_ack,
- std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
- _offering_client, _service, _instance,
- _eventgroup, _pending_unsubscription_id);
- io_.post(its_callback);
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << __func__ << e.what();
- }
+ });
}
- }
-}
-
-void routing_manager_impl::send_subscription(
- client_t _offering_client, client_t _subscribing_client,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- major_version_t _major,
- pending_subscription_id_t _pending_subscription_id) {
- if (host_->get_client() == _offering_client) {
- auto self = shared_from_this();
- host_->on_subscription(_service, _instance, _eventgroup,
- _subscribing_client, true,
- [this, self, _service, _instance,
- _eventgroup, _subscribing_client, _pending_subscription_id]
- (const bool _subscription_accepted) {
- try {
- if (!_subscription_accepted) {
+ } else { // service hosted by local client
+ for (const auto its_client : _clients) {
+ if (!stub_->send_subscribe(find_local(_offering_client), its_client,
+ _service, _instance, _eventgroup, _major, ANY_EVENT, _id)) {
+ try {
const auto its_callback = std::bind(
&routing_manager_stub_host::on_subscribe_nack,
std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
- _subscribing_client, _service, _instance,
- _eventgroup, ANY_EVENT, _pending_subscription_id);
- io_.post(its_callback);
- } else {
- const auto its_callback = std::bind(
- &routing_manager_stub_host::on_subscribe_ack,
- std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
- _subscribing_client, _service, _instance,
- _eventgroup, ANY_EVENT, _pending_subscription_id);
+ its_client, _service, _instance, _eventgroup,
+ ANY_EVENT, _id);
io_.post(its_callback);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__ << e.what();
}
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << __func__ << e.what();
- }
- });
- } else { // service hosted by local client
- if (!stub_->send_subscribe(find_local(_offering_client),
- _subscribing_client,
- _service, _instance, _eventgroup,
- _major, ANY_EVENT,
- _pending_subscription_id)) {
- try {
- const auto its_callback = std::bind(
- &routing_manager_stub_host::on_subscribe_nack,
- std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
- _subscribing_client, _service, _instance,
- _eventgroup, ANY_EVENT, _pending_subscription_id);
- io_.post(its_callback);
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << __func__ << e.what();
}
}
}
@@ -5056,31 +4048,15 @@ void routing_manager_impl::send_subscription(
void routing_manager_impl::cleanup_server_endpoint(
service_t _service, const std::shared_ptr<endpoint>& _endpoint) {
if (_endpoint) {
- std::lock_guard<std::recursive_mutex> its_lock(endpoint_mutex_);
- bool reliable = _endpoint->is_reliable();
- // Check whether any service still uses this endpoint
- _endpoint->decrement_use_count();
- bool isLastService = (_endpoint->get_use_count() == 0);
-
- // Clear service_instances_
- if (1 >= service_instances_[_service].size()) {
- service_instances_.erase(_service);
- } else {
- service_instances_[_service].erase(_endpoint.get());
- }
-
- // Clear server endpoint if no service remains using it
- if (isLastService) {
- const uint16_t port = _endpoint->get_local_port();
- if (server_endpoints_.find(port) != server_endpoints_.end()) {
- server_endpoints_[port].erase(reliable);
- if (server_endpoints_[port].find(!reliable) == server_endpoints_[port].end()) {
- server_endpoints_.erase(port);
- }
+ // Clear service_instances_, check whether any service still
+ // uses this endpoint and clear server endpoint if no service
+ // remains using it
+ if (ep_mgr_impl_->remove_instance(_service, _endpoint.get())) {
+ if (ep_mgr_impl_->remove_server_endpoint(
+ _endpoint->get_local_port(), _endpoint->is_reliable())) {
+ // Stop endpoint (close socket) to release its async_handlers!
+ _endpoint->stop();
}
-
- // Stop endpoint (close socket) to release its async_handlers!
- _endpoint->stop();
}
}
}
@@ -5182,16 +4158,18 @@ void routing_manager_impl::on_security_update_timeout(
bool routing_manager_impl::update_security_policy_configuration(
uint32_t _uid, uint32_t _gid,
- ::std::shared_ptr<policy> _policy, std::shared_ptr<payload> _payload, security_update_handler_t _handler) {
+ const std::shared_ptr<policy>& _policy,
+ const std::shared_ptr<payload>& _payload,
+ const security_update_handler_t& _handler) {
bool ret(true);
// cache security policy payload for later distribution to new registering clients
stub_->policy_cache_add(_uid, _payload);
// update security policy from configuration
- configuration_->update_security_policy(_uid, _gid, _policy);
+ security::get()->update_security_policy(_uid, _gid, _policy);
// determine currently connected clients
- std::unordered_set<client_t> its_clients_to_inform = get_connected_clients();
+ std::unordered_set<client_t> its_clients_to_inform = ep_mgr_impl_->get_connected_clients();
// add handler
pending_security_update_id_t its_id;
@@ -5254,13 +4232,13 @@ bool routing_manager_impl::update_security_policy_configuration(
}
bool routing_manager_impl::remove_security_policy_configuration(
- uint32_t _uid, uint32_t _gid, security_update_handler_t _handler) {
+ uint32_t _uid, uint32_t _gid, const security_update_handler_t& _handler) {
bool ret(true);
// remove security policy from configuration (only if there was a updateACL call before)
if (stub_->is_policy_cached(_uid)) {
- if (!configuration_->remove_security_policy(_uid, _gid)) {
- _handler(vsomeip::security_update_state_e::SU_UNKNOWN_USER_ID);
+ if (!security::get()->remove_security_policy(_uid, _gid)) {
+ _handler(security_update_state_e::SU_UNKNOWN_USER_ID);
ret = false;
} else {
// remove policy from cache to prevent sending it to registering clients
@@ -5270,7 +4248,7 @@ bool routing_manager_impl::remove_security_policy_configuration(
pending_security_update_id_t its_id;
// determine currently connected clients
- std::unordered_set<client_t> its_clients_to_inform = get_connected_clients();
+ std::unordered_set<client_t> its_clients_to_inform = ep_mgr_impl_->get_connected_clients();
if (!its_clients_to_inform.empty()) {
its_id = pending_security_update_add(its_clients_to_inform);
@@ -5330,14 +4308,14 @@ bool routing_manager_impl::remove_security_policy_configuration(
}
}
else {
- _handler(vsomeip::security_update_state_e::SU_UNKNOWN_USER_ID);
+ _handler(security_update_state_e::SU_UNKNOWN_USER_ID);
ret = false;
}
return ret;
}
pending_security_update_id_t routing_manager_impl::pending_security_update_add(
- std::unordered_set<client_t> _clients) {
+ const std::unordered_set<client_t>& _clients) {
std::lock_guard<std::mutex> its_lock(pending_security_updates_mutex_);
if (++pending_security_update_id_ == 0) {
pending_security_update_id_++;
@@ -5423,4 +4401,96 @@ void routing_manager_impl::on_security_update_response(
}
}
-} // namespace vsomeip
+void routing_manager_impl::print_stub_status() const {
+ stub_->print_endpoint_status();
+}
+
+void routing_manager_impl::service_endpoint_connected(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor, const std::shared_ptr<endpoint>& _endpoint,
+ bool _unreliable_only) {
+
+ if (!_unreliable_only) {
+ // Mark only TCP-only and TCP+UDP services available here
+ // UDP-only services are already marked as available in add_routing_info
+ on_availability(_service, _instance, true, _major, _minor);
+ stub_->on_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ _major, _minor);
+ }
+
+ std::shared_ptr<boost::asio::steady_timer> its_timer =
+ std::make_shared<boost::asio::steady_timer>(io_);
+ boost::system::error_code ec;
+ its_timer->expires_from_now(std::chrono::milliseconds(3), ec);
+ if (!ec) {
+ its_timer->async_wait(
+ std::bind(&routing_manager_impl::call_sd_endpoint_connected,
+ std::static_pointer_cast<routing_manager_impl>(
+ shared_from_this()), std::placeholders::_1,
+ _service, _instance, _endpoint, its_timer));
+ } else {
+ VSOMEIP_ERROR << __func__ << " " << ec.message();
+ }
+}
+
+void routing_manager_impl::service_endpoint_disconnected(
+ service_t _service, instance_t _instance, major_version_t _major,
+ minor_version_t _minor, const std::shared_ptr<endpoint>& _endpoint) {
+ (void)_endpoint;
+ on_availability(_service, _instance, false, _major, _minor);
+ stub_->on_stop_offer_service(VSOMEIP_ROUTING_CLIENT, _service, _instance,
+ _major, _minor);
+ VSOMEIP_WARNING << __func__ << ": lost connection to remote service: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "]";
+}
+
+void
+routing_manager_impl::send_unsubscription(client_t _offering_client,
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ const std::set<client_t> &_removed,
+ remote_subscription_id_t _id) {
+
+ (void)_major; // TODO: Remove completely?
+
+ if (host_->get_client() == _offering_client) {
+ auto self = shared_from_this();
+ for (const auto its_client : _removed) {
+ host_->on_subscription(_service, _instance,
+ _eventgroup, its_client, own_uid_, own_gid_, false,
+ [this, self, _service, _instance, _eventgroup,
+ its_client, _id, _offering_client]
+ (const bool _is_accepted) {
+ (void)_is_accepted;
+ try {
+ const auto its_callback = std::bind(
+ &routing_manager_stub_host::on_unsubscribe_ack,
+ std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
+ its_client, _service, _instance, _eventgroup, _id);
+ io_.post(its_callback);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__ << e.what();
+ }
+ }
+ );
+ }
+ } else {
+ for (const auto its_client : _removed) {
+ if (!stub_->send_unsubscribe(find_local(_offering_client), its_client,
+ _service, _instance, _eventgroup, ANY_EVENT, _id)) {
+ try {
+ const auto its_callback = std::bind(
+ &routing_manager_stub_host::on_unsubscribe_ack,
+ std::dynamic_pointer_cast<routing_manager_stub_host>(shared_from_this()),
+ its_client, _service, _instance, _eventgroup, _id);
+ io_.post(its_callback);
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << __func__ << e.what();
+ }
+ }
+ }
+ }
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_proxy.cpp b/implementation/routing/src/routing_manager_proxy.cpp
index d439654..8135c3f 100644
--- a/implementation/routing/src/routing_manager_proxy.cpp
+++ b/implementation/routing/src/routing_manager_proxy.cpp
@@ -12,26 +12,28 @@
#include <vsomeip/constants.hpp>
#include <vsomeip/runtime.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/event.hpp"
#include "../include/routing_manager_host.hpp"
#include "../include/routing_manager_proxy.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
+#include "../../security/include/policy.hpp"
+#include "../../security/include/security_impl.hpp"
+
#include "../../endpoints/include/local_client_endpoint_impl.hpp"
#include "../../endpoints/include/local_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../message/include/deserializer.hpp"
+#include "../../message/include/message_impl.hpp"
#include "../../message/include/serializer.hpp"
#include "../../service_discovery/include/runtime.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
-#include "../../configuration/include/policy.hpp"
#ifdef USE_DLT
#include "../../tracing/include/connector_impl.hpp"
#endif
-namespace vsomeip {
+namespace vsomeip_v3 {
routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host,
bool _client_side_logging,
@@ -40,8 +42,8 @@ routing_manager_proxy::routing_manager_proxy(routing_manager_host *_host,
is_connected_(false),
is_started_(false),
state_(inner_state_type_e::ST_DEREGISTERED),
- sender_(0),
- receiver_(0),
+ sender_(nullptr),
+ receiver_(nullptr),
register_application_timer_(io_),
logger_(logger::get()),
request_debounce_timer_ (io_),
@@ -55,31 +57,20 @@ routing_manager_proxy::~routing_manager_proxy() {
}
void routing_manager_proxy::init() {
- routing_manager_base::init();
+ routing_manager_base::init(std::make_shared<endpoint_manager_base>(this, io_, configuration_));
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
- sender_ = create_local(VSOMEIP_ROUTING_CLIENT);
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
}
-
- init_receiver();
}
void routing_manager_proxy::start() {
is_started_ = true;
-
- if (!receiver_) {
- // application has been stopped and started again
- init_receiver();
- }
- if (receiver_) {
- receiver_->start();
- }
-
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (!sender_) {
// application has been stopped and started again
- sender_ = create_local(VSOMEIP_ROUTING_CLIENT);
+ sender_ = ep_mgr_->create_local(VSOMEIP_ROUTING_CLIENT);
}
if (sender_) {
sender_->start();
@@ -135,7 +126,7 @@ void routing_manager_proxy::stop() {
sender_ = nullptr;
}
- for (auto client: get_connected_clients()) {
+ for (auto client: ep_mgr_->get_connected_clients()) {
if (client != VSOMEIP_ROUTING_CLIENT) {
remove_local(client, true);
}
@@ -153,12 +144,14 @@ void routing_manager_proxy::stop() {
#endif
}
-const std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const {
+std::shared_ptr<configuration> routing_manager_proxy::get_configuration() const {
return host_->get_configuration();
}
-bool routing_manager_proxy::offer_service(client_t _client, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
+bool routing_manager_proxy::offer_service(client_t _client,
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+
if(!routing_manager_base::offer_service(_client, _service, _instance, _major, _minor)) {
VSOMEIP_WARNING << "routing_manager_proxy::offer_service,"
<< "routing_manager_base::offer_service returned false";
@@ -168,15 +161,15 @@ bool routing_manager_proxy::offer_service(client_t _client, service_t _service,
if (state_ == inner_state_type_e::ST_REGISTERED) {
send_offer_service(_client, _service, _instance, _major, _minor);
}
- service_data_t offer = { _service, _instance, _major, _minor, false };
+ service_data_t offer = { _service, _instance, _major, _minor };
pending_offers_.insert(offer);
}
return true;
}
void routing_manager_proxy::send_offer_service(client_t _client,
- service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor) {
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
(void)_client;
byte_t its_command[VSOMEIP_OFFER_SERVICE_COMMAND_SIZE];
@@ -207,6 +200,7 @@ void routing_manager_proxy::send_offer_service(client_t _client,
void routing_manager_proxy::stop_offer_service(client_t _client,
service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor) {
+
(void)_client;
routing_manager_base::stop_offer_service(_client, _service, _instance, _major, _minor);
@@ -256,14 +250,14 @@ void routing_manager_proxy::stop_offer_service(client_t _client,
}
void routing_manager_proxy::request_service(client_t _client,
- service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy) {
- routing_manager_base::request_service(_client, _service, _instance, _major,
- _minor, _use_exclusive_proxy);
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) {
+ routing_manager_base::request_service(_client,
+ _service, _instance, _major, _minor);
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
size_t request_debouncing_time = configuration_->get_request_debouncing(host_->get_name());
- service_data_t request = { _service, _instance, _major, _minor, _use_exclusive_proxy };
+ service_data_t request = { _service, _instance, _major, _minor };
if (!request_debouncing_time) {
if (state_ == inner_state_type_e::ST_REGISTERED) {
std::set<service_data_t> requests;
@@ -325,10 +319,11 @@ void routing_manager_proxy::release_service(client_t _client,
void routing_manager_proxy::register_event(client_t _client,
service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, const event_type_e _type,
+ reliability_type_e _reliability,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
- epsilon_change_func_t _epsilon_change_func,
+ bool _update_on_change, epsilon_change_func_t _epsilon_change_func,
bool _is_provided, bool _is_shadow, bool _is_cache_placeholder) {
(void)_is_shadow;
(void)_is_cache_placeholder;
@@ -336,8 +331,9 @@ void routing_manager_proxy::register_event(client_t _client,
const event_data_t registration = {
_service,
_instance,
- _event,
- _is_field,
+ _notifier,
+ _type,
+ _reliability,
_is_provided,
_eventgroups
};
@@ -351,36 +347,29 @@ void routing_manager_proxy::register_event(client_t _client,
}
}
if (is_first || _is_provided) {
- routing_manager_base::register_event(_client, _service, _instance,
- _event,_eventgroups, _is_field,
- _cycle, _change_resets_cycle,
- _epsilon_change_func,
- _is_provided);
+ routing_manager_base::register_event(_client,
+ _service, _instance,
+ _notifier,
+ _eventgroups, _type, _reliability,
+ _cycle, _change_resets_cycle, _update_on_change,
+ _epsilon_change_func,
+ _is_provided);
}
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED && is_first) {
send_register_event(client_, _service, _instance,
- _event, _eventgroups, _is_field, _is_provided);
+ _notifier, _eventgroups, _type, _reliability, _is_provided);
}
}
-
- if(_is_provided) {
- VSOMEIP_INFO << "REGISTER EVENT("
- << std::hex << std::setw(4) << std::setfill('0') << _client << "): ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _event
- << ":is_provider=" << _is_provided << "]";
- }
}
void routing_manager_proxy::unregister_event(client_t _client,
- service_t _service, instance_t _instance, event_t _event,
+ service_t _service, instance_t _instance, event_t _notifier,
bool _is_provided) {
routing_manager_base::unregister_event(_client, _service, _instance,
- _event, _is_provided);
+ _notifier, _is_provided);
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
@@ -398,8 +387,8 @@ void routing_manager_proxy::unregister_event(client_t _client,
sizeof(_service));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event,
- sizeof(_event));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_notifier,
+ sizeof(_notifier));
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
= static_cast<byte_t>(_is_provided);
@@ -414,7 +403,7 @@ void routing_manager_proxy::unregister_event(client_t _client,
while (it != pending_event_registrations_.end()) {
if (it->service_ == _service
&& it->instance_ == _instance
- && it->event_ == _event) {
+ && it->notifier_ == _notifier) {
break;
}
it++;
@@ -433,12 +422,15 @@ bool routing_manager_proxy::is_field(service_t _service, instance_t _instance,
return false;
}
-void routing_manager_proxy::subscribe(client_t _client, service_t _service,
+void routing_manager_proxy::subscribe(client_t _client, uid_t _uid, gid_t _gid, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, subscription_type_e _subscription_type) {
+ event_t _event) {
+ (void)_uid;
+ (void)_gid;
{
+ credentials_t its_credentials = std::make_pair(own_uid_, own_gid_);
if (_event == ANY_EVENT) {
- if (!is_subscribe_to_any_event_allowed(_client, _service, _instance, _eventgroup)) {
+ if (!is_subscribe_to_any_event_allowed(its_credentials, _client, _service, _instance, _eventgroup)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
<< " : routing_manager_proxy::subscribe: "
<< " isn't allowed to subscribe to service/instance/event "
@@ -447,8 +439,11 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service,
return;
}
} else {
- if (!configuration_->is_client_allowed(_client, _service,
- _instance, _event)) {
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
+ if (!its_security->is_client_allowed(own_uid_, own_gid_,
+ _client, _service, _instance, _event)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
<< " : routing_manager_proxy::subscribe: "
<< " isn't allowed to subscribe to service/instance/event "
@@ -460,18 +455,16 @@ void routing_manager_proxy::subscribe(client_t _client, service_t _service,
std::lock_guard<std::mutex> its_lock(state_mutex_);
if (state_ == inner_state_type_e::ST_REGISTERED && is_available(_service, _instance, _major)) {
- send_subscribe(_client, _service, _instance, _eventgroup, _major,
- _event, _subscription_type);
+ send_subscribe(_client, _service, _instance, _eventgroup, _major, _event );
}
- subscription_data_t subscription = { _service, _instance, _eventgroup, _major,
- _event, _subscription_type};
+ subscription_data_t subscription = { _service, _instance, _eventgroup, _major, _event, _uid, _gid};
pending_subscriptions_.insert(subscription);
}
}
void routing_manager_proxy::send_subscribe(client_t _client, service_t _service,
instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, subscription_type_e _subscription_type) {
+ event_t _event) {
(void)_client;
byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE];
@@ -492,14 +485,12 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service,
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major;
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_event,
sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_subscription_type,
- sizeof(_subscription_type));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &DEFAULT_SUBSCRIPTION,
- sizeof(DEFAULT_SUBSCRIPTION)); // local subscription
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
+ &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
client_t target_client = find_local_client(_service, _instance);
if (target_client != VSOMEIP_ROUTING_CLIENT) {
- auto its_target = find_or_create_local(target_client);
+ auto its_target = ep_mgr_->find_or_create_local(target_client);
its_target->send(its_command, sizeof(its_command));
} else {
std::lock_guard<std::mutex> its_lock(sender_mutex_);
@@ -511,7 +502,7 @@ void routing_manager_proxy::send_subscribe(client_t _client, service_t _service,
void routing_manager_proxy::send_subscribe_nack(client_t _subscriber,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) {
+ event_t _event, remote_subscription_id_t _id) {
byte_t its_command[VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE];
uint32_t its_size = VSOMEIP_SUBSCRIBE_NACK_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE;
@@ -532,12 +523,12 @@ void routing_manager_proxy::send_subscribe_nack(client_t _subscriber,
sizeof(_subscriber));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &_subscription_id, sizeof(_subscription_id));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id,
+ sizeof(_id));
if (_subscriber != VSOMEIP_ROUTING_CLIENT
- && _subscription_id == DEFAULT_SUBSCRIPTION) {
- auto its_target = find_local(_subscriber);
+ && _id == PENDING_SUBSCRIPTION_ID) {
+ auto its_target = ep_mgr_->find_local(_subscriber);
if (its_target) {
its_target->send(its_command, sizeof(its_command));
return;
@@ -553,7 +544,7 @@ void routing_manager_proxy::send_subscribe_nack(client_t _subscriber,
void routing_manager_proxy::send_subscribe_ack(client_t _subscriber,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) {
+ event_t _event, remote_subscription_id_t _id) {
byte_t its_command[VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE];
uint32_t its_size = VSOMEIP_SUBSCRIBE_ACK_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE;
@@ -574,12 +565,12 @@ void routing_manager_proxy::send_subscribe_ack(client_t _subscriber,
sizeof(_subscriber));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &_subscription_id, sizeof(_subscription_id));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10], &_id,
+ sizeof(_id));
if (_subscriber != VSOMEIP_ROUTING_CLIENT
- && _subscription_id == DEFAULT_SUBSCRIPTION) {
- auto its_target = find_local(_subscriber);
+ && _id == PENDING_SUBSCRIPTION_ID) {
+ auto its_target = ep_mgr_->find_local(_subscriber);
if (its_target) {
its_target->send(its_command, sizeof(its_command));
return;
@@ -593,9 +584,11 @@ void routing_manager_proxy::send_subscribe_ack(client_t _subscriber,
}
}
-void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+void routing_manager_proxy::unsubscribe(client_t _client, uid_t _uid, gid_t _gid,
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
(void)_client;
+ (void)_uid;
+ (void)_gid;
{
std::lock_guard<std::mutex> its_lock(state_mutex_);
remove_pending_subscription(_service, _instance, _eventgroup, _event);
@@ -618,10 +611,10 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
sizeof(_eventgroup));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &DEFAULT_SUBSCRIPTION,
- sizeof(DEFAULT_SUBSCRIPTION)); // is_local
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
- auto its_target = find_local(_service, _instance);
+ auto its_target = ep_mgr_->find_local(_service, _instance);
if (its_target) {
its_target->send(its_command, sizeof(its_command));
} else {
@@ -636,13 +629,14 @@ void routing_manager_proxy::unsubscribe(client_t _client, service_t _service,
bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
length_t _size, instance_t _instance,
- bool _flush,
bool _reliable,
client_t _bound_client,
- bool _is_valid_crc,
+ credentials_t _credentials,
+ uint8_t _status_check,
bool _sent_from_remote) {
(void)_client;
(void)_bound_client;
+ (void)_credentials;
(void)_sent_from_remote;
bool is_sent(false);
bool has_remote_subscribers(false);
@@ -695,7 +689,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
client_t its_client = find_local_client(its_service, _instance);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
if (is_client_known(its_client)) {
- its_target = find_or_create_local(its_client);
+ its_target = ep_mgr_->find_or_create_local(its_client);
}
}
} else if (!utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
@@ -705,18 +699,18 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
_data[VSOMEIP_CLIENT_POS_MAX]);
if (its_client != VSOMEIP_ROUTING_CLIENT) {
if (is_client_known(its_client)) {
- its_target = find_or_create_local(its_client);
+ its_target = ep_mgr_->find_or_create_local(its_client);
}
}
} else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
_client == VSOMEIP_ROUTING_CLIENT) {
// notify
has_remote_subscribers = send_local_notification(get_client(), _data, _size,
- _instance, _flush, _reliable, _is_valid_crc);
+ _instance, _reliable, _status_check);
} else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
_client != VSOMEIP_ROUTING_CLIENT) {
// notify_one
- its_target = find_local(_client);
+ its_target = ep_mgr_->find_local(_client);
if (its_target) {
#ifdef USE_DLT
const uint16_t its_data_size
@@ -728,7 +722,7 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
_data, its_data_size);
#endif
return send_local(its_target, get_client(), _data, _size,
- _instance, _flush, _reliable, VSOMEIP_SEND, _is_valid_crc);
+ _instance, _reliable, VSOMEIP_SEND, _status_check);
}
}
// If no direct endpoint could be found
@@ -775,35 +769,32 @@ bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
if (send) {
is_sent = send_local(its_target,
(command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
- _data, _size, _instance, _flush, _reliable, command, _is_valid_crc);
+ _data, _size, _instance, _reliable, command, _status_check);
}
}
return (is_sent);
}
-bool routing_manager_proxy::send_to(
+bool routing_manager_proxy::send_to(const client_t _client,
const std::shared_ptr<endpoint_definition> &_target,
- std::shared_ptr<message> _message,
- bool _flush) {
+ std::shared_ptr<message> _message) {
+ (void)_client;
(void)_target;
(void)_message;
- (void)_flush;
return (false);
}
bool routing_manager_proxy::send_to(
const std::shared_ptr<endpoint_definition> &_target,
- const byte_t *_data, uint32_t _size, instance_t _instance,
- bool _flush) {
+ const byte_t *_data, uint32_t _size, instance_t _instance) {
(void)_target;
(void)_data;
(void)_size;
(void)_instance;
- (void)_flush;
return (false);
}
-void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) {
+void routing_manager_proxy::on_connect(const std::shared_ptr<endpoint>& _endpoint) {
_endpoint->set_connected(true);
_endpoint->set_established(true);
{
@@ -813,14 +804,10 @@ void routing_manager_proxy::on_connect(std::shared_ptr<endpoint> _endpoint) {
}
}
is_connected_ = true;
- if (is_connected_ && is_started_) {
- VSOMEIP_INFO << std::hex << "Client " << client_
- << " successfully connected to routing ~> registering..";
- register_application();
- }
+ assign_client();
}
-void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
+void routing_manager_proxy::on_disconnect(const std::shared_ptr<endpoint>& _endpoint) {
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
is_connected_ = !(_endpoint == sender_);
@@ -833,29 +820,10 @@ void routing_manager_proxy::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
}
}
-void routing_manager_proxy::on_error(
- const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port) {
-
- // Implement me when needed
-
- (void)(_data);
- (void)(_length);
- (void)(_receiver);
- (void)(_remote_address);
- (void)(_remote_port);
-}
-
-void routing_manager_proxy::release_port(uint16_t _port, bool _reliable) {
- (void)_port;
- (void)_reliable;
- // intentionally empty
-}
-
void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
endpoint *_receiver, const boost::asio::ip::address &_destination,
client_t _bound_client,
+ credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
(void)_receiver;
@@ -879,10 +847,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
major_version_t its_major;
client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
client_t its_subscriber;
- bool its_reliable;
- pending_subscription_id_t its_subscription_id(DEFAULT_SUBSCRIPTION);
+ remote_subscription_id_t its_subscription_id(PENDING_SUBSCRIPTION_ID);
std::uint32_t its_remote_subscriber_count(0);
+ std::uint32_t its_sender_uid = std::get<0>(_credentials);
+ std::uint32_t its_sender_gid = std::get<1>(_credentials);
+
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
+
if (_size > VSOMEIP_COMMAND_SIZE_POS_MAX) {
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
@@ -891,7 +865,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
sizeof(its_length));
bool message_from_routing(false);
- if (configuration_->is_security_enabled()) {
+ if (its_security->is_enabled()) {
// if security is enabled, client ID of routing must be configured
// and credential passing is active. Otherwise bound client is zero by default
message_from_routing = (_bound_client == routing_host_id);
@@ -899,7 +873,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
message_from_routing = (its_client == routing_host_id);
}
- if (configuration_->is_security_enabled() && !message_from_routing &&
+ if (its_security->is_enabled() && !message_from_routing &&
_bound_client != its_client) {
VSOMEIP_WARNING << std::hex << "Client " << std::setw(4) << std::setfill('0') << get_client()
<< " received a message with command " << (uint32_t)its_command
@@ -918,13 +892,13 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
instance_t its_instance;
bool its_reliable;
- bool its_is_valid_crc;
+ uint8_t its_check_status;
std::memcpy(&its_instance,&_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
sizeof(instance_t));
std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
sizeof(its_reliable));
- std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
- sizeof(its_is_valid_crc));
+ std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
+ sizeof(its_check_status));
// reduce by size of instance, flush, reliable, client and is_valid_crc flag
const std::uint32_t its_message_size = its_length -
@@ -943,14 +917,17 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
auto a_deserializer = get_deserializer();
a_deserializer->set_data(&_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS],
its_message_size);
- std::shared_ptr<message> its_message(a_deserializer->deserialize_message());
+ std::shared_ptr<message_impl> its_message(a_deserializer->deserialize_message());
a_deserializer->reset();
put_deserializer(a_deserializer);
if (its_message) {
its_message->set_instance(its_instance);
its_message->set_reliable(its_reliable);
- its_message->set_is_valid_crc(its_is_valid_crc);
+ its_message->set_check_result(its_check_status);
+ its_message->set_uid(std::get<0>(_credentials));
+ its_message->set_gid(std::get<1>(_credentials));
+
if (!message_from_routing) {
if (utility::is_notification(its_message->get_message_type())) {
if (!is_response_allowed(_bound_client, its_message->get_service(),
@@ -964,7 +941,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return;
} else {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ if (!its_security->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_proxy::on_message: "
@@ -978,7 +956,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
cache_event_payload(its_message);
}
} else if (utility::is_request(its_message->get_message_type())) {
- if (configuration_->is_security_enabled()
+ if (its_security->is_enabled()
&& its_message->get_client() != _bound_client) {
VSOMEIP_WARNING << std::hex << "vSomeIP Security: Client 0x" << std::setw(4) << std::setfill('0') << get_client()
<< " received a request from client 0x" << std::setw(4) << std::setfill('0')
@@ -990,8 +968,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
return;
}
- if (!configuration_->is_client_allowed(its_message->get_client(),
- its_message->get_service(), its_message->get_instance(), its_message->get_method())) {
+ if (!its_security->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_message->get_client(), its_message->get_service(),
+ its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_message->get_client()
<< " : routing_manager_proxy::on_message: "
<< "isn't allowed to send a request to service/instance/method "
@@ -1012,7 +991,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< " ~> Skip message!";
return;
} else {
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ if (!its_security->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_proxy::on_message: "
@@ -1026,7 +1006,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
}
} else {
- if (!configuration_->is_remote_client_allowed()) {
+ if (!its_security->is_remote_client_allowed()) {
// if the message is from routing manager, check if
// policy allows remote requests.
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
@@ -1042,7 +1022,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
// As subscription is sent on eventgroup level, incoming remote event ID's
// need to be checked as well if remote clients are allowed
// and the local policy only allows specific events in the eventgroup to be received.
- if (!configuration_->is_client_allowed(get_client(), its_message->get_service(),
+ if (!its_security->is_client_allowed(own_uid_, own_gid_,
+ get_client(), its_message->get_service(),
its_message->get_instance(), its_message->get_method())) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_proxy::on_message: "
@@ -1068,6 +1049,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
static_cast<std::uint16_t>(its_message_size));
}
#endif
+
host_->on_message(std::move(its_message));
} else {
VSOMEIP_ERROR << "Routing proxy: on_message: "
@@ -1076,12 +1058,23 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
break;
}
+ case VSOMEIP_ASSIGN_CLIENT_ACK: {
+ if (_size != VSOMEIP_ASSIGN_CLIENT_ACK_COMMAND_SIZE) {
+ VSOMEIP_WARNING << "Received a VSOMEIP_ASSIGN_CLIENT_ACK command with wrong size ~> skip!";
+ break;
+ }
+ client_t its_assigned_client(VSOMEIP_CLIENT_UNSET);
+ std::memcpy(&its_assigned_client,
+ &_data[VSOMEIP_COMMAND_PAYLOAD_POS], sizeof(client_));
+ on_client_assign_ack(its_assigned_client);
+ break;
+ }
case VSOMEIP_ROUTING_INFO:
if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
VSOMEIP_WARNING << "Received a ROUTING_INFO command with invalid size -> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
on_routing_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
VSOMEIP_WARNING << "routing_manager_proxy::on_message: "
@@ -1116,18 +1109,20 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
sizeof(its_major));
std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
sizeof(its_event));
- std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
+ std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
sizeof(its_subscription_id));
{
std::unique_lock<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
- if (its_subscription_id != DEFAULT_SUBSCRIPTION) {
+ if (its_subscription_id != PENDING_SUBSCRIPTION_ID) {
its_lock.unlock();
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::set_incoming_subscription_state(its_client, its_service,
its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
+#endif
// Remote subscriber: Notify routing manager initially + count subscribes
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance, its_eventgroup,
- its_client, true,
+ its_client, its_sender_uid, its_sender_gid, true,
[this, self, its_client, its_service, its_instance,
its_eventgroup, its_event, its_subscription_id, its_major]
(const bool _subscription_accepted){
@@ -1145,8 +1140,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
notify_remote_initially(its_service, its_instance, its_eventgroup,
its_already_subscribed_events);
}
+#ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client, true);
-
+#endif
std::uint32_t its_count = get_remote_subscriber_count(
its_service, its_instance, its_eventgroup, true);
VSOMEIP_INFO << "SUBSCRIBE("
@@ -1156,17 +1152,18 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << ":"
<< std::hex << std::setw(4) << std::setfill('0') << its_event << ":"
<< std::dec << (uint16_t)its_major << "]"
- << (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " "
+ << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
<< std::dec << its_count;
-
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
its_instance, its_eventgroup, its_event);
+#endif
});
} else if (is_client_known(its_client)) {
its_lock.unlock();
if (!message_from_routing) {
if (its_event == ANY_EVENT) {
- if (!is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) {
+ if (!is_subscribe_to_any_event_allowed(_credentials, its_client, its_service, its_instance, its_eventgroup)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_proxy::on_message: "
<< " isn't allowed to subscribe to service/instance/event "
@@ -1175,8 +1172,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
return;
}
} else {
- if (!configuration_->is_client_allowed(its_client,
- its_service, its_instance, its_event)) {
+ if (!its_security->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_client, its_service, its_instance, its_event)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_proxy::on_message: "
<< " subscribes to service/instance/event "
@@ -1186,7 +1183,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
}
} else {
- if (!configuration_->is_remote_client_allowed()) {
+ if (!its_security->is_remote_client_allowed()) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_proxy::on_message: "
<< std::hex << "Routing manager with client ID 0x"
@@ -1201,38 +1198,42 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
}
// Local & already known subscriber: create endpoint + send (N)ACK + insert subscription
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::set_incoming_subscription_state(its_client, its_service,
its_instance, its_eventgroup, its_event, subscription_state_e::IS_SUBSCRIBING);
- (void) find_or_create_local(its_client);
+#endif
+ (void) ep_mgr_->find_or_create_local(its_client);
auto self = shared_from_this();
host_->on_subscription(its_service, its_instance,
- its_eventgroup, its_client, true,
- [this, self, its_client, its_service, its_instance, its_eventgroup,
- its_event, its_major]
+ its_eventgroup, its_client, its_sender_uid, its_sender_gid, true,
+ [this, self, its_client, its_sender_uid, its_sender_gid, its_service,
+ its_instance, its_eventgroup, its_event, its_major]
(const bool _subscription_accepted) {
if (!_subscription_accepted) {
- send_subscribe_nack(its_client, its_service,
- its_instance, its_eventgroup, its_event, DEFAULT_SUBSCRIPTION);
+ send_subscribe_nack(its_client, its_service, its_instance,
+ its_eventgroup, its_event, PENDING_SUBSCRIPTION_ID);
} else {
send_subscribe_ack(its_client, its_service, its_instance,
- its_eventgroup, its_event, DEFAULT_SUBSCRIPTION);
- routing_manager_base::subscribe(its_client, its_service, its_instance,
- its_eventgroup, its_major, its_event,
- subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ its_eventgroup, its_event, PENDING_SUBSCRIPTION_ID);
+ routing_manager_base::subscribe(its_client, its_sender_uid, its_sender_gid,
+ its_service, its_instance, its_eventgroup, its_major, its_event);
+#ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(its_service, its_instance, its_eventgroup, its_client);
+#endif
}
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::erase_incoming_subscription_state(its_client, its_service,
its_instance, its_eventgroup, its_event);
+#endif
});
} else {
// Local & not yet known subscriber ~> set pending until subscriber gets known!
subscription_data_t subscription = { its_service, its_instance,
- its_eventgroup, its_major, its_event,
- subscription_type_e::SU_RELIABLE_AND_UNRELIABLE};
+ its_eventgroup, its_major, its_event, its_sender_uid, its_sender_gid };
pending_incoming_subscripitons_[its_client].insert(subscription);
}
}
- if (its_subscription_id == DEFAULT_SUBSCRIPTION) { // local subscription
+ if (its_subscription_id == PENDING_SUBSCRIPTION_ID) { // local subscription
VSOMEIP_INFO << "SUBSCRIBE("
<< std::hex << std::setw(4) << std::setfill('0') << its_client <<"): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
@@ -1258,16 +1259,16 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
sizeof(its_event));
std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(its_subscription_id));
- host_->on_subscription(its_service, its_instance, its_eventgroup, its_client, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
- if (its_subscription_id == DEFAULT_SUBSCRIPTION) {
+ host_->on_subscription(its_service, its_instance, its_eventgroup, its_client, its_sender_uid, its_sender_gid, false, [](const bool _subscription_accepted){ (void)_subscription_accepted; });
+ if (its_subscription_id == PENDING_SUBSCRIPTION_ID) {
// Local subscriber: withdraw subscription
- routing_manager_base::unsubscribe(its_client, its_service, its_instance, its_eventgroup, its_event);
+ routing_manager_base::unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance, its_eventgroup, its_event);
} else {
// Remote subscriber: withdraw subscription only if no more remote subscriber exists
its_remote_subscriber_count = get_remote_subscriber_count(its_service,
its_instance, its_eventgroup, false);
if (!its_remote_subscriber_count) {
- routing_manager_base::unsubscribe(VSOMEIP_ROUTING_CLIENT, its_service,
+ routing_manager_base::unsubscribe(VSOMEIP_ROUTING_CLIENT, ANY_UID, ANY_GID, its_service,
its_instance, its_eventgroup, its_event);
}
send_unsubscribe_ack(its_service, its_instance, its_eventgroup,
@@ -1279,7 +1280,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_event << "] "
- << (bool)(its_subscription_id != DEFAULT_SUBSCRIPTION) << " "
+ << (bool)(its_subscription_id != PENDING_SUBSCRIPTION_ID) << " "
<< std::dec << its_remote_subscriber_count;
break;
@@ -1333,30 +1334,12 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
<< std::hex << std::setw(4) << std::setfill('0') << its_event << "]";
break;
- case VSOMEIP_ID_REQUEST:
- if (_size < VSOMEIP_ID_REQUEST_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a VSOMEIP_ID_REQUEST command with wrong size ~> skip!";
- break;
- }
- std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(its_service));
- std::memcpy(&its_instance, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
- sizeof(its_instance));
- std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_major));
- std::memcpy(&its_reliable, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
- sizeof(its_reliable));
-
- send_identify_request(its_service, its_instance, its_major, its_reliable);
-
- break;
-
case VSOMEIP_OFFERED_SERVICES_RESPONSE:
if (_size - VSOMEIP_COMMAND_HEADER_SIZE != its_length) {
VSOMEIP_WARNING << "Received a VSOMEIP_OFFERED_SERVICES_RESPONSE command with invalid size -> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
on_offered_services_info(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
VSOMEIP_WARNING << std::hex << "Security: Client 0x" << get_client()
@@ -1385,7 +1368,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_POLICY command with wrong size -> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
pending_security_update_id_t its_update_id(0);
uint32_t its_uid(0);
uint32_t its_gid(0);
@@ -1399,10 +1382,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
uint32_t its_size = uint32_t(_size - (VSOMEIP_COMMAND_PAYLOAD_POS
+ sizeof(pending_security_update_id_t)));
- utility::parse_policy(buffer_ptr, its_size, its_uid, its_gid, its_policy);
+ its_security->parse_policy(buffer_ptr, its_size, its_uid, its_gid, its_policy);
- if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
- configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ if (its_security->is_policy_update_allowed(its_uid, its_policy)) {
+ its_security->update_security_policy(its_uid, its_gid, its_policy);
send_update_security_policy_response(its_update_id);
}
} else {
@@ -1418,10 +1401,10 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_REMOVE_SECURITY_POLICY command with wrong size ~> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
pending_security_update_id_t its_update_id(0);
- uint32_t its_uid(0xffffffff);
- uint32_t its_gid(0xffffffff);
+ uint32_t its_uid(ANY_UID);
+ uint32_t its_gid(ANY_GID);
std::memcpy(&its_update_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
sizeof(pending_security_update_id_t));
@@ -1429,8 +1412,8 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
sizeof(uint32_t));
std::memcpy(&its_gid, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
sizeof(uint32_t));
- if (configuration_->is_policy_removal_allowed(its_uid)) {
- configuration_->remove_security_policy(its_uid, its_gid);
+ if (its_security->is_policy_removal_allowed(its_uid)) {
+ its_security->remove_security_policy(its_uid, its_gid);
send_remove_security_policy_response(its_update_id);
}
} else {
@@ -1447,7 +1430,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_DISTRIBUTE_SECURITY_POLICIES command with wrong size -> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
uint32_t its_policy_count(0);
uint32_t its_policy_size(0);
const byte_t* buffer_ptr = 0;
@@ -1471,9 +1454,9 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
buffer_ptr += sizeof(uint32_t);
if (buffer_ptr + its_policy_size <= _data + _size) {
- if (utility::parse_policy(buffer_ptr, its_policy_size, its_uid, its_gid, its_policy)) {
- if (configuration_->is_policy_update_allowed(its_uid, its_policy)) {
- configuration_->update_security_policy(its_uid, its_gid, its_policy);
+ if (its_security->parse_policy(buffer_ptr, its_policy_size, its_uid, its_gid, its_policy)) {
+ if (its_security->is_policy_update_allowed(its_uid, its_policy)) {
+ its_security->update_security_policy(its_uid, its_gid, its_policy);
}
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client() << " could not parse policy!";
@@ -1496,7 +1479,7 @@ void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
VSOMEIP_WARNING << "vSomeIP Security: Received a VSOMEIP_UPDATE_SECURITY_CREDENTIALS command with wrong size -> skip!";
break;
}
- if (!configuration_->is_security_enabled() || message_from_routing) {
+ if (!its_security->is_enabled() || message_from_routing) {
on_update_security_credentials(&_data[VSOMEIP_COMMAND_PAYLOAD_POS], its_length);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << get_client()
@@ -1521,6 +1504,9 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
msg << std::hex << std::setw(2) << std::setfill('0') << (int)_data[i] << " ";
VSOMEIP_INFO << msg.str();
#endif
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
uint32_t i = 0;
while (i + sizeof(uint32_t) + sizeof(routing_info_entry_e) <= _size) {
@@ -1550,10 +1536,10 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
}
if (its_client == get_client()) {
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- << " is registered.";
+ << " (" << host_->get_name() << ") is registered.";
#ifndef _WIN32
- if (!check_credentials(get_client(), getuid(), getgid())) {
+ if (!its_security->check_credentials(get_client(), own_uid_, own_gid_)) {
VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_proxy::on_routing_info: RIE_ADD_CLIENT: isn't allowed"
<< " to use the server endpoint due to credential check failed!";
@@ -1583,9 +1569,9 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
known_clients_.erase(its_client);
}
if (its_client == get_client()) {
- configuration_->remove_client_to_uid_gid_mapping(its_client);
+ its_security->remove_client_to_uid_gid_mapping(its_client);
VSOMEIP_INFO << std::hex << "Application/Client " << get_client()
- << " is deregistered.";
+ << " (" << host_->get_name() << ") is deregistered.";
// inform host about its own registration state changes
host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
@@ -1684,6 +1670,8 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
client_t client_id_;
major_version_t major_;
event_t event_;
+ uid_t uid_;
+ gid_t gid_;
};
std::lock_guard<std::recursive_mutex> its_lock(incoming_subscriptions_mutex_);
std::forward_list<struct subscription_info> subscription_actions;
@@ -1697,35 +1685,41 @@ void routing_manager_proxy::on_routing_info(const byte_t *_data,
subscription_actions.push_front(
{ subscription.service_, subscription.instance_,
subscription.eventgroup_, client,
- subscription.major_, subscription.event_ });
+ subscription.major_, subscription.event_,
+ subscription.uid_, subscription.gid_ });
}
}
}
}
for (const subscription_info &si : subscription_actions) {
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::set_incoming_subscription_state(si.client_id_, si.service_id_, si.instance_id_,
si.eventgroup_id_, si.event_, subscription_state_e::IS_SUBSCRIBING);
- (void) find_or_create_local(si.client_id_);
+#endif
+ (void) ep_mgr_->find_or_create_local(si.client_id_);
auto self = shared_from_this();
host_->on_subscription(
si.service_id_, si.instance_id_, si.eventgroup_id_,
- si.client_id_, true,
+ si.client_id_, si.uid_, si.gid_, true,
[this, self, si](const bool _subscription_accepted) {
if (!_subscription_accepted) {
send_subscribe_nack(si.client_id_, si.service_id_,
- si.instance_id_, si.eventgroup_id_, si.event_, DEFAULT_SUBSCRIPTION);
+ si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_ID);
} else {
- routing_manager_base::subscribe(si.client_id_,
+ routing_manager_base::subscribe(si.client_id_, si.uid_, si.gid_,
si.service_id_, si.instance_id_, si.eventgroup_id_,
- si.major_, si.event_,
- subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ si.major_, si.event_);
send_subscribe_ack(si.client_id_, si.service_id_,
- si.instance_id_, si.eventgroup_id_, si.event_, DEFAULT_SUBSCRIPTION);
+ si.instance_id_, si.eventgroup_id_, si.event_, PENDING_SUBSCRIPTION_ID);
+#ifdef VSOMEIP_ENABLE_COMPAT
send_pending_notify_ones(si.service_id_,
si.instance_id_, si.eventgroup_id_, si.client_id_);
+#endif
}
+#ifdef VSOMEIP_ENABLE_COMPAT
routing_manager_base::erase_incoming_subscription_state(si.client_id_, si.service_id_,
si.instance_id_, si.eventgroup_id_, si.event_);
+#endif
{
std::lock_guard<std::recursive_mutex> its_lock2(incoming_subscriptions_mutex_);
pending_incoming_subscripitons_.erase(si.client_id_);
@@ -1788,6 +1782,10 @@ void routing_manager_proxy::on_offered_services_info(const byte_t *_data,
}
void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clients) {
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
+
// inform host about its own registration state changes
host_->on_state(static_cast<state_type_e>(inner_state_type_e::ST_DEREGISTERED));
@@ -1810,7 +1808,7 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien
<<": Reconnecting to routing manager.";
#ifndef _WIN32
- if (!check_credentials(get_client(), getuid(), getgid())) {
+ if (!its_security->check_credentials(get_client(), own_uid_, own_gid_)) {
VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_proxy::reconnect: isn't allowed"
<< " to use the server endpoint due to credential check failed!";
@@ -1828,6 +1826,44 @@ void routing_manager_proxy::reconnect(const std::unordered_set<client_t> &_clien
}
}
+void routing_manager_proxy::assign_client() {
+ std::vector<byte_t> its_command;
+
+ std::string its_name(host_->get_name());
+ uint32_t its_size(static_cast<uint32_t>(its_name.size()));
+ its_command.resize(7 + its_name.size());
+
+ its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ASSIGN_CLIENT;
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
+ sizeof(client_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
+ sizeof(its_size));
+ if (0 < its_name.size())
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], its_name.c_str(),
+ its_name.size());
+
+ std::lock_guard<std::mutex> its_state_lock(state_mutex_);
+ if (is_connected_) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ if (sender_) {
+ if (state_ != inner_state_type_e::ST_DEREGISTERED)
+ return;
+ state_ = inner_state_type_e::ST_ASSIGNING;
+
+ sender_->send(&its_command[0], static_cast<uint32_t>(its_command.size()));
+
+ boost::system::error_code ec;
+ register_application_timer_.cancel(ec);
+ register_application_timer_.expires_from_now(std::chrono::milliseconds(10000));
+ register_application_timer_.async_wait(
+ std::bind(
+ &routing_manager_proxy::assign_client_timeout_cbk,
+ std::dynamic_pointer_cast<routing_manager_proxy>(shared_from_this()),
+ std::placeholders::_1));
+ }
+ }
+}
+
void routing_manager_proxy::register_application() {
byte_t its_command[] = {
VSOMEIP_REGISTER_APPLICATION, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -1836,12 +1872,9 @@ void routing_manager_proxy::register_application() {
sizeof(client_));
if (is_connected_) {
- std::lock_guard<std::mutex> its_state_lock(state_mutex_);
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- {
- state_ = inner_state_type_e::ST_REGISTERING;
- }
+ state_ = inner_state_type_e::ST_REGISTERING;
sender_->send(its_command, sizeof(its_command));
register_application_timer_.cancel();
@@ -1898,32 +1931,31 @@ void routing_manager_proxy::send_request_services(std::set<service_data_t>& _req
std::vector<byte_t> its_command(its_size + VSOMEIP_COMMAND_HEADER_SIZE);
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_REQUEST_SERVICE;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client_,
- sizeof(client_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(std::uint32_t));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS],
+ &client_, sizeof(client_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN],
+ &its_size, sizeof(std::uint32_t));
- uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
- + sizeof(minor_version_t) + sizeof(bool));
+ uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t)
+ + sizeof(major_version_t) + sizeof(minor_version_t));
- int i = 0;
+ unsigned int i = 0;
for (auto its_service : _requests) {
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)], &its_service.service_,
- sizeof(its_service.service_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)], &its_service.instance_,
- sizeof(its_service.instance_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)],
+ &its_service.service_, sizeof(its_service.service_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2 + (i * entry_size)],
+ &its_service.instance_, sizeof(its_service.instance_));
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4 + (i * entry_size)] = its_service.major_;
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)], &its_service.minor_,
- sizeof(its_service.minor_));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)], &its_service.use_exclusive_proxy_,
- sizeof(its_service.use_exclusive_proxy_));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)],
+ &its_service.minor_, sizeof(its_service.minor_));
++i;
}
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- sender_->send(&its_command[0], static_cast<std::uint32_t>(its_size + VSOMEIP_COMMAND_HEADER_SIZE));
+ sender_->send(&its_command[0],
+ static_cast<std::uint32_t>(its_size + VSOMEIP_COMMAND_HEADER_SIZE));
}
}
}
@@ -1955,8 +1987,10 @@ void routing_manager_proxy::send_release_service(client_t _client, service_t _se
void routing_manager_proxy::send_register_event(client_t _client,
service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field, bool _is_provided) {
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, const event_type_e _type,
+ reliability_type_e _reliability,
+ bool _is_provided) {
std::size_t its_eventgroups_size = (_eventgroups.size() * sizeof(eventgroup_t)) +
VSOMEIP_REGISTER_EVENT_COMMAND_SIZE;
@@ -1978,14 +2012,16 @@ void routing_manager_proxy::send_register_event(client_t _client,
sizeof(_service));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_event,
- sizeof(_event));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_notifier,
+ sizeof(_notifier));
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6]
- = static_cast<byte_t>(_is_field);
+ = static_cast<byte_t>(_type);
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7]
= static_cast<byte_t>(_is_provided);
+ its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8]
+ = static_cast<byte_t>(_reliability);
- std::size_t i = 8;
+ std::size_t i = 9;
for (auto eg : _eventgroups) {
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + i], &eg,
sizeof(eventgroup_t));
@@ -1999,22 +2035,38 @@ void routing_manager_proxy::send_register_event(client_t _client,
}
}
+ if (_is_provided) {
+ VSOMEIP_INFO << "REGISTER EVENT("
+ << std::hex << std::setw(4) << std::setfill('0') << client_ << "): ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _notifier
+ << ":is_provider=" << _is_provided << "]";
+ }
+
delete[] its_command;
}
void routing_manager_proxy::on_subscribe_ack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
(void)_client;
+#if 0
+ VSOMEIP_ERROR << "routing_manager_proxy::" << __func__
+ << "(" << std::hex << host_->get_client() << "):"
+ << "event="
+ << std::hex << _service << "."
+ << std::hex << _instance << "."
+ << std::hex << _eventgroup << "."
+ << std::hex << _event;
+#endif
if (_event == ANY_EVENT) {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- for (auto its_event : its_eventgroup->get_events()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
+ for (const auto& its_event : its_eventgroup->get_events()) {
host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x0 /*OK*/);
}
}
} else {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x0 /*OK*/);
host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x0 /*OK*/);
}
}
@@ -2025,41 +2077,15 @@ void routing_manager_proxy::on_subscribe_nack(client_t _client,
if (_event == ANY_EVENT) {
auto its_eventgroup = find_eventgroup(_service, _instance, _eventgroup);
if (its_eventgroup) {
- for (auto its_event : its_eventgroup->get_events()) {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
+ for (const auto& its_event : its_eventgroup->get_events()) {
host_->on_subscription_status(_service, _instance, _eventgroup, its_event->get_event(), 0x7 /*Rejected*/);
}
}
} else {
- host_->on_subscription_error(_service, _instance, _eventgroup, 0x7 /*Rejected*/);
host_->on_subscription_status(_service, _instance, _eventgroup, _event, 0x7 /*Rejected*/);
}
}
-void routing_manager_proxy::on_identify_response(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) {
- static const uint32_t size = VSOMEIP_ID_RESPONSE_COMMAND_SIZE;
- byte_t its_command[size];
- uint32_t its_size = size - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ID_RESPONSE;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
- sizeof(_client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_reliable,
- sizeof(_reliable));
- {
- std::lock_guard<std::mutex> its_lock(sender_mutex_);
- if (sender_) {
- sender_->send(its_command, size);
- }
- }
-}
-
void routing_manager_proxy::cache_event_payload(
const std::shared_ptr<message> &_message) {
const service_t its_service(_message->get_service());
@@ -2075,9 +2101,12 @@ void routing_manager_proxy::cache_event_payload(
std::set<eventgroup_t> its_eventgroups;
// create a placeholder field until someone requests this event with
// full information like eventgroup, field or not etc.
- routing_manager_base::register_event(host_->get_client(), its_service,
- its_instance, its_method, its_eventgroups, true,
- std::chrono::milliseconds::zero(), false,
+ routing_manager_base::register_event(host_->get_client(),
+ its_service, its_instance,
+ its_method,
+ its_eventgroups, event_type_e::ET_UNKNOWN,
+ reliability_type_e::RT_UNKNOWN,
+ std::chrono::milliseconds::zero(), false, true,
nullptr,
false, false, true);
std::shared_ptr<event> its_event = find_event(its_service, its_instance, its_method);
@@ -2113,52 +2142,30 @@ void routing_manager_proxy::on_stop_offer_service(service_t _service,
void routing_manager_proxy::send_pending_commands() {
for (auto &po : pending_offers_)
- send_offer_service(client_, po.service_, po.instance_,
+ send_offer_service(client_,
+ po.service_, po.instance_,
po.major_, po.minor_);
for (auto &per : pending_event_registrations_)
- send_register_event(client_, per.service_, per.instance_,
- per.event_, per.eventgroups_,
- per.is_field_, per.is_provided_);
+ send_register_event(client_,
+ per.service_, per.instance_,
+ per.notifier_,
+ per.eventgroups_, per.type_, per.reliability_,
+ per.is_provided_);
send_request_services(requests_);
}
void routing_manager_proxy::init_receiver() {
- std::stringstream its_client;
- its_client << utility::get_base_path(configuration_) << std::hex << client_;
-#ifdef _WIN32
- ::_unlink(its_client.str().c_str());
- int port = VSOMEIP_INTERNAL_BASE_PORT + client_;
-#else
- configuration_->store_client_to_uid_gid_mapping(get_client(), getuid(), getgid());
- configuration_->store_uid_gid_to_client_mapping(getuid(), getgid(), get_client());
+#ifndef _WIN32
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
- if (-1 == ::unlink(its_client.str().c_str()) && errno != ENOENT) {
- VSOMEIP_ERROR << "routing_manager_proxy::init_receiver unlink failed ("
- << its_client.str() << "): "<< std::strerror(errno);
- }
-#endif
- try {
- receiver_ = std::make_shared<local_server_endpoint_impl>(shared_from_this(),
-#ifdef _WIN32
- boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
-#else
- boost::asio::local::stream_protocol::endpoint(its_client.str()),
-#endif
- io_, configuration_->get_max_message_size_local(),
- configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local(),
- configuration_->get_permissions_uds());
-#ifdef _WIN32
- VSOMEIP_INFO << "Listening at " << port;
-#else
- VSOMEIP_INFO << "Listening at " << its_client.str();
+ its_security->store_client_to_uid_gid_mapping(get_client(), own_uid_, own_gid_);
+ its_security->store_uid_gid_to_client_mapping(own_uid_, own_gid_, get_client());
#endif
- } catch (const std::exception &e) {
- host_->on_error(error_code_e::SERVER_ENDPOINT_CREATION_FAILED);
- VSOMEIP_ERROR << "Client ID: " << std::hex << client_ << ": " << e.what();
- }
+ receiver_ = ep_mgr_->create_local_server(shared_from_this());
}
void routing_manager_proxy::notify_remote_initially(service_t _service, instance_t _instance,
@@ -2179,16 +2186,18 @@ void routing_manager_proxy::notify_remote_initially(service_t _service, instance
if (service_info) {
its_notification->set_interface_version(service_info->get_major());
}
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- if (serializer_->serialize(its_notification.get())) {
+
+ std::shared_ptr<serializer> its_serializer(get_serializer());
+ if (its_serializer->serialize(its_notification.get())) {
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
if (sender_) {
- send_local(sender_, VSOMEIP_ROUTING_CLIENT, serializer_->get_data(),
- serializer_->get_size(), _instance, true, false, VSOMEIP_NOTIFY);
+ send_local(sender_, VSOMEIP_ROUTING_CLIENT, its_serializer->get_data(),
+ its_serializer->get_size(), _instance, false, VSOMEIP_NOTIFY);
}
}
- serializer_->reset();
+ its_serializer->reset();
+ put_serializer(its_serializer);
} else {
VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
}
@@ -2243,6 +2252,30 @@ void routing_manager_proxy::clear_remote_subscriber_count(
}
}
+void
+routing_manager_proxy::assign_client_timeout_cbk(
+ boost::system::error_code const &_error) {
+ if (!_error) {
+ bool register_again(false);
+ {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ != inner_state_type_e::ST_REGISTERED) {
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+ register_again = true;
+ }
+ }
+ if (register_again) {
+ std::lock_guard<std::mutex> its_lock(sender_mutex_);
+ VSOMEIP_WARNING << std::hex << "Client 0x" << get_client()
+ << " request client timeout! Trying again...";
+
+ if (sender_) {
+ sender_->restart();
+ }
+ }
+ }
+}
+
void routing_manager_proxy::register_application_timeout_cbk(
boost::system::error_code const &_error) {
if (!_error) {
@@ -2256,8 +2289,9 @@ void routing_manager_proxy::register_application_timeout_cbk(
}
if (register_again) {
std::lock_guard<std::mutex> its_lock(sender_mutex_);
- VSOMEIP_WARNING << std::hex << "Client 0x" << get_client() << " register timeout!"
- << " : Restart route to stub!";
+ VSOMEIP_WARNING << std::hex << "Client 0x" << get_client()
+ << " register timeout! Trying again...";
+
if (sender_) {
sender_->restart();
}
@@ -2285,19 +2319,21 @@ bool routing_manager_proxy::is_client_known(client_t _client) {
}
bool routing_manager_proxy::create_placeholder_event_and_subscribe(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, client_t _client) {
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _notifier, client_t _client) {
+
bool is_inserted(false);
// we received a event which was not yet requested/offered
// create a placeholder field until someone requests/offers this event with
// full information like eventgroup, field or not etc.
std::set<eventgroup_t> its_eventgroups({ _eventgroup });
// routing_manager_proxy: Always register with own client id and shadow = false
- routing_manager_base::register_event(host_->get_client(), _service,
- _instance, _event, its_eventgroups, true,
- std::chrono::milliseconds::zero(), false, nullptr, false, false,
+ routing_manager_base::register_event(host_->get_client(),
+ _service, _instance, _notifier,
+ its_eventgroups, event_type_e::ET_UNKNOWN, reliability_type_e::RT_UNKNOWN,
+ std::chrono::milliseconds::zero(), false, true, nullptr, false, false,
true);
- std::shared_ptr<event> its_event = find_event(_service, _instance, _event);
+ std::shared_ptr<event> its_event = find_event(_service, _instance, _notifier);
if (its_event) {
is_inserted = its_event->add_subscriber(_eventgroup, _client, false);
}
@@ -2318,7 +2354,8 @@ void routing_manager_proxy::request_debounce_timeout_cbk(
{
std::lock_guard<std::mutex> its_lock(request_timer_mutex_);
request_debounce_timer_running_ = true;
- request_debounce_timer_.expires_from_now(std::chrono::milliseconds(configuration_->get_request_debouncing(host_->get_name())));
+ request_debounce_timer_.expires_from_now(std::chrono::milliseconds(
+ configuration_->get_request_debouncing(host_->get_name())));
request_debounce_timer_.async_wait(
std::bind(
&routing_manager_proxy::request_debounce_timeout_cbk,
@@ -2358,7 +2395,7 @@ void routing_manager_proxy::handle_client_error(client_t _client) {
std::lock_guard<std::mutex> its_lock(known_clients_mutex_);
its_known_clients = known_clients_;
}
- reconnect(its_known_clients);
+ reconnect(its_known_clients);
}
}
}
@@ -2386,7 +2423,7 @@ void routing_manager_proxy::send_get_offered_services_info(client_t _client, off
void routing_manager_proxy::send_unsubscribe_ack(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- pending_subscription_id_t _subscription_id) {
+ remote_subscription_id_t _id) {
byte_t its_command[VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE];
const std::uint32_t its_size = VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE
- VSOMEIP_COMMAND_HEADER_SIZE;
@@ -2403,8 +2440,8 @@ void routing_manager_proxy::send_unsubscribe_ack(
sizeof(_instance));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_eventgroup,
sizeof(_eventgroup));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- &_subscription_id, sizeof(_subscription_id));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_id,
+ sizeof(_id));
{
std::lock_guard<std::mutex> its_lock(sender_mutex_);
@@ -2419,8 +2456,8 @@ void routing_manager_proxy::resend_provided_event_registrations() {
for (const event_data_t& ed : pending_event_registrations_) {
if (ed.is_provided_) {
send_register_event(client_, ed.service_, ed.instance_,
- ed.event_, ed.eventgroups_,
- ed.is_field_, ed.is_provided_);
+ ed.notifier_, ed.eventgroups_, ed.type_, ed.reliability_,
+ ed.is_provided_);
}
}
}
@@ -2489,6 +2526,10 @@ void routing_manager_proxy::send_remove_security_policy_response(pending_securit
}
void routing_manager_proxy::on_update_security_credentials(const byte_t *_data, uint32_t _size) {
+ auto its_security = security_impl::get();
+ if (!its_security)
+ return;
+
uint32_t i = 0;
while ( (i + sizeof(uint32_t) + sizeof(uint32_t)) <= _size) {
std::shared_ptr<policy> its_policy(std::make_shared<policy>());
@@ -2505,8 +2546,49 @@ void routing_manager_proxy::on_update_security_credentials(const byte_t *_data,
its_policy->allow_who_ = true;
its_policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
- configuration_->add_security_credentials(its_uid, its_gid, its_policy, get_client());
+ its_security->add_security_credentials(its_uid, its_gid, its_policy, get_client());
+ }
+}
+
+void routing_manager_proxy::on_client_assign_ack(const client_t &_client) {
+ std::lock_guard<std::mutex> its_lock(state_mutex_);
+ if (state_ == inner_state_type_e::ST_ASSIGNING) {
+ if (_client != VSOMEIP_CLIENT_UNSET) {
+ state_ = inner_state_type_e::ST_ASSIGNED;
+
+ boost::system::error_code ec;
+ register_application_timer_.cancel(ec);
+ host_->set_client(_client);
+ client_ = _client;
+
+ if (is_started_) {
+ init_receiver();
+ if (receiver_) {
+ receiver_->start();
+
+ VSOMEIP_INFO << std::hex << "Client " << client_
+ << " (" << host_->get_name()
+ << ") successfully connected to routing ~> registering..";
+ register_application();
+ } else {
+ state_ = inner_state_type_e::ST_DEREGISTERED;
+
+ host_->set_client(VSOMEIP_CLIENT_UNSET);
+ client_ = VSOMEIP_CLIENT_UNSET;
+
+ sender_->restart();
+ }
+ }
+ } else {
+ VSOMEIP_ERROR << "Didn't receive valid clientID! Won't register application.";
+ }
+ } else {
+ VSOMEIP_WARNING << "Client " << std::hex << client_
+ << " received another client identifier ("
+ << std::hex << _client
+ << "). Ignoring it. ("
+ << (int)state_ << ")";
}
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/routing_manager_stub.cpp b/implementation/routing/src/routing_manager_stub.cpp
index 5c19af9..65945f7 100644
--- a/implementation/routing/src/routing_manager_stub.cpp
+++ b/implementation/routing/src/routing_manager_stub.cpp
@@ -14,30 +14,28 @@
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/runtime.hpp>
#include <vsomeip/error.hpp>
-
-#ifndef WITHOUT_SYSTEMD
-#include <systemd/sd-daemon.h>
-#endif
-#define SD_LISTEN_FDS_START 3
+#include <vsomeip/internal/logger.hpp>
#include "../include/routing_manager_stub.hpp"
#include "../include/routing_manager_stub_host.hpp"
+#include "../include/remote_subscription.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
+#include "../../security/include/security.hpp"
+
#include "../../endpoints/include/local_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
+#include "../../endpoints/include/endpoint_manager_impl.hpp"
#include "../../utility/include/byteorder.hpp"
#include "../../utility/include/utility.hpp"
#include "../implementation/message/include/payload_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
const std::vector<byte_t> routing_manager_stub::its_ping_(
{ VSOMEIP_PING, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
routing_manager_stub::routing_manager_stub(
routing_manager_stub_host *_host,
- std::shared_ptr<configuration> _configuration) :
+ const std::shared_ptr<configuration>& _configuration) :
host_(_host),
io_(_host->get_io()),
watchdog_timer_(_host->get_io()),
@@ -45,7 +43,6 @@ routing_manager_stub::routing_manager_stub(
endpoint_(nullptr),
local_receiver_(nullptr),
configuration_(_configuration),
- routingCommandSize_(VSOMEIP_ROUTING_INFO_SIZE_INIT),
is_socket_activated_(false),
client_registration_running_(false),
max_local_message_size_(configuration_->get_max_message_size_local()),
@@ -75,11 +72,11 @@ void routing_manager_stub::start() {
std::placeholders::_1));
}
- if(!endpoint_) {
+ if (!endpoint_) {
// application has been stopped and started again
init_routing_endpoint();
}
- if(endpoint_) {
+ if (endpoint_) {
endpoint_->start();
}
@@ -127,12 +124,15 @@ void routing_manager_stub::stop() {
if( !is_socket_activated_) {
endpoint_->stop();
endpoint_ = nullptr;
+ std::stringstream its_endpoint_path;
+ its_endpoint_path << utility::get_base_path(configuration_) << std::hex
+ << VSOMEIP_ROUTING_CLIENT;
#ifdef _WIN32
- ::_unlink(endpoint_path_.c_str());
+ ::_unlink(its_endpoint_path.str().c_str());
#else
- if (-1 == ::unlink(endpoint_path_.c_str())) {
+ if (-1 == ::unlink(its_endpoint_path.str().c_str())) {
VSOMEIP_ERROR << "routing_manager_stub::stop() unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
+ << its_endpoint_path.str() << "): "<< std::strerror(errno);
}
#endif
}
@@ -140,53 +140,24 @@ void routing_manager_stub::stop() {
if(local_receiver_) {
local_receiver_->stop();
local_receiver_ = nullptr;
+ std::stringstream its_local_receiver_path;
+ its_local_receiver_path << utility::get_base_path(configuration_)
+ << std::hex << host_->get_client();
#ifdef _WIN32
- ::_unlink(local_receiver_path_.c_str());
+ ::_unlink(its_local_receiver_path.str().c_str());
#else
- if (-1 == ::unlink(local_receiver_path_.c_str())) {
+ if (-1 == ::unlink(its_local_receiver_path.str().c_str())) {
VSOMEIP_ERROR << "routing_manager_stub::stop() unlink (local receiver) failed ("
- << local_receiver_path_ << "): "<< std::strerror(errno);
+ << its_local_receiver_path.str() << "): "<< std::strerror(errno);
}
#endif
}
}
-const std::shared_ptr<configuration> routing_manager_stub::get_configuration() const {
- return configuration_;
-}
-
-void routing_manager_stub::on_connect(std::shared_ptr<endpoint> _endpoint) {
- _endpoint->set_connected(true);
- _endpoint->set_established(true);
-}
-
-void routing_manager_stub::on_disconnect(std::shared_ptr<endpoint> _endpoint) {
- (void)_endpoint;
-}
-
-void routing_manager_stub::on_error(
- const byte_t *_data, length_t _length, endpoint *_receiver,
- const boost::asio::ip::address &_remote_address,
- std::uint16_t _remote_port) {
-
- // Implement me when needed
-
- (void)(_data);
- (void)(_length);
- (void)(_receiver);
- (void)(_remote_address);
- (void)(_remote_port);
-}
-
-void routing_manager_stub::release_port(uint16_t _port, bool _reliable) {
- (void)_port;
- (void)_reliable;
- // intentionally empty
-}
-
void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
endpoint *_receiver, const boost::asio::ip::address &_destination,
client_t _bound_client,
+ credentials_t _credentials,
const boost::asio::ip::address &_remote_address,
std::uint16_t _remote_port) {
(void)_receiver;
@@ -201,6 +172,9 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
VSOMEIP_INFO << msg.str();
#endif
+ std::uint32_t its_sender_uid = std::get<0>(_credentials);
+ std::uint32_t its_sender_gid = std::get<1>(_credentials);
+
if (VSOMEIP_COMMAND_SIZE_POS_MAX < _size) {
byte_t its_command;
client_t its_client;
@@ -209,9 +183,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
instance_t its_instance;
method_t its_method;
eventgroup_t its_eventgroup;
- std::set<eventgroup_t> its_eventgroups;
- event_t its_event;
- bool is_field(false);
+ event_t its_notifier;
+ event_type_e its_event_type;
bool is_provided(false);
major_version_t its_major;
minor_version_t its_minor;
@@ -219,19 +192,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
const byte_t *its_data;
uint32_t its_size;
bool its_reliable(false);
- subscription_type_e its_subscription_type;
client_t its_client_from_header;
client_t its_target_client;
client_t its_subscriber;
- bool its_is_valid_crc(true);
- std::uint16_t its_subscription_id(DEFAULT_SUBSCRIPTION);
+ uint8_t its_check_status(0);
+ std::uint16_t its_subscription_id(PENDING_SUBSCRIPTION_ID);
offer_type_e its_offer_type;
its_command = _data[VSOMEIP_COMMAND_TYPE_POS];
std::memcpy(&its_client, &_data[VSOMEIP_COMMAND_CLIENT_POS],
sizeof(its_client));
- if (configuration_->is_security_enabled() && _bound_client != its_client) {
+ if (security::get()->is_enabled() && _bound_client != its_client) {
VSOMEIP_WARNING << "vSomeIP Security: routing_manager_stub::on_message: "
<< "Routing Manager received a message from client "
<< std::hex << std::setw(4) << std::setfill('0')
@@ -278,6 +250,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
VSOMEIP_WARNING << "Received a OFFER_SERVICE command with wrong size ~> skip!";
break;
}
+
std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
sizeof(its_service));
std::memcpy(&its_instance,
@@ -288,7 +261,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5],
sizeof(its_minor));
- if (configuration_->is_offer_allowed(its_client, its_service, its_instance)) {
+ if (security::get()->is_offer_allowed(its_sender_uid, its_sender_gid,
+ its_client, its_service, its_instance)) {
host_->offer_service(its_client, its_service, its_instance,
its_major, its_minor);
} else {
@@ -331,15 +305,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_eventgroup));
std::memcpy(&its_major, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
sizeof(its_major));
- std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
- sizeof(its_event));
- std::memcpy(&its_subscription_type, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9],
- sizeof(its_subscription_type));
-
- if (its_event == ANY_EVENT) {
- if (host_->is_subscribe_to_any_event_allowed(its_client, its_service, its_instance, its_eventgroup)) {
- host_->subscribe(its_client, its_service, its_instance,
- its_eventgroup, its_major, its_event, its_subscription_type);
+ std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
+ sizeof(its_notifier));
+
+ if (its_notifier == ANY_EVENT) {
+ if (host_->is_subscribe_to_any_event_allowed(_credentials, its_client, its_service,
+ its_instance, its_eventgroup)) {
+ host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance,
+ its_eventgroup, its_major, its_notifier);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_stub::on_message: "
@@ -348,15 +321,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< " which violates the security policy ~> Skip subscribe!";
}
} else {
- if (configuration_->is_client_allowed(its_client,
- its_service, its_instance, its_event)) {
- host_->subscribe(its_client, its_service, its_instance,
- its_eventgroup, its_major, its_event, its_subscription_type);
+ if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_client, its_service, its_instance, its_notifier)) {
+ host_->subscribe(its_client, its_sender_uid, its_sender_gid, its_service, its_instance,
+ its_eventgroup, its_major, its_notifier);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client
<< " : routing_manager_stub::on_message: "
<< " subscribes to service/instance/event "
- << its_service << "/" << its_instance << "/" << its_event
+ << its_service << "/" << its_instance << "/" << its_notifier
<< " which violates the security policy ~> Skip subscribe!";
}
}
@@ -373,11 +346,11 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_instance));
std::memcpy(&its_eventgroup, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
sizeof(its_eventgroup));
- std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(its_event));
+ std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
+ sizeof(its_notifier));
- host_->unsubscribe(its_client, its_service,
- its_instance, its_eventgroup, its_event);
+ host_->unsubscribe(its_client, its_sender_uid, its_sender_gid, its_service,
+ its_instance, its_eventgroup, its_notifier);
break;
case VSOMEIP_SUBSCRIBE_ACK:
@@ -393,18 +366,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_eventgroup));
std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
sizeof(its_subscriber));
- std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- sizeof(its_event));
+ std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(its_notifier));
std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
sizeof(its_subscription_id));
host_->on_subscribe_ack(its_subscriber, its_service,
- its_instance, its_eventgroup, its_event, its_subscription_id);
+ its_instance, its_eventgroup, its_notifier, its_subscription_id);
VSOMEIP_INFO << "SUBSCRIBE ACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_event << "]";
+ << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]";
break;
case VSOMEIP_SUBSCRIBE_NACK:
@@ -420,18 +393,18 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_eventgroup));
std::memcpy(&its_subscriber, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
sizeof(its_subscriber));
- std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
- sizeof(its_event));
+ std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(its_notifier));
std::memcpy(&its_subscription_id, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
sizeof(its_subscription_id));
host_->on_subscribe_nack(its_subscriber, its_service,
- its_instance, its_eventgroup, its_event, its_subscription_id);
+ its_instance, its_eventgroup, its_notifier, its_subscription_id);
VSOMEIP_INFO << "SUBSCRIBE NACK("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_eventgroup << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_event << "]";
+ << std::hex << std::setw(4) << std::setfill('0') << its_notifier << "]";
break;
case VSOMEIP_UNSUBSCRIBE_ACK:
if (_size != VSOMEIP_UNSUBSCRIBE_ACK_COMMAND_SIZE) {
@@ -473,14 +446,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_instance));
std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
sizeof(its_reliable));
- std::memcpy(&its_is_valid_crc, &_data[VSOMEIP_SEND_COMMAND_VALID_CRC_POS],
- sizeof(its_is_valid_crc));
+ std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
+ sizeof(its_check_status));
// Allow response messages from local proxies as answer to remote requests
// but check requests sent by local proxies to remote against policy.
if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
- if (!configuration_->is_client_allowed(its_client_from_header,
- its_service, its_instance, its_method)) {
+ if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_client_from_header, its_service, its_instance, its_method)) {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << its_client_from_header
<< " : routing_manager_stub::on_message: "
<< " isn't allowed to send a request to service/instance/method "
@@ -502,7 +475,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
break;
}
host_->on_message(its_service, its_instance, its_data, its_message_size,
- its_reliable, _bound_client, its_is_valid_crc, false);
+ its_reliable, _bound_client, _credentials, its_check_status, false);
break;
}
case VSOMEIP_NOTIFY: {
@@ -562,8 +535,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
}
case VSOMEIP_REQUEST_SERVICE:
{
- uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t) + sizeof(major_version_t)
- + sizeof(minor_version_t) + sizeof(bool));
+ uint32_t entry_size = (sizeof(service_t) + sizeof(instance_t)
+ + sizeof(major_version_t) + sizeof(minor_version_t));
if (its_size % entry_size > 0) {
VSOMEIP_WARNING << "Received a REQUEST_SERVICE command with invalid size -> skip!";
break;
@@ -575,7 +548,6 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
instance_t its_instance;
major_version_t its_major;
minor_version_t its_minor;
- bool use_exclusive_proxy;
std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + (i * entry_size)],
sizeof(its_service));
std::memcpy(&its_instance,
@@ -585,13 +557,14 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
sizeof(its_major));
std::memcpy(&its_minor, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 5 + (i * entry_size)],
sizeof(its_minor));
- std::memcpy(&use_exclusive_proxy, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 9 + (i * entry_size)],
- sizeof(use_exclusive_proxy));
- if (configuration_->is_client_allowed(its_client, its_service, its_instance, 0x00, true)) {
+ if (security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
+ its_client, its_service, its_instance, 0x00, true)) {
host_->request_service(its_client, its_service, its_instance,
- its_major, its_minor, use_exclusive_proxy);
- service_data_t request = { its_service, its_instance,
- its_major, its_minor, use_exclusive_proxy };
+ its_major, its_minor );
+ service_data_t request = {
+ its_service, its_instance,
+ its_major, its_minor
+ };
requests.insert(request);
} else {
VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex
@@ -601,7 +574,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
<< " which violates the security policy ~> Skip request!";
}
}
- if (configuration_->is_security_enabled()) {
+ if (security::get()->is_enabled()) {
handle_credentials(its_client, requests);
}
handle_requests(its_client, requests);
@@ -622,48 +595,58 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
host_->release_service(its_client, its_service, its_instance);
break;
- case VSOMEIP_REGISTER_EVENT:
+ case VSOMEIP_REGISTER_EVENT: {
if (_size < VSOMEIP_REGISTER_EVENT_COMMAND_SIZE) {
VSOMEIP_WARNING << "Received a REGISTER_EVENT command with wrong size ~> skip!";
break;
}
+
+ std::set<eventgroup_t> its_eventgroups;
+ reliability_type_e its_reliability = reliability_type_e::RT_UNKNOWN;
+
std::memcpy(&its_service,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS],
sizeof(its_service));
std::memcpy(&its_instance,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
sizeof(its_instance));
- std::memcpy(&its_event,
+ std::memcpy(&its_notifier,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_event));
- std::memcpy(&is_field,
+ sizeof(its_notifier));
+ std::memcpy(&its_event_type,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
- sizeof(is_field));
+ sizeof(its_event_type));
std::memcpy(&is_provided,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 7],
sizeof(is_provided));
+ std::memcpy(&its_reliability,
+ &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 8],
+ sizeof(its_reliability));
if (is_provided
&& !configuration_->is_offered_remote(its_service,
its_instance)) {
break;
}
- for (std::size_t i = 8; i+1 < its_size; i++) {
+ for (std::size_t i = 9; i+1 < its_size; i++) {
std::memcpy(&its_eventgroup,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + i],
sizeof(its_eventgroup));
its_eventgroups.insert(its_eventgroup);
}
- host_->register_shadow_event(its_client, its_service,
- its_instance, its_event, its_eventgroups,
- is_field, is_provided);
+ host_->register_shadow_event(its_client,
+ its_service, its_instance,
+ its_notifier, its_eventgroups, its_event_type,
+ its_reliability,
+ is_provided);
VSOMEIP_INFO << "REGISTER EVENT("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_event
- << ":is_provider=" << is_provided << "]";
+ << std::hex << std::setw(4) << std::setfill('0') << its_notifier
+ << ":is_provider=" << is_provided << ":reliability="
+ << (std::uint32_t)(its_reliability) << "]";
break;
-
+ }
case VSOMEIP_UNREGISTER_EVENT:
if (_size != VSOMEIP_UNREGISTER_EVENT_COMMAND_SIZE) {
VSOMEIP_WARNING << "Received a UNREGISTER_EVENT command with wrong size ~> skip!";
@@ -674,8 +657,8 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::memcpy(&its_instance,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
sizeof(its_instance));
- std::memcpy(&its_event, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_event));
+ std::memcpy(&its_notifier, &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
+ sizeof(its_notifier));
std::memcpy(&is_provided,
&_data[VSOMEIP_COMMAND_PAYLOAD_POS + 6],
sizeof(is_provided));
@@ -685,36 +668,15 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
break;
}
host_->unregister_shadow_event(its_client, its_service, its_instance,
- its_event, is_provided);
+ its_notifier, is_provided);
VSOMEIP_INFO << "UNREGISTER EVENT("
<< std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
<< std::hex << std::setw(4) << std::setfill('0') << its_service << "."
<< std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_event
+ << std::hex << std::setw(4) << std::setfill('0') << its_notifier
<< ":is_provider=" << is_provided << "]";
break;
- case VSOMEIP_ID_RESPONSE:
- if (_size != VSOMEIP_ID_RESPONSE_COMMAND_SIZE) {
- VSOMEIP_WARNING << "Received a ID_RESPONSE command with wrong size ~> skip!";
- break;
- }
- std::memcpy(&its_service, &_data[VSOMEIP_COMMAND_PAYLOAD_POS],
- sizeof(its_service));
- std::memcpy(&its_instance,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 2],
- sizeof(its_instance));
- std::memcpy(&its_reliable,
- &_data[VSOMEIP_COMMAND_PAYLOAD_POS + 4],
- sizeof(its_reliable));
- host_->on_identify_response(its_client, its_service, its_instance, its_reliable);
- VSOMEIP_INFO << "ID RESPONSE("
- << std::hex << std::setw(4) << std::setfill('0') << its_client << "): ["
- << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
- << std::hex << std::setw(4) << std::setfill('0') << its_instance
- << ":is_reliable=" << its_reliable << "]";
- break;
-
case VSOMEIP_REGISTERED_ACK:
if (_size != VSOMEIP_REGISTERED_ACK_COMMAND_SIZE) {
VSOMEIP_WARNING << "Received a REGISTERED_ACK command with wrong size ~> skip!";
@@ -735,7 +697,7 @@ void routing_manager_stub::on_message(const byte_t *_data, length_t _size,
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
create_offered_services_info(its_client);
- for (auto found_client : routing_info_) {
+ for (const auto& found_client : routing_info_) {
// skip services which are offered on remote hosts
if (found_client.first != VSOMEIP_ROUTING_CLIENT) {
for (const auto &its_service : found_client.second.second) {
@@ -879,7 +841,7 @@ void routing_manager_stub::client_registration_func(void) {
pending_client_registrations_.clear();
its_lock.unlock();
- for (auto r : its_registrations) {
+ for (const auto& r : its_registrations) {
for (auto b : r.second) {
if (b == registration_type_e::REGISTER) {
on_register_application(r.first);
@@ -921,7 +883,7 @@ void routing_manager_stub::client_registration_func(void) {
}
connection_matrix_.erase(r.first);
}
- for (auto its_client : connection_matrix_) {
+ for (const auto& its_client : connection_matrix_) {
connection_matrix_[its_client.first].erase(r.first);
}
service_requests_.erase(r.first);
@@ -929,9 +891,7 @@ void routing_manager_stub::client_registration_func(void) {
// Don't remove client ID to UID maping as same client
// could have passed its credentials again
host_->remove_local(r.first, false);
- if (b == registration_type_e::DEREGISTER_ON_ERROR) {
- utility::release_client_id(r.first);
- }
+ utility::release_client_id(r.first);
}
}
}
@@ -940,76 +900,8 @@ void routing_manager_stub::client_registration_func(void) {
}
void routing_manager_stub::init_routing_endpoint() {
- std::stringstream its_endpoint_path;
- its_endpoint_path << utility::get_base_path(configuration_) << VSOMEIP_ROUTING_CLIENT;
- endpoint_path_ = its_endpoint_path.str();
- client_t routing_host_id = configuration_->get_id(configuration_->get_routing_host());
- if (configuration_->is_security_enabled() && get_client() != routing_host_id) {
- VSOMEIP_ERROR << __func__ << std::hex << " Client " << get_client() << " isn't allowed"
- << " to create the routing endpoint due to its not configured as the routing master!";
- return;
- }
- uint32_t native_socket_fd, num_fd = 0;
-#ifndef WITHOUT_SYSTEMD
- num_fd = sd_listen_fds(0);
-#endif
- if (num_fd > 1) {
- VSOMEIP_ERROR << "Too many file descriptors received by systemd socket activation! num_fd: " << num_fd;
- } else if (num_fd == 1) {
- native_socket_fd = SD_LISTEN_FDS_START + 0;
- VSOMEIP_INFO << "Using native socket created by systemd socket activation! fd: " << native_socket_fd;
- #ifndef _WIN32
- try {
- endpoint_ =
- std::make_shared < local_server_endpoint_impl
- > (shared_from_this(),
- boost::asio::local::stream_protocol::endpoint(endpoint_path_),
- io_, configuration_->get_max_message_size_local(), native_socket_fd,
- configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local(),
- configuration_->get_permissions_uds());
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
- << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
- VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: "
- << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
- }
- #endif
- is_socket_activated_ = true;
- } else {
- #if _WIN32
- ::_unlink(endpoint_path_.c_str());
- int port = VSOMEIP_INTERNAL_BASE_PORT;
- VSOMEIP_INFO << "Routing endpoint at " << port;
- #else
- if (-1 == ::unlink(endpoint_path_.c_str()) && errno != ENOENT) {
- VSOMEIP_ERROR << "routing_manager_stub::init_endpoint unlink failed ("
- << endpoint_path_ << "): "<< std::strerror(errno);
- }
- VSOMEIP_INFO << "init_routing_endpoint Routing endpoint at " << endpoint_path_;
- #endif
-
- try {
- endpoint_ =
- std::make_shared < local_server_endpoint_impl
- > (shared_from_this(),
- #ifdef _WIN32
- boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port),
- #else
- boost::asio::local::stream_protocol::endpoint(endpoint_path_),
- #endif
- io_, configuration_->get_max_message_size_local(),
- configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local(),
- configuration_->get_permissions_uds());
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
- << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
- VSOMEIP_ERROR << "routing_manager_stub::init_routing_endpoint Client ID: "
- << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
- }
- is_socket_activated_ = false;
- }
+ endpoint_ = host_->get_endpoint_manager()->create_local_server(
+ &is_socket_activated_, shared_from_this());
}
void routing_manager_stub::on_offer_service(client_t _client,
@@ -1018,22 +910,13 @@ void routing_manager_stub::on_offer_service(client_t _client,
create_local_receiver();
}
- if (_client == VSOMEIP_ROUTING_CLIENT ||
- configuration_->is_offer_allowed(_client, _service, _instance)) {
- std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
- if (configuration_->is_security_enabled()) {
- distribute_credentials(_client, _service, _instance);
- }
- inform_requesters(_client, _service, _instance, _major, _minor,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, true);
- } else {
- VSOMEIP_WARNING << "vSomeIP Security: Client 0x" << std::hex << _client
- << " : routing_manager_stub::on_offer_service: "
- << "isn't allowed to offer the following service/instance "
- << _service << "/" << _instance
- << " ~> Skip offer!";
+ std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
+ routing_info_[_client].second[_service][_instance] = std::make_pair(_major, _minor);
+ if (security::get()->is_enabled()) {
+ distribute_credentials(_client, _service, _instance);
}
+ inform_requesters(_client, _service, _instance, _major, _minor,
+ routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE, true);
}
void routing_manager_stub::on_stop_offer_service(client_t _client,
@@ -1155,7 +1038,7 @@ void routing_manager_stub::send_client_credentials_info(const client_t _target)
// Send routing info or error!
if(its_command.size() <= max_local_message_size_
|| VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size), true);
+ its_endpoint->send(&its_command[0], uint32_t(its_size));
} else {
VSOMEIP_ERROR << "Credentials info exceeds maximum message size: Can't send!";
}
@@ -1212,7 +1095,7 @@ void routing_manager_stub::send_client_routing_info(const client_t _target) {
// Send routing info or error!
if(its_command.size() <= max_local_message_size_
|| VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size), true);
+ its_endpoint->send(&its_command[0], uint32_t(its_size));
} else {
VSOMEIP_ERROR << "Routing info exceeds maximum message size: Can't send!";
}
@@ -1249,7 +1132,7 @@ void routing_manager_stub::send_offered_services_info(const client_t _target) {
// Send routing info or error!
if(its_command.size() <= max_local_message_size_
|| VSOMEIP_MAX_LOCAL_MESSAGE_SIZE == 0) {
- its_endpoint->send(&its_command[0], uint32_t(its_size), true);
+ its_endpoint->send(&its_command[0], uint32_t(its_size));
} else {
VSOMEIP_ERROR << "Offered services info exceeds maximum message size: Can't send!";
}
@@ -1406,10 +1289,10 @@ void routing_manager_stub::distribute_credentials(client_t _hoster, service_t _s
// search for UID / GID linked with the client ID that offers the requested services
std::pair<uint32_t, uint32_t> its_uid_gid;
- if (configuration_->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
+ if (security::get()->get_client_to_uid_gid_mapping(_hoster, its_uid_gid)) {
for (auto its_requesting_client : its_requesting_clients) {
std::pair<uint32_t, uint32_t> its_requester_uid_gid;
- if (configuration_->get_client_to_uid_gid_mapping(its_requesting_client, its_requester_uid_gid)) {
+ if (security::get()->get_client_to_uid_gid_mapping(its_requesting_client, its_requester_uid_gid)) {
if (its_uid_gid != its_requester_uid_gid) {
its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
create_client_credentials_info(its_requesting_client);
@@ -1465,21 +1348,21 @@ bool routing_manager_stub::is_already_connected(client_t _source, client_t _sink
void routing_manager_stub::broadcast(const std::vector<byte_t> &_command) const {
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
- for (auto a : routing_info_) {
+ for (const auto& a : routing_info_) {
if (a.first != VSOMEIP_ROUTING_CLIENT && a.first != host_->get_client()) {
std::shared_ptr<endpoint> its_endpoint
= host_->find_local(a.first);
if (its_endpoint) {
- its_endpoint->send(&_command[0], uint32_t(_command.size()), true);
+ its_endpoint->send(&_command[0], uint32_t(_command.size()));
}
}
}
}
-bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _target,
+bool routing_manager_stub::send_subscribe(const std::shared_ptr<endpoint>& _target,
client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, major_version_t _major,
- event_t _event, pending_subscription_id_t _subscription_id) {
+ event_t _event, remote_subscription_id_t _id) {
if (_target) {
byte_t its_command[VSOMEIP_SUBSCRIBE_COMMAND_SIZE];
uint32_t its_size = VSOMEIP_SUBSCRIBE_COMMAND_SIZE
@@ -1498,11 +1381,8 @@ bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _ta
its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6] = _major;
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 7], &_event,
sizeof(_event));
- // set byte for subscription_type to zero. It's only used
- // in subscribe messages sent from rm_proxies to rm_stub.
- its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9] = 0x0;
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &_subscription_id, sizeof(_subscription_id));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 9], &_id,
+ sizeof(_id));
return _target->send(its_command, sizeof(its_command));
} else {
@@ -1517,10 +1397,11 @@ bool routing_manager_stub::send_subscribe(std::shared_ptr<vsomeip::endpoint> _ta
}
}
-bool routing_manager_stub::send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _target,
+bool routing_manager_stub::send_unsubscribe(
+ const std::shared_ptr<endpoint>& _target,
client_t _client, service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event,
- pending_subscription_id_t _unsubscription_id) {
+ remote_subscription_id_t _id) {
if (_target) {
byte_t its_command[VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE];
uint32_t its_size = VSOMEIP_UNSUBSCRIBE_COMMAND_SIZE
@@ -1538,8 +1419,8 @@ bool routing_manager_stub::send_unsubscribe(std::shared_ptr<vsomeip::endpoint> _
sizeof(_eventgroup));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 6], &_event,
sizeof(_event));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_unsubscription_id,
- sizeof(_unsubscription_id));
+ std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_id,
+ sizeof(_id));
return _target->send(its_command, sizeof(its_command));
} else {
@@ -1580,9 +1461,9 @@ void routing_manager_stub::send_subscribe_ack(client_t _client, service_t _servi
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION));
+ &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
- its_endpoint->send(&its_command[0], sizeof(its_command), true);
+ its_endpoint->send(&its_command[0], sizeof(its_command));
}
}
@@ -1612,9 +1493,9 @@ void routing_manager_stub::send_subscribe_nack(client_t _client, service_t _serv
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 8], &_event,
sizeof(_event));
std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 10],
- &DEFAULT_SUBSCRIPTION, sizeof(DEFAULT_SUBSCRIPTION));
+ &PENDING_SUBSCRIPTION_ID, sizeof(PENDING_SUBSCRIPTION_ID));
- its_endpoint->send(&its_command[0], sizeof(its_command), true);
+ its_endpoint->send(&its_command[0], sizeof(its_command));
}
}
@@ -1691,7 +1572,7 @@ void routing_manager_stub::check_watchdog() {
std::list< client_t > lost;
{
std::lock_guard<std::mutex> its_lock(routing_info_mutex_);
- for (auto i : routing_info_) {
+ for (const auto& i : routing_info_) {
if (i.first > 0 && i.first != host_->get_client()) {
if (i.second.first > configuration_->get_allowed_missing_pongs()) {
VSOMEIP_WARNING << "Lost contact to application " << std::hex << (int)i.first;
@@ -1720,43 +1601,16 @@ void routing_manager_stub::create_local_receiver() {
if (local_receiver_) {
return;
}
- std::stringstream its_local_receiver_path;
- its_local_receiver_path << utility::get_base_path(configuration_) << std::hex << host_->get_client();
- local_receiver_path_ = its_local_receiver_path.str();
-#if _WIN32
- ::_unlink(local_receiver_path_.c_str());
- int port = VSOMEIP_INTERNAL_BASE_PORT;
-#else
- if (!check_credentials(get_client(), getuid(), getgid())) {
+#ifndef _WIN32
+ else if (!security::get()->check_credentials(get_client(), getuid(), getgid())) {
VSOMEIP_ERROR << "vSomeIP Security: Client 0x" << std::hex << get_client()
<< " : routing_manager_stub::create_local_receiver: isn't allowed"
<< " to create a server endpoint due to credential check failed!";
return;
}
- if (-1 == ::unlink(local_receiver_path_.c_str()) && errno != ENOENT) {
- VSOMEIP_ERROR << "routing_manager_stub::create_local_receiver unlink (local receiver) failed ("
- << local_receiver_path_ << "): "<< std::strerror(errno);
- }
#endif
- try {
- local_receiver_ =
- std::make_shared < local_server_endpoint_impl
- > (shared_from_this(),
- #ifdef _WIN32
- boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port + host_->get_client()),
- #else
- boost::asio::local::stream_protocol::endpoint(local_receiver_path_),
- #endif
- io_, configuration_->get_max_message_size_local(),
- configuration_->get_buffer_shrink_threshold(),
- configuration_->get_endpoint_queue_limit_local(),
- configuration_->get_permissions_uds());
- } catch (const std::exception &e) {
- VSOMEIP_ERROR << ERROR_INFO[static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED)]
- << " (" << static_cast<int>(error_code_e::SERVER_ENDPOINT_CREATION_FAILED) << ")";
- VSOMEIP_ERROR << "routing_manager_stub::_local_receiver Client ID: "
- << std::hex << VSOMEIP_ROUTING_CLIENT << ": " << e.what();
- }
+ local_receiver_ = std::static_pointer_cast<endpoint_manager_base>(
+ host_->get_endpoint_manager())->create_local_server(shared_from_this());
local_receiver_->start();
}
@@ -1805,8 +1659,7 @@ bool routing_manager_stub::send_ping(client_t _client) {
pinged_clients_timer_.async_wait(
std::bind(&routing_manager_stub::on_ping_timer_expired, this,
std::placeholders::_1));
- return its_endpoint->send(&its_ping_[0], uint32_t(its_ping_.size()),
- true);
+ return its_endpoint->send(&its_ping_[0], uint32_t(its_ping_.size()));
}
}
@@ -1904,7 +1757,7 @@ void routing_manager_stub::remove_from_pinged_clients(client_t _client) {
}
pinged_clients_timer_.async_wait(
std::bind(&routing_manager_stub::on_ping_timer_expired, this,
- std::placeholders::_1));
+ std::placeholders::_1));
}
bool routing_manager_stub::is_registered(client_t _client) const {
@@ -1922,7 +1775,7 @@ void routing_manager_stub::update_registration(client_t _client,
"registering." : "deregistering.");
if (_type != registration_type_e::REGISTER) {
- configuration_->remove_client_to_uid_gid_mapping(_client);
+ security::get()->remove_client_to_uid_gid_mapping(_client);
}
if (_type == registration_type_e::DEREGISTER) {
@@ -1968,7 +1821,7 @@ void routing_manager_stub::handle_credentials(const client_t _client, std::set<s
std::lock_guard<std::mutex> its_guard(routing_info_mutex_);
std::set<std::pair<uint32_t, uint32_t>> its_credentials;
std::pair<uint32_t, uint32_t> its_requester_uid_gid;
- if (configuration_->get_client_to_uid_gid_mapping(_client, its_requester_uid_gid)) {
+ if (security::get()->get_client_to_uid_gid_mapping(_client, its_requester_uid_gid)) {
// determine credentials of offering clients using current routing info
std::set<client_t> its_offering_clients;
@@ -1984,7 +1837,7 @@ void routing_manager_stub::handle_credentials(const client_t _client, std::set<s
// search for UID / GID linked with the client ID that offers the requested services
for (auto its_offering_client : its_offering_clients) {
std::pair<uint32_t, uint32_t> its_uid_gid;
- if (configuration_->get_client_to_uid_gid_mapping(its_offering_client, its_uid_gid)) {
+ if (security::get()->get_client_to_uid_gid_mapping(its_offering_client, its_uid_gid)) {
if (its_uid_gid != its_requester_uid_gid) {
its_credentials.insert(std::make_pair(std::get<0>(its_uid_gid), std::get<1>(its_uid_gid)));
}
@@ -2010,51 +1863,63 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
for (auto request : _requests) {
service_requests_[_client][request.service_][request.instance_]
= std::make_pair(request.major_, request.minor_);
- for (auto found_client : routing_info_) {
- auto found_service = found_client.second.second.find(request.service_);
- if (found_service != found_client.second.second.end()) {
- if (request.instance_ == ANY_INSTANCE) {
- if (found_client.first != VSOMEIP_ROUTING_CLIENT &&
- found_client.first != host_->get_client()) {
- if (!is_already_connected(found_client.first, _client)) {
- if (_client == found_client.first) {
- service_available = true;
- insert_client_routing_info(found_client.first,
+ if (request.instance_ == ANY_INSTANCE) {
+ std::set<client_t> its_clients = host_->find_local_clients(request.service_, request.instance_);
+ // insert VSOMEIP_ROUTING_CLIENT to check wether service is remotely offered
+ its_clients.insert(VSOMEIP_ROUTING_CLIENT);
+ for (const client_t c : its_clients) {
+ if (c != VSOMEIP_ROUTING_CLIENT &&
+ c != host_->get_client()) {
+ if (!is_already_connected(c, _client)) {
+ if (_client == c) {
+ service_available = true;
+ insert_client_routing_info(c,
+ routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ } else {
+ create_client_routing_info(c);
+ insert_client_routing_info(c,
routing_info_entry_e::RIE_ADD_CLIENT, _client);
- } else {
- create_client_routing_info(found_client.first);
- insert_client_routing_info(found_client.first,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
- send_client_routing_info(found_client.first);
- }
+ send_client_routing_info(c);
}
}
- if (_client != VSOMEIP_ROUTING_CLIENT &&
- _client != host_->get_client()) {
- for (auto instance : found_service->second) {
- service_available = true;
- insert_client_routing_info(_client,
- routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- found_client.first, request.service_, instance.first,
- instance.second.first, instance.second.second);
+ }
+ if (_client != VSOMEIP_ROUTING_CLIENT &&
+ _client != host_->get_client()) {
+ const auto found_client = routing_info_.find(c);
+ if (found_client != routing_info_.end()) {
+ const auto found_service = found_client->second.second.find(request.service_);
+ if (found_service != found_client->second.second.end()) {
+ for (auto instance : found_service->second) {
+ service_available = true;
+ insert_client_routing_info(_client,
+ routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
+ c, request.service_, instance.first,
+ instance.second.first, instance.second.second);
+ }
}
}
- break;
- } else {
- auto found_instance = found_service->second.find(request.instance_);
+ }
+ }
+ } else {
+ const client_t c = host_->find_local_client(request.service_, request.instance_);
+ const auto found_client = routing_info_.find(c);
+ if (found_client != routing_info_.end()) {
+ const auto found_service = found_client->second.second.find(request.service_);
+ if (found_service != found_client->second.second.end()) {
+ const auto found_instance = found_service->second.find(request.instance_);
if (found_instance != found_service->second.end()) {
- if (found_client.first != VSOMEIP_ROUTING_CLIENT &&
- found_client.first != host_->get_client()) {
- if (!is_already_connected(found_client.first, _client)) {
- if (_client == found_client.first) {
+ if (c != VSOMEIP_ROUTING_CLIENT &&
+ c != host_->get_client()) {
+ if (!is_already_connected(c, _client)) {
+ if (_client == c) {
service_available = true;
- insert_client_routing_info(found_client.first,
- routing_info_entry_e::RIE_ADD_CLIENT, _client);
+ insert_client_routing_info(c,
+ routing_info_entry_e::RIE_ADD_CLIENT, _client);
} else {
- create_client_routing_info(found_client.first);
- insert_client_routing_info(found_client.first,
+ create_client_routing_info(c);
+ insert_client_routing_info(c,
routing_info_entry_e::RIE_ADD_CLIENT, _client);
- send_client_routing_info(found_client.first);
+ send_client_routing_info(c);
}
}
}
@@ -2063,11 +1928,10 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
service_available = true;
insert_client_routing_info(_client,
routing_info_entry_e::RIE_ADD_SERVICE_INSTANCE,
- found_client.first, request.service_, request.instance_,
+ c, request.service_, request.instance_,
found_instance->second.first,
found_instance->second.second);
}
- break;
}
}
}
@@ -2078,37 +1942,6 @@ void routing_manager_stub::handle_requests(const client_t _client, std::set<serv
}
}
-#ifndef _WIN32
-bool routing_manager_stub::check_credentials(client_t _client, uid_t _uid, gid_t _gid) {
- return configuration_->check_credentials(_client, _uid, _gid);
-}
-#endif
-
-void routing_manager_stub::send_identify_request_command(std::shared_ptr<vsomeip::endpoint> _target,
- service_t _service, instance_t _instance, major_version_t _major, bool _reliable) {
- if (_target) {
- byte_t its_command[VSOMEIP_ID_REQUEST_COMMAND_SIZE];
- uint32_t its_size = VSOMEIP_ID_REQUEST_COMMAND_SIZE
- - VSOMEIP_COMMAND_HEADER_SIZE;
- its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_ID_REQUEST;
- client_t client = get_client();
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &client,
- sizeof(client));
- std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
- sizeof(its_size));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS], &_service,
- sizeof(_service));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 2], &_instance,
- sizeof(_instance));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 4], &_major,
- sizeof(_major));
- std::memcpy(&its_command[VSOMEIP_COMMAND_PAYLOAD_POS + 5], &_reliable,
- sizeof(_reliable));
-
- _target->send(its_command, sizeof(its_command));
- }
-}
-
void routing_manager_stub::on_client_id_timer_expired(boost::system::error_code const &_error) {
std::set<client_t> used_client_ids;
{
@@ -2152,8 +1985,9 @@ bool routing_manager_stub::send_provided_event_resend_request(client_t _client,
if (its_endpoint) {
byte_t its_command[VSOMEIP_RESEND_PROVIDED_EVENTS_COMMAND_SIZE];
its_command[VSOMEIP_COMMAND_TYPE_POS] = VSOMEIP_RESEND_PROVIDED_EVENTS;
- std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &_client,
- sizeof(client_t));
+ const client_t routing_client(VSOMEIP_ROUTING_CLIENT);
+ std::memcpy(&its_command[VSOMEIP_COMMAND_CLIENT_POS], &routing_client,
+ sizeof(routing_client));
std::uint32_t its_size = sizeof(pending_remote_offer_id_t);
std::memcpy(&its_command[VSOMEIP_COMMAND_SIZE_POS_MIN], &its_size,
sizeof(its_size));
@@ -2182,7 +2016,7 @@ bool routing_manager_stub::is_policy_cached(uint32_t _uid) {
}
}
-void routing_manager_stub::policy_cache_add(uint32_t _uid, std::shared_ptr<payload> _payload) {
+void routing_manager_stub::policy_cache_add(uint32_t _uid, const std::shared_ptr<payload>& _payload) {
// cache security policy payload for later distribution to new registering clients
{
std::lock_guard<std::mutex> its_lock(updated_security_policies_mutex_);
@@ -2198,7 +2032,8 @@ void routing_manager_stub::policy_cache_remove(uint32_t _uid) {
}
bool routing_manager_stub::send_update_security_policy_request(client_t _client, pending_security_update_id_t _update_id,
- uint32_t _uid, std::shared_ptr<payload> _payload) {
+ uint32_t _uid, const std::shared_ptr<payload>& _payload) {
+ (void)_uid;
std::shared_ptr<endpoint> its_endpoint = host_->find_local(_client);
if (its_endpoint) {
std::vector<byte_t> its_command;
@@ -2269,7 +2104,7 @@ bool routing_manager_stub::send_cached_security_policies(client_t _client) {
reinterpret_cast<const byte_t*>(&its_policy_count)[i]);
}
- for (auto its_uid_gid : updated_security_policies_) {
+ for (const auto& its_uid_gid : updated_security_policies_) {
// policy payload length including gid and uid
std::uint32_t its_length = uint32_t(its_uid_gid.second->get_length());
for (uint32_t i = 0; i < sizeof(its_length); ++i) {
@@ -2318,4 +2153,4 @@ bool routing_manager_stub::send_remove_security_policy_request( client_t _client
}
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/routing/src/serviceinfo.cpp b/implementation/routing/src/serviceinfo.cpp
index 42db53b..324fcd7 100644
--- a/implementation/routing/src/serviceinfo.cpp
+++ b/implementation/routing/src/serviceinfo.cpp
@@ -5,11 +5,14 @@
#include "../include/serviceinfo.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
-serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
- ttl_t _ttl, bool _is_local)
+serviceinfo::serviceinfo(service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ ttl_t _ttl, bool _is_local)
: group_(0),
+ service_(_service),
+ instance_(_instance),
major_(_major),
minor_(_minor),
ttl_(0),
@@ -24,6 +27,8 @@ serviceinfo::serviceinfo(major_version_t _major, minor_version_t _minor,
serviceinfo::serviceinfo(const serviceinfo& _other) :
group_(_other.group_),
+ service_(_other.service_),
+ instance_(_other.instance_),
major_(_other.major_),
minor_(_other.minor_),
ttl_(_other.ttl_),
@@ -45,6 +50,14 @@ void serviceinfo::set_group(servicegroup *_group) {
group_ = _group;
}
+service_t serviceinfo::get_service() const {
+ return service_;
+}
+
+instance_t serviceinfo::get_instance() const {
+ return instance_;
+}
+
major_version_t serviceinfo::get_major() const {
return major_;
}
@@ -80,7 +93,7 @@ std::shared_ptr<endpoint> serviceinfo::get_endpoint(bool _reliable) const {
return (_reliable ? reliable_ : unreliable_);
}
-void serviceinfo::set_endpoint(std::shared_ptr<endpoint> _endpoint,
+void serviceinfo::set_endpoint(const std::shared_ptr<endpoint>& _endpoint,
bool _reliable) {
std::lock_guard<std::mutex> its_lock(endpoint_mutex_);
if (_reliable) {
@@ -117,5 +130,4 @@ void serviceinfo::set_is_in_mainphase(bool _in_mainphase) {
is_in_mainphase_ = _in_mainphase;
}
-} // namespace vsomeip
-
+} // namespace vsomeip_v3
diff --git a/implementation/runtime/include/application_impl.hpp b/implementation/runtime/include/application_impl.hpp
index fe23c90..b439501 100644
--- a/implementation/runtime/include/application_impl.hpp
+++ b/implementation/runtime/include/application_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_APPLICATION_IMPL_HPP
-#define VSOMEIP_APPLICATION_IMPL_HPP
+#ifndef VSOMEIP_V3_APPLICATION_IMPL_HPP_
+#define VSOMEIP_V3_APPLICATION_IMPL_HPP_
#include <atomic>
#include <condition_variable>
@@ -22,10 +22,14 @@
#include <vsomeip/export.hpp>
#include <vsomeip/application.hpp>
-#include "../../routing/include/routing_manager_host.hpp"
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+#include "../../routing/include/routing_manager_host.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class runtime;
class configuration;
@@ -40,49 +44,47 @@ public:
VSOMEIP_EXPORT application_impl(const std::string &_name);
VSOMEIP_EXPORT ~application_impl();
- VSOMEIP_EXPORT void set_configuration(const std::shared_ptr<configuration> _configuration);
-
VSOMEIP_EXPORT bool init();
VSOMEIP_EXPORT void start();
VSOMEIP_EXPORT void stop();
+ VSOMEIP_EXPORT void process(int _number);
+
+ VSOMEIP_EXPORT security_mode_e get_security_mode() const;
// Provide services / events
VSOMEIP_EXPORT void offer_service(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor);
VSOMEIP_EXPORT void stop_offer_service(service_t _service, instance_t _instance,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR);
+ major_version_t _major, minor_version_t _minor);
- VSOMEIP_EXPORT void offer_event(service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups,
- bool _is_field);
- VSOMEIP_EXPORT void offer_event(service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups,
- bool _is_field,
+ VSOMEIP_EXPORT void offer_event(service_t _service, instance_t _instance,
+ event_t _notifier,
+ const std::set<eventgroup_t> &_eventgroups, event_type_e _type,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
- const epsilon_change_func_t &_epsilon_change_func);
+ bool _update_on_change,
+ const epsilon_change_func_t &_epsilon_change_func,
+ reliability_type_e _reliability);
+
VSOMEIP_EXPORT void stop_offer_event(service_t _service,
instance_t _instance, event_t _event);
// Consume services / events
- VSOMEIP_EXPORT void request_service(service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _use_exclusive_proxy);
- VSOMEIP_EXPORT void release_service(service_t _service,
- instance_t _instance);
+ VSOMEIP_EXPORT void request_service(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor);
+ VSOMEIP_EXPORT void release_service(
+ service_t _service, instance_t _instance);
VSOMEIP_EXPORT void request_event(service_t _service,
instance_t _instance, event_t _event,
const std::set<eventgroup_t> &_eventgroups,
- bool _is_field);
+ event_type_e _type, reliability_type_e _reliability);
VSOMEIP_EXPORT void release_event(service_t _service,
instance_t _instance, event_t _event);
VSOMEIP_EXPORT void subscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major,
- subscription_type_e _subscription_type, event_t _event);
+ eventgroup_t _eventgroup, major_version_t _major, event_t _event);
VSOMEIP_EXPORT void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup);
@@ -90,27 +92,17 @@ public:
eventgroup_t _eventgroup, event_t _event);
VSOMEIP_EXPORT bool is_available(service_t _service, instance_t _instance,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) const;
+ major_version_t _major, minor_version_t _minor) const;
- VSOMEIP_EXPORT void send(std::shared_ptr<message> _message, bool _flush);
+ VSOMEIP_EXPORT void send(std::shared_ptr<message> _message);
VSOMEIP_EXPORT void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload) const;
- VSOMEIP_EXPORT void notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload,
bool _force) const;
- VSOMEIP_EXPORT void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- bool _force, bool _flush) const;
VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, client_t _client) const;
- VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, client_t _client,
bool _force) const;
- VSOMEIP_EXPORT void notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, client_t _client,
- bool _force, bool _flush) const;
VSOMEIP_EXPORT void register_state_handler(state_handler_t _handler);
VSOMEIP_EXPORT void unregister_state_handler();
@@ -122,58 +114,53 @@ public:
VSOMEIP_EXPORT void register_availability_handler(service_t _service,
instance_t _instance, availability_handler_t _handler,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR);
+ major_version_t _major, minor_version_t _minor);
VSOMEIP_EXPORT void unregister_availability_handler(service_t _service,
instance_t _instance,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR);
+ major_version_t _major, minor_version_t _minor);
VSOMEIP_EXPORT void register_subscription_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, subscription_handler_t _handler);
VSOMEIP_EXPORT void unregister_subscription_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup);
- VSOMEIP_EXPORT void register_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- error_handler_t _handler);
- VSOMEIP_EXPORT void unregister_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup);
-
VSOMEIP_EXPORT bool is_routing() const;
// routing_manager_host
VSOMEIP_EXPORT const std::string & get_name() const;
VSOMEIP_EXPORT client_t get_client() const;
+ VSOMEIP_EXPORT void set_client(const client_t &_client);
+ VSOMEIP_EXPORT session_t get_session();
+ VSOMEIP_EXPORT diagnosis_t get_diagnosis() const;
VSOMEIP_EXPORT std::shared_ptr<configuration> get_configuration() const;
+ VSOMEIP_EXPORT std::shared_ptr<configuration_public> get_public_configuration() const;
VSOMEIP_EXPORT boost::asio::io_service & get_io();
VSOMEIP_EXPORT void on_state(state_type_e _state);
VSOMEIP_EXPORT void on_availability(service_t _service, instance_t _instance,
bool _is_available, major_version_t _major, minor_version_t _minor);
- VSOMEIP_EXPORT void on_message(const std::shared_ptr<message> &&_message);
- VSOMEIP_EXPORT void on_error(error_code_e _error);
+ VSOMEIP_EXPORT void on_message(std::shared_ptr<message> &&_message);
VSOMEIP_EXPORT void on_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client, bool _subscribed, std::function<void(bool)> _accepted_cb);
- VSOMEIP_EXPORT void on_subscription_error(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, uint16_t _error);
+ eventgroup_t _eventgroup, client_t _client, uid_t _uid, gid_t _gid, bool _subscribed,
+ std::function<void(bool)> _accepted_cb);
VSOMEIP_EXPORT void on_subscription_status(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event, uint16_t _error);
VSOMEIP_EXPORT void register_subscription_status_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- subscription_status_handler_t _handler);
+ subscription_status_handler_t _handler, bool _is_selective);
+ VSOMEIP_EXPORT void unregister_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event);
// service_discovery_host
VSOMEIP_EXPORT routing_manager * get_routing_manager() const;
VSOMEIP_EXPORT bool are_available(available_t &_available,
- service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
- major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const;
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor) const;
VSOMEIP_EXPORT void set_routing_state(routing_state_e _routing_state);
VSOMEIP_EXPORT void clear_all_handler();
- VSOMEIP_EXPORT void register_subscription_status_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- subscription_status_handler_t _handler, bool _is_selective);
VSOMEIP_EXPORT void get_offered_services_async(offer_type_e _offer_type, offered_services_handler_t _handler);
@@ -184,10 +171,13 @@ public:
VSOMEIP_EXPORT void register_async_subscription_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, async_subscription_handler_t _handler);
- VSOMEIP_EXPORT void set_offer_acceptance_required(ip_address_t _address, const std::string _path, bool _enable);
- VSOMEIP_EXPORT offer_acceptance_map_type_t get_offer_acceptance_required();
+ VSOMEIP_EXPORT void set_sd_acceptance_required(const remote_info_t& _remote,
+ const std::string& _path, bool _enable);
+ VSOMEIP_EXPORT void set_sd_acceptance_required(
+ const sd_acceptance_map_type_t& _remotes, bool _enable);
+ VSOMEIP_EXPORT sd_acceptance_map_type_t get_sd_acceptance_required();
- VSOMEIP_EXPORT void register_offer_acceptance_handler(offer_acceptance_handler_t _handler);
+ VSOMEIP_EXPORT void register_sd_acceptance_handler(sd_acceptance_handler_t _handler);
VSOMEIP_EXPORT void register_reboot_notification_handler(reboot_notification_handler_t _handler);
@@ -209,6 +199,7 @@ public:
VSOMEIP_EXPORT void remove_security_policy_configuration(uint32_t _uid,
uint32_t _gid,
security_update_handler_t _handler);
+
private:
//
// Types
@@ -269,13 +260,6 @@ private:
//
// Methods
//
- inline void update_session() {
- session_++;
- if (0 == session_) {
- session_++;
- }
- }
-
bool is_available_unlocked(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor) const;
@@ -315,7 +299,7 @@ private:
bool check_subscription_state(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event);
- void print_blocking_call(std::shared_ptr<sync_handler> _handler);
+ void print_blocking_call(const std::shared_ptr<sync_handler>& _handler);
void watchdog_cbk(boost::system::error_code const &_error);
@@ -323,7 +307,7 @@ private:
// Attributes
//
std::shared_ptr<runtime> runtime_;
- client_t client_; // unique application identifier
+ std::atomic<client_t> client_; // unique application identifier
session_t session_;
std::mutex session_mutex_;
@@ -347,6 +331,9 @@ private:
std::mutex state_handler_mutex_;
state_handler_t handler_;
+ // vsomeip security mode
+ security_mode_e security_mode_;
+
// vsomeip offered services handler
std::mutex offered_services_handler_mutex_;
offered_services_handler_t offered_services_handler_;
@@ -447,8 +434,11 @@ private:
std::map<std::pair<service_t, instance_t>,
std::deque<std::shared_ptr<sync_handler> > > availability_handlers_;
+
+ uid_t own_uid_;
+ gid_t own_gid_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_APPLICATION_IMPL_HPP
+#endif // VSOMEIP_V3_APPLICATION_IMPL_HPP_
diff --git a/implementation/runtime/include/runtime_impl.hpp b/implementation/runtime/include/runtime_impl.hpp
index c376e6d..ec49a42 100644
--- a/implementation/runtime/include/runtime_impl.hpp
+++ b/implementation/runtime/include/runtime_impl.hpp
@@ -3,14 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_RUNTIME_IMPL_HPP
-#define VSOMEIP_RUNTIME_IMPL_HPP
+#ifndef VSOMEIP_V3_RUNTIME_IMPL_HPP_
+#define VSOMEIP_V3_RUNTIME_IMPL_HPP_
#include <vsomeip/runtime.hpp>
#include <map>
#include <mutex>
-namespace vsomeip {
+namespace vsomeip_v3 {
class runtime_impl: public runtime {
public:
@@ -43,15 +43,13 @@ public:
void remove_application( const std::string &_name);
private:
- static std::shared_ptr<runtime> the_runtime_;
static std::map<std::string, std::string> properties_;
std::map<std::string, std::weak_ptr<application>> applications_;
mutable std::mutex applications_mutex_;
- static uint32_t postfix_id;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_RUNTIME_IMPL_HPP
+#endif // VSOMEIP_V3_RUNTIME_IMPL_HPP_
diff --git a/implementation/runtime/src/application_impl.cpp b/implementation/runtime/src/application_impl.cpp
index a3040c3..0018340 100644
--- a/implementation/runtime/src/application_impl.cpp
+++ b/implementation/runtime/src/application_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -7,6 +7,8 @@
#include <thread>
#include <iomanip>
#include <iostream>
+
+#include <boost/exception/diagnostic_information.hpp>
#include <boost/log/exceptions.hpp>
#ifndef _WIN32
@@ -18,32 +20,42 @@
#include <vsomeip/runtime.hpp>
#include <vsomeip/plugins/application_plugin.hpp>
#include <vsomeip/plugins/pre_configuration_plugin.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/application_impl.hpp"
+#ifdef VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
+#include "../../configuration/include/configuration_impl.hpp"
+#else
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
+#include "../../configuration/include/configuration_plugin.hpp"
+#endif // VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
#include "../../message/include/serializer.hpp"
#include "../../routing/include/routing_manager_impl.hpp"
#include "../../routing/include/routing_manager_proxy.hpp"
#include "../../utility/include/utility.hpp"
#include "../../tracing/include/connector_impl.hpp"
-#include "../../plugin/include/plugin_manager.hpp"
+#include "../../plugin/include/plugin_manager_impl.hpp"
#include "../../endpoints/include/endpoint.hpp"
+#include "../../security/include/security.hpp"
+
+namespace vsomeip_v3 {
-namespace vsomeip {
+#ifdef ANDROID
+configuration::~configuration() {}
+#endif
uint32_t application_impl::app_counter__ = 0;
std::mutex application_impl::app_counter_mutex__;
application_impl::application_impl(const std::string &_name)
: runtime_(runtime::get()),
- client_(ILLEGAL_CLIENT),
- session_(1),
+ client_(VSOMEIP_CLIENT_UNSET),
+ session_(0),
is_initialized_(false), name_(_name),
work_(std::make_shared<boost::asio::io_service::work>(io_)),
routing_(0),
state_(state_type_e::ST_DEREGISTERED),
+ security_mode_(security_mode_e::SM_OFF),
#ifdef VSOMEIP_ENABLE_SIGNAL_HANDLING
signals_(io_, SIGINT, SIGTERM),
catched_signal_(false),
@@ -58,6 +70,12 @@ application_impl::application_impl(const std::string &_name)
stopped_called_(false),
watchdog_timer_(io_),
client_side_logging_(false) {
+ own_uid_ = ANY_UID;
+ own_gid_ = ANY_GID;
+#ifndef _WIN32
+ own_uid_ = getuid();
+ own_gid_ = getgid();
+#endif
}
application_impl::~application_impl() {
@@ -72,7 +90,7 @@ application_impl::~application_impl() {
try {
std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
- for (auto t : io_threads_) {
+ for (const auto& t : io_threads_) {
if (t->joinable()) {
t->detach();
}
@@ -84,7 +102,7 @@ application_impl::~application_impl() {
try {
std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- for (auto its_dispatcher : dispatchers_) {
+ for (const auto& its_dispatcher : dispatchers_) {
if (its_dispatcher.second->joinable()) {
its_dispatcher.second->detach();
}
@@ -95,12 +113,6 @@ application_impl::~application_impl() {
}
}
-void application_impl::set_configuration(
- const std::shared_ptr<configuration> _configuration) {
- (void)_configuration;
- // Dummy.
-}
-
bool application_impl::init() {
if(is_initialized_) {
VSOMEIP_WARNING << "Trying to initialize an already initialized application.";
@@ -122,19 +134,43 @@ bool application_impl::init() {
if (nullptr != its_config_module) {
// TODO: Add loading of custom configuration module
} else { // load default module
+#ifndef VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
auto its_plugin = plugin_manager::get()->get_plugin(
plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
if (its_plugin) {
- configuration_ = std::dynamic_pointer_cast<configuration>(its_plugin);
- if (configuration_path.length()) {
- configuration_->set_configuration_path(configuration_path);
+ auto its_configuration_plugin
+ = std::dynamic_pointer_cast<configuration_plugin>(its_plugin);
+ if (its_configuration_plugin) {
+ configuration_ = its_configuration_plugin->get_configuration(name_);
+ VSOMEIP_INFO << "Configuration module loaded.";
+ } else {
+ std::cerr << "Invalid configuration module!" << std::endl;
+ std::exit(EXIT_FAILURE);
}
- configuration_->load(name_);
- VSOMEIP_INFO << "Default configuration module loaded.";
} else {
std::cerr << "Configuration module could not be loaded!" << std::endl;
std::exit(EXIT_FAILURE);
}
+#else
+ configuration_ = std::dynamic_pointer_cast<configuration>(
+ std::make_shared<vsomeip_v3::cfg::configuration_impl>());
+ if (configuration_path.length()) {
+ configuration_->set_configuration_path(configuration_path);
+ }
+ configuration_->load(name_);
+#endif // VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
+ }
+
+ // Set security mode
+ auto its_security = security::get();
+ if (its_security->is_enabled()) {
+ if (its_security->is_audit()) {
+ security_mode_ = security_mode_e::SM_AUDIT;
+ } else {
+ security_mode_ = security_mode_e::SM_ON;
+ }
+ } else {
+ security_mode_ = security_mode_e::SM_OFF;
}
const char *client_side_logging = getenv(VSOMEIP_ENV_CLIENTSIDELOGGING);
@@ -197,58 +233,41 @@ bool application_impl::init() {
max_dispatch_time_ = its_configuration->get_max_dispatch_time(name_);
std::string its_routing_host = its_configuration->get_routing_host();
- if (!utility::auto_configuration_init(its_configuration)) {
- VSOMEIP_WARNING << "Could _not_ initialize auto-configuration:"
- " Cannot guarantee unique application identifiers!";
- if (client_ == ILLEGAL_CLIENT) {
- VSOMEIP_ERROR << "Couldn't acquire client identifier.";
+ if (its_routing_host != "") {
+ is_routing_manager_host_ = (its_routing_host == name_);
+ if (is_routing_manager_host_ &&
+ !utility::is_routing_manager(configuration_)) {
+#ifndef VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
+ VSOMEIP_ERROR << "application: " << name_ << " configured as "
+ "routing but other routing manager present. Won't "
+ "instantiate routing";
+ is_routing_manager_host_ = false;
return false;
+#else
+ is_routing_manager_host_ = true;
+#endif // VSOMEIP_ENABLE_MULTIPLE_ROUTING_MANAGERS
}
} else {
- // Client Identifier
- client_t its_old_client = client_;
- client_ = utility::request_client_id(its_configuration, name_, client_);
- if (client_ == ILLEGAL_CLIENT) {
- VSOMEIP_ERROR << "Couldn't acquire client identifier from auto-configuration.";
- return false;
- }
- std::string credentials = "";
-#ifndef _WIN32
- credentials = " and UID/GID=" + std::to_string(getuid()) + "/" + std::to_string(getgid());
-#endif
- VSOMEIP_INFO << "SOME/IP client identifier configured. "
- << "Using "
- << std::hex << std::setfill('0') << std::setw(4)
- << client_
- << " (was: "
- << std::hex << std::setfill('0') << std::setw(4)
- << its_old_client
- << ")" << credentials;
-
- // Routing
- if (its_routing_host == "") {
- VSOMEIP_INFO << "No routing manager configured. Using auto-configuration.";
- is_routing_manager_host_ = utility::is_routing_manager_host(client_);
- }
- }
-
- if (its_routing_host != "") {
- is_routing_manager_host_ = (its_routing_host == name_);
+ is_routing_manager_host_ = utility::is_routing_manager(configuration_);
}
if (is_routing_manager_host_) {
VSOMEIP_INFO << "Instantiating routing manager [Host].";
+ if (client_ == VSOMEIP_CLIENT_UNSET) {
+ client_ = static_cast<client_t>(
+ (configuration_->get_diagnosis_address() << 8)
+ & configuration_->get_diagnosis_mask());
+ utility::request_client_id(configuration_, name_, client_);
+ }
routing_ = std::make_shared<routing_manager_impl>(this);
} else {
VSOMEIP_INFO << "Instantiating routing manager [Proxy].";
routing_ = std::make_shared<routing_manager_proxy>(this, client_side_logging_, client_side_logging_filter_);
}
+ routing_->set_client(client_);
routing_->init();
- // Smallest allowed session identifier
- session_ = 0x0001;
-
#ifdef USE_DLT
// Tracing
std::shared_ptr<trace::connector_impl> its_connector
@@ -324,6 +343,11 @@ void application_impl::start() {
pthread_setname_np(pthread_self(),s.str().c_str());
}
#endif
+ if (!is_initialized_) {
+ VSOMEIP_ERROR << "Trying to start an unintialized application.";
+ return;
+ }
+
const size_t io_thread_count = configuration_->get_io_thread_count(name_);
const int io_thread_nice_level = configuration_->get_io_thread_nice_level(name_);
{
@@ -335,9 +359,6 @@ void application_impl::start() {
return;
}
if (stopped_) {
- utility::release_client_id(client_);
- utility::auto_configuration_exit(client_, configuration_);
-
{
std::lock_guard<std::mutex> its_lock_start_stop(block_stop_mutex_);
block_stopping_ = true;
@@ -399,7 +420,7 @@ void application_impl::start() {
#endif
try {
io_.run();
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(ANDROID)
} catch (const boost::log::v2_mt_posix::system_error &e) {
std::cerr << "catched boost::log system_error in I/O thread" << std::endl;
#endif
@@ -415,7 +436,7 @@ void application_impl::start() {
auto its_plugins = configuration_->get_plugins(name_);
auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
if (its_app_plugin_info != its_plugins.end()) {
- for (auto its_library : its_app_plugin_info->second) {
+ for (const auto& its_library : its_app_plugin_info->second) {
auto its_application_plugin = plugin_manager::get()->get_plugin(
plugin_type_e::APPLICATION_PLUGIN, its_library);
if (its_application_plugin) {
@@ -448,10 +469,7 @@ void application_impl::start() {
stop_thread_.join();
}
- utility::release_client_id(client_);
- utility::auto_configuration_exit(client_, configuration_);
-
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(ANDROID)
} catch (const boost::log::v2_mt_posix::system_error &e) {
std::cerr << "catched boost::log system_error in I/O thread" << std::endl;
#endif
@@ -484,7 +502,7 @@ void application_impl::start() {
}
void application_impl::stop() {
-#ifndef _WIN32 // Gives serious problems under Windows.
+#if !defined(_WIN32) && !defined(ANDROID)
try {
VSOMEIP_INFO << "Stopping vsomeip application \"" << name_ << "\" ("
<< std::hex << std::setw(4) << std::setfill('0') << client_ << ").";
@@ -501,7 +519,7 @@ void application_impl::stop() {
stop_caller_id_ = std::this_thread::get_id();
stopped_ = true;
stopped_called_ = true;
- for (auto thread : io_threads_) {
+ for (const auto& thread : io_threads_) {
if (thread->get_id() == std::this_thread::get_id()) {
block = false;
}
@@ -513,7 +531,7 @@ void application_impl::stop() {
auto its_plugins = configuration_->get_plugins(name_);
auto its_app_plugin_info = its_plugins.find(plugin_type_e::APPLICATION_PLUGIN);
if (its_app_plugin_info != its_plugins.end()) {
- for (auto its_library : its_app_plugin_info->second) {
+ for (const auto& its_library : its_app_plugin_info->second) {
auto its_application_plugin = plugin_manager::get()->get_plugin(
plugin_type_e::APPLICATION_PLUGIN, its_library);
if (its_application_plugin) {
@@ -538,6 +556,15 @@ void application_impl::stop() {
}
}
+void application_impl::process(int _number) {
+ (void)_number;
+ VSOMEIP_ERROR << "application::process is not (yet) implemented.";
+}
+
+security_mode_e application_impl::get_security_mode() const {
+ return security_mode_;
+}
+
void application_impl::offer_service(service_t _service, instance_t _instance,
major_version_t _major, minor_version_t _minor) {
if (routing_)
@@ -551,31 +578,20 @@ void application_impl::stop_offer_service(service_t _service, instance_t _instan
}
void application_impl::request_service(service_t _service, instance_t _instance,
- major_version_t _major, minor_version_t _minor, bool _use_exclusive_proxy) {
- if (_use_exclusive_proxy) {
- message_handler_t handler([&](const std::shared_ptr<message>& response) {
- routing_->on_identify_response(get_client(), response->get_service(),
- response->get_instance(), response->is_reliable());
- });
- register_message_handler(_service, _instance, ANY_METHOD - 1, handler);
- }
-
+ major_version_t _major, minor_version_t _minor) {
if (routing_)
- routing_->request_service(client_, _service, _instance, _major, _minor,
- _use_exclusive_proxy);
+ routing_->request_service(client_, _service, _instance, _major, _minor);
}
void application_impl::release_service(service_t _service,
instance_t _instance) {
- if (routing_) {
+ if (routing_)
routing_->release_service(client_, _service, _instance);
- }
}
void application_impl::subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup,
major_version_t _major,
- subscription_type_e _subscription_type,
event_t _event) {
if (routing_) {
bool send_back_cached(false);
@@ -590,8 +606,8 @@ void application_impl::subscribe(service_t _service, instance_t _instance,
}
if (check_subscription_state(_service, _instance, _eventgroup, _event)) {
- routing_->subscribe(client_, _service, _instance, _eventgroup, _major,
- _event, _subscription_type);
+ routing_->subscribe(client_, own_uid_, own_gid_, _service, _instance, _eventgroup, _major,
+ _event);
}
}
}
@@ -600,14 +616,14 @@ void application_impl::unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup) {
remove_subscription(_service, _instance, _eventgroup, ANY_EVENT);
if (routing_)
- routing_->unsubscribe(client_, _service, _instance, _eventgroup, ANY_EVENT);
+ routing_->unsubscribe(client_, own_uid_, own_gid_, _service, _instance, _eventgroup, ANY_EVENT);
}
void application_impl::unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event) {
remove_subscription(_service, _instance, _eventgroup, _event);
if (routing_)
- routing_->unsubscribe(client_, _service, _instance, _eventgroup, _event);
+ routing_->unsubscribe(client_, own_uid_, own_gid_, _service, _instance, _eventgroup, _event);
}
bool application_impl::is_available(
@@ -805,8 +821,7 @@ bool application_impl::are_available_unlocked(available_t &_available,
return true;
}
-void application_impl::send(std::shared_ptr<message> _message, bool _flush) {
- std::lock_guard<std::mutex> its_lock(session_mutex_);
+void application_impl::send(std::shared_ptr<message> _message) {
bool is_request = utility::is_request(_message);
if (client_side_logging_
&& (client_side_logging_filter_.empty()
@@ -820,7 +835,7 @@ void application_impl::send(std::shared_ptr<message> _message, bool _flush) {
<< std::hex << std::setw(4) << std::setfill('0')
<< ((is_request) ? session_ : _message->get_session()) << ":"
<< std::hex << std::setw(4) << std::setfill('0')
- << ((is_request) ? client_ : _message->get_client()) << "] "
+ << ((is_request) ? client_.load() : _message->get_client()) << "] "
<< "type=" << std::hex << static_cast<std::uint32_t>(_message->get_message_type())
<< " thread=" << std::hex << std::this_thread::get_id();
}
@@ -828,38 +843,17 @@ void application_impl::send(std::shared_ptr<message> _message, bool _flush) {
// in case of requests set the request-id (client-id|session-id)
if (is_request) {
_message->set_client(client_);
- _message->set_session(session_);
- }
- // in case of successful sending, increment the session-id
- if (routing_->send(client_, _message, _flush)) {
- if (is_request) {
- update_session();
- }
+ _message->set_session(get_session());
}
+ // Always increment the session-id
+ (void)routing_->send(client_, _message);
}
}
void application_impl::notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload) const {
- return notify(_service, _instance, _event, _payload, false, true);
-}
-
-void application_impl::notify(service_t _service, instance_t _instance,
event_t _event, std::shared_ptr<payload> _payload, bool _force) const {
if (routing_)
- routing_->notify(_service, _instance, _event, _payload, _force, true);
-}
-
-void application_impl::notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload, bool _force, bool _flush) const {
- if (routing_)
- routing_->notify(_service, _instance, _event, _payload, _force, _flush);
-}
-
-void application_impl::notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- client_t _client) const {
- return notify_one(_service, _instance, _event, _payload, _client, false, true);
+ routing_->notify(_service, _instance, _event, _payload, _force);
}
void application_impl::notify_one(service_t _service, instance_t _instance,
@@ -867,16 +861,11 @@ void application_impl::notify_one(service_t _service, instance_t _instance,
client_t _client, bool _force) const {
if (routing_) {
routing_->notify_one(_service, _instance, _event, _payload, _client,
- _force, true, false);
- }
-}
-
-void application_impl::notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush) const {
- if (routing_) {
- routing_->notify_one(_service, _instance, _event, _payload, _client,
- _force, _flush, false);
+ _force
+#ifdef VSOMEIP_ENABLE_COMPAT
+ , false
+#endif
+ );
}
}
@@ -915,10 +904,10 @@ void application_impl::do_register_availability_handler(service_t _service,
std::shared_ptr<sync_handler> its_sync_handler
= std::make_shared<sync_handler>([_handler, are_available, available]() {
- for(auto available_services_it : available)
- for(auto available_instances_it : available_services_it.second)
- _handler(available_services_it.first, available_instances_it.first, are_available);
- });
+ for(const auto& available_services_it : available)
+ for(const auto& available_instances_it : available_services_it.second)
+ _handler(available_services_it.first, available_instances_it.first, are_available);
+ });
its_sync_handler->handler_type_ = handler_type_e::AVAILABILITY;
its_sync_handler->service_id_ = _service;
its_sync_handler->instance_id_ = _instance;
@@ -956,7 +945,8 @@ void application_impl::unregister_availability_handler(service_t _service,
}
void application_impl::on_subscription(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, client_t _client, bool _subscribed, std::function<void(bool)> _accepted_cb) {
+ eventgroup_t _eventgroup, client_t _client, uid_t _uid, gid_t _gid,
+ bool _subscribed, std::function<void(bool)> _accepted_cb) {
bool handler_found = false;
std::pair<subscription_handler_t, async_subscription_handler_t> its_handlers;
{
@@ -977,10 +967,10 @@ void application_impl::on_subscription(service_t _service, instance_t _instance,
if(handler_found) {
if(auto its_handler = its_handlers.first) {
// "normal" subscription handler exists
- _accepted_cb(its_handler(_client, _subscribed));
+ _accepted_cb(its_handler(_client, _uid, _gid, _subscribed));
} else if(auto its_handler = its_handlers.second) {
// async subscription handler exists
- its_handler(_client, _subscribed, _accepted_cb);
+ its_handler(_client, _uid, _gid, _subscribed, _accepted_cb);
}
} else {
_accepted_cb(true);
@@ -993,11 +983,6 @@ void application_impl::register_subscription_handler(service_t _service,
std::lock_guard<std::mutex> its_lock(subscription_mutex_);
subscription_[_service][_instance][_eventgroup] = std::make_pair(_handler, nullptr);
-
- message_handler_t handler([&](const std::shared_ptr<message>& request) {
- send(runtime_->create_response(request), true);
- });
- register_message_handler(_service, _instance, ANY_METHOD - 1, handler);
}
void application_impl::unregister_subscription_handler(service_t _service,
@@ -1013,7 +998,6 @@ void application_impl::unregister_subscription_handler(service_t _service,
}
}
}
- unregister_message_handler(_service, _instance, ANY_METHOD - 1);
}
void application_impl::on_subscription_status(service_t _service,
@@ -1166,46 +1150,6 @@ void application_impl::deliver_subscription_state(service_t _service, instance_t
}
}
-void application_impl::on_subscription_error(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, uint16_t _error) {
- error_handler_t handler = nullptr;
- std::lock_guard<std::mutex> its_lock(subscription_error_mutex_);
- auto found_service = eventgroup_error_handlers_.find(_service);
- if (found_service != eventgroup_error_handlers_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_eventgroup = found_instance->second.find(_eventgroup);
- if (found_eventgroup != found_instance->second.end()) {
- auto found_client = found_eventgroup->second.find(get_client());
- if (found_client != found_eventgroup->second.end()) {
- handler = found_client->second;
-
- }
- }
- }
- }
- if (handler) {
- std::unique_lock<std::mutex> handlers_lock(handlers_mutex_);
- std::shared_ptr<sync_handler> its_sync_handler
- = std::make_shared<sync_handler>([handler, _error]() {
- handler(_error);
- });
- its_sync_handler->handler_type_ = handler_type_e::SUBSCRIPTION;
- its_sync_handler->service_id_ = _service;
- its_sync_handler->instance_id_ = _instance;
- its_sync_handler->eventgroup_id_ = _eventgroup;
- handlers_.push_back(its_sync_handler);
- dispatcher_condition_.notify_all();
- }
-}
-
-void application_impl::register_subscription_status_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- subscription_status_handler_t _handler) {
- register_subscription_status_handler(_service, _instance, _eventgroup,
- _event, _handler, false);
-}
-
void application_impl::register_subscription_status_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
subscription_status_handler_t _handler, bool _is_selective) {
@@ -1214,45 +1158,36 @@ void application_impl::register_subscription_status_handler(service_t _service,
subscription_status_handlers_[_service][_instance][_eventgroup][_event] =
std::make_pair(_handler, _is_selective);
} else {
- auto its_service = subscription_status_handlers_.find(_service);
- if (its_service != subscription_status_handlers_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- auto its_eventgroup = its_instance->second.find(_eventgroup);
- if (its_eventgroup != its_instance->second.end()) {
- its_eventgroup->second.erase(_event);
- if (its_eventgroup->second.size() == 0) {
- its_instance->second.erase(_eventgroup);
- if (its_instance->second.size() == 0) {
- its_service->second.erase(_instance);
- if (its_service->second.size() == 0) {
- subscription_status_handlers_.erase(_service);
- }
- }
- }
- }
- }
- }
+ VSOMEIP_WARNING <<
+ "application_impl::register_subscription_status_handler: "
+ "_handler is null, for unregistration please use "
+ "application_impl::unregister_subscription_status_handler ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _event << "]";
}
}
-void application_impl::register_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- error_handler_t _handler) {
- std::lock_guard<std::mutex> its_lock(subscription_error_mutex_);
- eventgroup_error_handlers_[_service][_instance][_eventgroup][get_client()] = _handler;
-}
-
-void application_impl::unregister_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup) {
- std::lock_guard<std::mutex> its_lock(subscription_error_mutex_);
- auto found_service = eventgroup_error_handlers_.find(_service);
- if (found_service != eventgroup_error_handlers_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- auto found_eventgroup = found_instance->second.find(_eventgroup);
- if (found_eventgroup != found_instance->second.end()) {
- found_eventgroup->second.erase(get_client());
+void application_impl::unregister_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event) {
+ std::lock_guard<std::mutex> its_lock(subscription_status_handlers_mutex_);
+ auto its_service = subscription_status_handlers_.find(_service);
+ if (its_service != subscription_status_handlers_.end()) {
+ auto its_instance = its_service->second.find(_instance);
+ if (its_instance != its_service->second.end()) {
+ auto its_eventgroup = its_instance->second.find(_eventgroup);
+ if (its_eventgroup != its_instance->second.end()) {
+ its_eventgroup->second.erase(_event);
+ if (its_eventgroup->second.empty()) {
+ its_instance->second.erase(_eventgroup);
+ if (its_instance->second.empty()) {
+ its_service->second.erase(_instance);
+ if (its_service->second.empty()) {
+ subscription_status_handlers_.erase(_service);
+ }
+ }
+ }
}
}
}
@@ -1280,20 +1215,17 @@ void application_impl::unregister_message_handler(service_t _service,
}
void application_impl::offer_event(service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field) {
- return offer_event(_service, _instance, _event, _eventgroups, _is_field,
- std::chrono::milliseconds::zero(), false, nullptr);
-}
-
-void application_impl::offer_event(service_t _service, instance_t _instance,
- event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field,
+ event_t _notifier, const std::set<eventgroup_t> &_eventgroups,
+ event_type_e _type,
std::chrono::milliseconds _cycle, bool _change_resets_cycle,
- const epsilon_change_func_t &_epsilon_change_func) {
+ bool _update_on_change,
+ const epsilon_change_func_t &_epsilon_change_func,
+ reliability_type_e _reliability) {
if (routing_)
- routing_->register_event(client_, _service, _instance, _event,
- _eventgroups, _is_field, _cycle, _change_resets_cycle,
+ routing_->register_event(client_,
+ _service, _instance,
+ _notifier, _eventgroups, _type, _reliability,
+ _cycle, _change_resets_cycle, _update_on_change,
_epsilon_change_func, true);
}
@@ -1305,11 +1237,12 @@ void application_impl::stop_offer_event(service_t _service, instance_t _instance
void application_impl::request_event(service_t _service, instance_t _instance,
event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field) {
+ event_type_e _type, reliability_type_e _reliability) {
if (routing_)
- routing_->register_event(client_, _service, _instance, _event,
- _eventgroups, _is_field,
- std::chrono::milliseconds::zero(), false,
+ routing_->register_event(client_,
+ _service, _instance,
+ _event, _eventgroups, _type, _reliability,
+ std::chrono::milliseconds::zero(), false, true,
nullptr,
false);
}
@@ -1329,10 +1262,27 @@ client_t application_impl::get_client() const {
return client_;
}
+void application_impl::set_client(const client_t &_client) {
+ client_ = _client;
+}
+
+session_t application_impl::get_session() {
+ std::lock_guard<std::mutex> its_lock(session_mutex_);
+ if (0 == ++session_) {
+ // Smallest allowed session identifier
+ session_ = 1;
+ }
+ return session_;
+}
+
std::shared_ptr<configuration> application_impl::get_configuration() const {
return configuration_;
}
+diagnosis_t application_impl::get_diagnosis() const {
+ return configuration_->get_diagnosis_address();
+}
+
boost::asio::io_service & application_impl::get_io() {
return io_;
}
@@ -1411,8 +1361,8 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
[&](const availability_major_minor_t& _av_ma_mi_it) {
auto found_major = _av_ma_mi_it.find(_major);
if (found_major != _av_ma_mi_it.end()) {
- for (std::int32_t mi = _minor; mi >= 0; mi--) {
- const auto found_minor = found_major->second.find(mi);
+ for (std::int32_t mi = static_cast<std::int32_t>(_minor); mi >= 0; mi--) {
+ const auto found_minor = found_major->second.find(static_cast<minor_version_t>(mi));
if (found_minor != found_major->second.end()) {
its_handlers.push_back(found_minor->second.first);
}
@@ -1424,8 +1374,8 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
}
found_major = _av_ma_mi_it.find(ANY_MAJOR);
if (found_major != _av_ma_mi_it.end()) {
- for (std::int32_t mi = _minor; mi >= 0; mi--) {
- const auto found_minor = found_major->second.find(mi);
+ for (std::int32_t mi = static_cast<std::int32_t>(_minor); mi >= 0; mi--) {
+ const auto found_minor = found_major->second.find(static_cast<minor_version_t>(mi));
if (found_minor != found_major->second.end()) {
its_handlers.push_back(found_minor->second.first);
}
@@ -1508,7 +1458,7 @@ void application_impl::on_availability(service_t _service, instance_t _instance,
}
}
-void application_impl::on_message(const std::shared_ptr<message> &&_message) {
+void application_impl::on_message(std::shared_ptr<message> &&_message) {
const service_t its_service = _message->get_service();
const instance_t its_instance = _message->get_instance();
const method_t its_method = _message->get_method();
@@ -1584,7 +1534,7 @@ void application_impl::on_message(const std::shared_ptr<message> &&_message) {
auto handler = its_handler.handler_;
std::shared_ptr<sync_handler> its_sync_handler =
std::make_shared<sync_handler>([handler, _message]() {
- handler(std::move(_message));
+ handler(_message);
});
its_sync_handler->handler_type_ = handler_type_e::MESSAGE;
its_sync_handler->service_id_ = _message->get_service();
@@ -1598,11 +1548,6 @@ void application_impl::on_message(const std::shared_ptr<message> &&_message) {
}
}
-void application_impl::on_error(error_code_e _error) {
- VSOMEIP_ERROR<< ERROR_INFO[static_cast<int>(_error)] << " ("
- << static_cast<int>(_error) << ")";
-}
-
// Interface "service_discovery_host"
routing_manager * application_impl::get_routing_manager() const {
return routing_.get();
@@ -1792,7 +1737,7 @@ void application_impl::invoke_handler(std::shared_ptr<sync_handler> &_handler) {
boost::asio::steady_timer its_dispatcher_timer(io_);
its_dispatcher_timer.expires_from_now(std::chrono::milliseconds(max_dispatch_time_));
- its_dispatcher_timer.async_wait([this, its_id, its_sync_handler](const boost::system::error_code &_error) {
+ its_dispatcher_timer.async_wait([this, its_sync_handler](const boost::system::error_code &_error) {
if (!_error) {
print_blocking_call(its_sync_handler);
if (has_active_dispatcher()) {
@@ -1984,56 +1929,83 @@ void application_impl::shutdown() {
}
try {
-
- {
- std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
- for (auto its_dispatcher : dispatchers_) {
- if (its_dispatcher.second->get_id() != stop_caller_id_) {
- if (its_dispatcher.second->joinable()) {
- its_dispatcher.second->join();
- }
- } else {
- // If the caller of stop() is one of our dispatchers
- // it can happen the shutdown mechanism will block
- // as that thread probably can't be joined. The reason
- // is the caller of stop() probably wants to join the
- // thread once call start (which got to the IO-Thread)
- // and which is expected to return after stop() has been
- // called.
- // Therefore detach this thread instead of joining because
- // after it will return to "main_dispatch" it will be
- // properly shutdown anyways because "is_dispatching_"
- // was set to "false" here.
- its_dispatcher.second->detach();
+ std::lock_guard<std::mutex> its_lock(dispatcher_mutex_);
+ for (const auto& its_dispatcher : dispatchers_) {
+ if (its_dispatcher.second->get_id() != stop_caller_id_) {
+ if (its_dispatcher.second->joinable()) {
+ its_dispatcher.second->join();
}
+ } else {
+ // If the caller of stop() is one of our dispatchers
+ // it can happen the shutdown mechanism will block
+ // as that thread probably can't be joined. The reason
+ // is the caller of stop() probably wants to join the
+ // thread once call start (which got to the IO-Thread)
+ // and which is expected to return after stop() has been
+ // called.
+ // Therefore detach this thread instead of joining because
+ // after it will return to "main_dispatch" it will be
+ // properly shutdown anyways because "is_dispatching_"
+ // was set to "false" here.
+ its_dispatcher.second->detach();
}
- availability_handlers_.clear();
- running_dispatchers_.clear();
- elapsed_dispatchers_.clear();
- dispatchers_.clear();
}
+ availability_handlers_.clear();
+ running_dispatchers_.clear();
+ elapsed_dispatchers_.clear();
+ dispatchers_.clear();
+#if !defined(_WIN32) && !defined(ANDROID)
+ } catch (const boost::log::v2_mt_posix::system_error &e) {
+ std::cerr << "application_impl::" << __func__ << ": stopping dispatchers, "
+ << "catched boost::log system_error" << std::endl;
+#endif
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "application_impl::" << __func__ << ": stopping dispatchers, "
+ << " catched exception: " << e.what();
+ }
+ try {
if (routing_)
routing_->stop();
+#if !defined(_WIN32) && !defined(ANDROID)
+ } catch (const boost::log::v2_mt_posix::system_error &e) {
+ std::cerr << "application_impl::" << __func__ << ": stopping routing, "
+ << "catched boost::log system_error" << std::endl;
+#endif
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "application_impl::" << __func__ << ": stopping routing, "
+ << " catched exception: " << e.what();
+ }
+ try {
work_.reset();
io_.stop();
+#if !defined(_WIN32) && !defined(ANDROID)
+ } catch (const boost::log::v2_mt_posix::system_error &e) {
+ std::cerr << "application_impl::" << __func__ << ": stopping io, "
+ << "catched boost::log system_error" << std::endl;
+#endif
+ } catch (const std::exception &e) {
+ VSOMEIP_ERROR << "application_impl::" << __func__ << ": stopping io, "
+ << " catched exception: " << e.what();
+ }
- {
- std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
- for (auto t : io_threads_) {
- if (t->joinable()) {
- t->join();
- }
+ try {
+ std::lock_guard<std::mutex> its_lock_start_stop(start_stop_mutex_);
+ for (const auto& t : io_threads_) {
+ if (t->joinable()) {
+ t->join();
}
- io_threads_.clear();
}
-#ifndef _WIN32
+ io_threads_.clear();
+#if !defined(_WIN32) && !defined(ANDROID)
} catch (const boost::log::v2_mt_posix::system_error &e) {
- std::cerr << "catched boost::log system_error in stop thread" << std::endl;
+ std::cerr << "application_impl::" << __func__ << ": joining threads, "
+ << "catched boost::log system_error" << std::endl;
#endif
} catch (const std::exception &e) {
- VSOMEIP_ERROR << "application_impl::shutdown() catched exception: " << e.what();
+ VSOMEIP_ERROR << "application_impl::" << __func__ << ": joining threads, "
+ << " catched exception: " << e.what();
}
}
@@ -2246,7 +2218,7 @@ bool application_impl::check_subscription_state(service_t _service, instance_t _
return should_subscribe;
}
-void application_impl::print_blocking_call(std::shared_ptr<sync_handler> _handler) {
+void application_impl::print_blocking_call(const std::shared_ptr<sync_handler>& _handler) {
switch (_handler->handler_type_) {
case handler_type_e::AVAILABILITY:
VSOMEIP_WARNING << "BLOCKING CALL AVAILABILITY("
@@ -2302,8 +2274,8 @@ void application_impl::get_offered_services_async(offer_type_e _offer_type, offe
std::vector<std::pair<service_t, instance_t>> its_services;
auto its_routing_manager_host = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
- for (auto s : its_routing_manager_host->get_offered_services()) {
- for (auto i : s.second) {
+ for (const auto& s : its_routing_manager_host->get_offered_services()) {
+ for (const auto& i : s.second) {
auto its_unreliable_endpoint = i.second->get_endpoint(false);
auto its_reliable_endpoint = i.second->get_endpoint(true);
@@ -2399,18 +2371,13 @@ void application_impl::register_async_subscription_handler(service_t _service,
std::lock_guard<std::mutex> its_lock(subscription_mutex_);
subscription_[_service][_instance][_eventgroup] = std::make_pair(nullptr, _handler);;
-
- message_handler_t handler([&](const std::shared_ptr<message>& request) {
- send(runtime_->create_response(request), true);
- });
- register_message_handler(_service, _instance, ANY_METHOD - 1, handler);
}
-void application_impl::register_offer_acceptance_handler(
- offer_acceptance_handler_t _handler) {
+void application_impl::register_sd_acceptance_handler(
+ sd_acceptance_handler_t _handler) {
if (is_routing() && routing_) {
const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
- rm_impl->register_offer_acceptance_handler(_handler);
+ rm_impl->register_sd_acceptance_handler(_handler);
}
}
@@ -2422,33 +2389,45 @@ void application_impl::register_reboot_notification_handler(
}
}
-void application_impl::set_offer_acceptance_required(
- ip_address_t _address, const std::string _path, bool _enable) {
+void application_impl::set_sd_acceptance_required(
+ const remote_info_t& _remote, const std::string& _path, bool _enable) {
if (is_routing()) {
- const boost::asio::ip::address its_address = _address.is_v4_ ?
- static_cast<boost::asio::ip::address>(boost::asio::ip::address_v4(_address.address_.v4_)) :
- static_cast<boost::asio::ip::address>(boost::asio::ip::address_v6(_address.address_.v6_));
- configuration_->set_offer_acceptance_required(its_address, _path, _enable);
+ const boost::asio::ip::address its_address = _remote.ip_.is_v4_ ?
+ static_cast<boost::asio::ip::address>(boost::asio::ip::address_v4(_remote.ip_.address_.v4_)) :
+ static_cast<boost::asio::ip::address>(boost::asio::ip::address_v6(_remote.ip_.address_.v6_));
+ configuration_->set_sd_acceptance_required(its_address, _remote.port_, _path, _enable);
if (_enable && routing_) {
const auto rm_impl = std::dynamic_pointer_cast<routing_manager_impl>(routing_);
- rm_impl->offer_acceptance_enabled(its_address);
+ rm_impl->sd_acceptance_enabled(its_address);
}
}
}
-vsomeip::application::offer_acceptance_map_type_t
-application_impl::get_offer_acceptance_required() {
- offer_acceptance_map_type_t its_ret;
+void application_impl::set_sd_acceptance_required(const sd_acceptance_map_type_t& _remotes,
+ bool _enable) {
+ (void) _remotes;
+ (void) _enable;
+}
+
+application::sd_acceptance_map_type_t
+application_impl::get_sd_acceptance_required() {
+ sd_acceptance_map_type_t its_ret;
if (is_routing()) {
- for (const auto& e : configuration_->get_offer_acceptance_required()) {
- ip_address_t its_address;
- its_address.is_v4_ = e.first.is_v4();
- if (its_address.is_v4_) {
- its_address.address_.v4_ = e.first.to_v4().to_bytes();
+ for (const auto& e : configuration_->get_sd_acceptance_required()) {
+ remote_info_t its_remote_info;
+ its_remote_info.ip_.is_v4_ = e.first.first.is_v4();
+ if (e.first.first.is_v4()) {
+ its_remote_info.ip_.address_.v4_ = e.first.first.to_v4().to_bytes();
+ its_remote_info.ip_.is_v4_ = true;
} else {
- its_address.address_.v6_ = e.first.to_v6().to_bytes();
+ its_remote_info.ip_.address_.v6_ = e.first.first.to_v6().to_bytes();
+ its_remote_info.ip_.is_v4_ = false;
}
- its_ret[its_address] = e.second;
+ its_remote_info.port_ = e.first.second;
+ its_remote_info.first_ = ANY_PORT;
+ its_remote_info.last_ = ANY_PORT;
+ its_remote_info.is_range_ = false;
+ its_ret[its_remote_info] = e.second;
}
}
return its_ret;
@@ -2531,4 +2510,4 @@ void application_impl::remove_security_policy_configuration(uint32_t _uid,
}
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/runtime/src/error.cpp b/implementation/runtime/src/error.cpp
deleted file mode 100644
index 998d1e7..0000000
--- a/implementation/runtime/src/error.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <vsomeip/error.hpp>
-
-namespace vsomeip {
-
-const char *ERROR_INFO[] = { "Missing vsomeip configuration",
- "Missing port configuration", "Client endpoint creation failed",
- "Server endpoint creation failed", "Service property mismatch" };
-
-} // namespace vsomeip
diff --git a/implementation/runtime/src/runtime.cpp b/implementation/runtime/src/runtime.cpp
index 281cea1..9e79b79 100644
--- a/implementation/runtime/src/runtime.cpp
+++ b/implementation/runtime/src/runtime.cpp
@@ -7,7 +7,7 @@
#include "../include/runtime_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
std::string runtime::get_property(const std::string &_name) {
return runtime_impl::get_property(_name);
@@ -21,4 +21,4 @@ std::shared_ptr<runtime> runtime::get() {
return runtime_impl::get();
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/runtime/src/runtime_impl.cpp b/implementation/runtime/src/runtime_impl.cpp
index 4ebb3ad..fc23ced 100644
--- a/implementation/runtime/src/runtime_impl.cpp
+++ b/implementation/runtime/src/runtime_impl.cpp
@@ -10,11 +10,9 @@
#include "../../message/include/message_impl.hpp"
#include "../../message/include/payload_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
std::map<std::string, std::string> runtime_impl::properties_;
-std::shared_ptr<runtime> runtime_impl::the_runtime_ = std::make_shared<runtime_impl>();
-uint32_t runtime_impl::postfix_id = 0;
std::string runtime_impl::get_property(const std::string &_name) {
auto found_property = properties_.find(_name);
@@ -28,6 +26,7 @@ void runtime_impl::set_property(const std::string &_name, const std::string &_va
}
std::shared_ptr<runtime> runtime_impl::get() {
+ static std::shared_ptr<runtime> the_runtime_ = std::make_shared<runtime_impl>();
return the_runtime_;
}
@@ -36,6 +35,7 @@ runtime_impl::~runtime_impl() {
std::shared_ptr<application> runtime_impl::create_application(
const std::string &_name) {
+ static std::uint32_t postfix_id = 0;
std::lock_guard<std::mutex> its_lock(applications_mutex_);
std::string its_name_ = _name;
auto found_application = applications_.find(_name);
@@ -128,4 +128,4 @@ void runtime_impl::remove_application(
}
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/configuration/include/policy.hpp b/implementation/security/include/policy.hpp
index c8f649e..018fbd5 100644
--- a/implementation/configuration/include/policy.hpp
+++ b/implementation/security/include/policy.hpp
@@ -3,15 +3,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CFG_POLICY_HPP
-#define VSOMEIP_CFG_POLICY_HPP
+#ifndef VSOMEIP_V3_POLICY_HPP_
+#define VSOMEIP_V3_POLICY_HPP_
-#include <memory>
+#include <utility>
#include <set>
+#include <cstring>
+#include <vsomeip/constants.hpp>
#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/internal/logger.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
typedef std::set<std::pair<uint32_t, uint32_t>> ranges_t;
typedef std::set<std::pair<ranges_t, ranges_t>> ids_t;
@@ -27,6 +30,6 @@ struct policy {
bool allow_what_;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CFG_POLICY_HPP
+#endif // VSOMEIP_V3_POLICY_HPP_
diff --git a/implementation/security/include/policy_manager_impl.hpp b/implementation/security/include/policy_manager_impl.hpp
new file mode 100644
index 0000000..a5a30ea
--- /dev/null
+++ b/implementation/security/include/policy_manager_impl.hpp
@@ -0,0 +1,43 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_POLICY_MANAGER_IMPL_HPP_
+#define VSOMEIP_V3_POLICY_MANAGER_IMPL_HPP_
+
+#include <memory>
+#include <mutex>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/internal/policy_manager.hpp>
+
+#include "../include/policy.hpp"
+#include "../../configuration/include/configuration_element.hpp"
+
+namespace vsomeip_v3 {
+
+class policy_manager_impl
+ : public policy_manager {
+public:
+ static std::shared_ptr<policy_manager> get();
+
+ virtual ~policy_manager_impl();
+
+ std::shared_ptr<policy> create_policy() const;
+ void print_policy(const std::shared_ptr<policy> &_policy) const;
+
+ bool parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid) const;
+ bool parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid,
+ const std::shared_ptr<policy> &_policy) const;
+
+ bool is_policy_update_allowed(uint32_t _uid,
+ std::shared_ptr<policy> &_policy) const;
+ bool is_policy_removal_allowed(uint32_t _uid) const;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_POLICY_MANAGER_IMPL_HPP_
diff --git a/implementation/security/include/security.hpp b/implementation/security/include/security.hpp
new file mode 100644
index 0000000..0bac7a0
--- /dev/null
+++ b/implementation/security/include/security.hpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SECURITY_SECURITY_HPP_
+#define VSOMEIP_V3_SECURITY_SECURITY_HPP_
+
+#include <memory>
+
+namespace vsomeip_v3 {
+
+struct configuration_element;
+
+class security {
+public:
+ VSOMEIP_EXPORT static std::shared_ptr<security> get();
+
+ virtual ~security() {};
+
+ virtual void load(const configuration_element &_element) = 0;
+
+ virtual bool is_enabled() const = 0;
+ virtual bool is_audit() const = 0;
+
+ virtual bool check_credentials(client_t _client, uid_t _uid, gid_t _gid) = 0;
+ virtual bool check_routing_credentials(client_t _client,
+ uint32_t _uid, uint32_t _gid) const = 0;
+
+ virtual bool is_client_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
+ service_t _service, instance_t _instance, method_t _method,
+ bool _is_request_service = false) const = 0;
+ virtual bool is_remote_client_allowed() const = 0;
+ virtual bool is_offer_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
+ service_t _service, instance_t _instance) const = 0;
+
+ virtual void update_security_policy(uint32_t _uid, uint32_t _gid,
+ const std::shared_ptr<policy>& _policy) = 0;
+ virtual bool remove_security_policy(uint32_t _uid, uint32_t _gid) = 0;
+
+ virtual bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
+ std::set<client_t> &_clients) = 0;
+ virtual bool remove_client_to_uid_gid_mapping(client_t _client) = 0;
+
+ virtual bool get_client_to_uid_gid_mapping(client_t _client,
+ std::pair<uint32_t, uint32_t> &_uid_gid) = 0;
+
+ virtual bool store_client_to_uid_gid_mapping(client_t _client,
+ uint32_t _uid, uint32_t _gid) = 0;
+ virtual void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
+ client_t _client) = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SECURITY_SECURITY_HPP_
diff --git a/implementation/security/include/security_impl.hpp b/implementation/security/include/security_impl.hpp
new file mode 100644
index 0000000..564c029
--- /dev/null
+++ b/implementation/security/include/security_impl.hpp
@@ -0,0 +1,122 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SECURITY_IMPL_HPP_
+#define VSOMEIP_V3_SECURITY_IMPL_HPP_
+
+#include <map>
+#include <mutex>
+#include <vector>
+
+#include <boost/property_tree/ptree.hpp>
+
+#include "../include/policy.hpp"
+#include "../include/security.hpp"
+
+namespace vsomeip_v3 {
+
+class security_impl :
+ public security {
+public:
+ static std::shared_ptr<security_impl> get();
+
+ security_impl();
+
+ void load(const configuration_element &_element);
+
+ bool is_enabled() const;
+ bool is_audit() const;
+
+ bool check_credentials(client_t _client, uid_t _uid, gid_t _gid);
+ bool check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const;
+
+ bool is_client_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
+ service_t _service, instance_t _instance, method_t _method,
+ bool _is_request_service = false) const;
+ bool is_offer_allowed(uint32_t _uid, uint32_t _gid, client_t _client,
+ service_t _service, instance_t _instance) const;
+
+ void update_security_policy(uint32_t _uid, uint32_t _gid, const std::shared_ptr<policy>& _policy);
+ bool remove_security_policy(uint32_t _uid, uint32_t _gid);
+
+ void add_security_credentials(uint32_t _uid, uint32_t _gid,
+ const std::shared_ptr<policy>& _credentials_policy, client_t _client);
+
+ bool is_remote_client_allowed() const;
+
+ bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const;
+
+ bool is_policy_removal_allowed(uint32_t _uid) const;
+
+ bool parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid) const;
+ bool parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid, const std::shared_ptr<policy> &_policy) const;
+
+ bool get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid, std::set<client_t> &_clients);
+ bool remove_client_to_uid_gid_mapping(client_t _client);
+
+ bool get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid);
+ bool store_client_to_uid_gid_mapping(client_t _client, uint32_t _uid, uint32_t _gid);
+ void store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid, client_t _client);
+
+private:
+ // Helper
+
+ bool get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const;
+ bool get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const;
+ bool get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const;
+ bool is_range(const byte_t* &_buffer, uint32_t &_buffer_size) const;
+ bool parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes,
+ ranges_t& its_ranges, uint32_t &_buffer_size) const;
+ bool parse_range(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint16_t &_first, uint16_t &_last) const;
+ bool parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id) const;
+
+ // Configuration
+ void load_policies(const configuration_element &_element);
+ void load_policy(const boost::property_tree::ptree &_tree);
+ void load_credential(const boost::property_tree::ptree &_tree, ids_t &_ids);
+ bool load_routing_credentials(const configuration_element &_element);
+ void load_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
+ void load_instance_ranges(const boost::property_tree::ptree &_tree, ranges_t &_range);
+
+ void load_security_update_whitelist(const configuration_element &_element);
+ void load_service_ranges(const boost::property_tree::ptree &_tree,
+ std::set<std::pair<service_t, service_t>> &_ranges);
+
+private:
+ client_t routing_client_;
+
+ mutable std::mutex ids_mutex_;
+ mutable std::mutex uid_to_clients_mutex_;
+
+ std::vector<std::shared_ptr<policy> > any_client_policies_;
+
+ mutable std::mutex any_client_policies_mutex_;
+ std::map<client_t, std::pair<uint32_t, uint32_t> > ids_;
+ std::map<std::pair<uint32_t, uint32_t>, std::set<client_t> > uid_to_clients_;
+
+ bool policy_enabled_;
+ bool check_credentials_;
+ bool check_routing_credentials_;
+ bool allow_remote_clients_;
+ bool check_whitelist_;
+
+ mutable std::mutex service_interface_whitelist_mutex_;
+ std::set<std::pair<service_t, service_t>> service_interface_whitelist_;
+
+ mutable std::mutex uid_whitelist_mutex_;
+ ranges_t uid_whitelist_;
+
+ mutable std::mutex routing_credentials_mutex_;
+ std::pair<uint32_t, uint32_t> routing_credentials_;
+
+ bool is_configured_;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SECURITY_IMPL_HPP_
diff --git a/implementation/security/src/policy_manager.cpp b/implementation/security/src/policy_manager.cpp
new file mode 100644
index 0000000..beae85c
--- /dev/null
+++ b/implementation/security/src/policy_manager.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/policy_manager_impl.hpp"
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<policy_manager>
+policy_manager::get() {
+ static std::shared_ptr<policy_manager> the_policy_manager
+ = std::make_shared<policy_manager_impl>();
+ return the_policy_manager;
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/security/src/policy_manager_impl.cpp b/implementation/security/src/policy_manager_impl.cpp
new file mode 100644
index 0000000..7789fcc
--- /dev/null
+++ b/implementation/security/src/policy_manager_impl.cpp
@@ -0,0 +1,111 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/policy.hpp"
+#include "../include/policy_manager_impl.hpp"
+#include "../include/security_impl.hpp"
+
+namespace vsomeip_v3 {
+
+policy_manager_impl::~policy_manager_impl() {
+}
+
+std::shared_ptr<policy>
+policy_manager_impl::create_policy() const {
+ return std::make_shared<policy>();
+}
+
+void
+policy_manager_impl::print_policy(const std::shared_ptr<policy> &_policy) const {
+
+ for (auto its_credential : _policy->ids_) {
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) == 0xFFFFFFFF) {
+ VSOMEIP_INFO << "print_policy Security configuration: UID: any";
+ } else {
+ VSOMEIP_INFO << "print_policy Security configuration: UID: 0x"
+ << std::hex << std::get<0>(its_range);
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) == 0xFFFFFFFF) {
+ VSOMEIP_INFO << "print_policy Security configuration: GID: any";
+ } else {
+ VSOMEIP_INFO << "print_policy Security configuration: GID: 0x"
+ << std::hex << std::get<0>(its_range);
+ }
+ }
+ }
+
+ VSOMEIP_INFO << "print_policy Security configuration: RQUESTS POLICY SIZE: "
+ << std::dec << _policy->services_.size();
+ for (auto its_offer : _policy->services_) {
+ VSOMEIP_INFO << "print_policy ALLOWED REQUESTS Service: 0x"
+ << std::hex << std::get<0>(its_offer);
+ for (auto its_ids : std::get<1>(its_offer)) {
+ VSOMEIP_INFO << "print_policy Instances: ";
+ for (auto its_instance_range : std::get<0>(its_ids)) {
+ VSOMEIP_INFO << "print_policy first: 0x"
+ << std::hex << std::get<0>(its_instance_range)
+ << " last: 0x" << std::get<1>(its_instance_range);
+ }
+ VSOMEIP_INFO << "print_policy Methods: ";
+ for (auto its_method_range : std::get<1>(its_ids)) {
+ VSOMEIP_INFO << "print_policy first: 0x"
+ << std::hex << std::get<0>(its_method_range)
+ << " last: 0x" << std::get<1>(its_method_range);
+ }
+ }
+ }
+
+ VSOMEIP_INFO << "print_policy Security configuration: OFFER POLICY SIZE: "
+ << std::dec << _policy->offers_.size();
+ for (auto its_offer : _policy->offers_) {
+ VSOMEIP_INFO << "print_policy ALLOWED OFFERS Service: 0x"
+ << std::hex << std::get<0>(its_offer);
+ for (auto its_ids : std::get<1>(its_offer)) {
+ VSOMEIP_INFO << "print_policy Instances: ";
+ VSOMEIP_INFO << "print_policy first: 0x"
+ << std::hex << std::get<0>(its_ids)
+ << " last: 0x" << std::get<1>(its_ids);
+ }
+ }
+}
+
+bool
+policy_manager_impl::parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid) const {
+
+ auto its_security = security_impl::get();
+ return (its_security
+ && its_security->parse_uid_gid(_buffer, _buffer_size, _uid, _gid));
+}
+
+bool
+policy_manager_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
+
+ auto its_security = security_impl::get();
+ return (its_security
+ && its_security->is_policy_update_allowed(_uid, _policy));
+}
+
+bool
+policy_manager_impl::is_policy_removal_allowed(uint32_t _uid) const {
+
+ auto its_security = security_impl::get();
+ return (its_security
+ && its_security->is_policy_removal_allowed(_uid));
+}
+
+bool
+policy_manager_impl::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid, const std::shared_ptr<policy> &_policy) const {
+
+ auto its_security = security_impl::get();
+ return (its_security
+ && its_security->parse_policy(_buffer, _buffer_size, _uid, _gid, _policy));
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/security/src/security.cpp b/implementation/security/src/security.cpp
new file mode 100644
index 0000000..7c7b3f4
--- /dev/null
+++ b/implementation/security/src/security.cpp
@@ -0,0 +1,15 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/security_impl.hpp"
+
+namespace vsomeip_v3 {
+
+std::shared_ptr<security>
+security::get() {
+ return security_impl::get();
+}
+
+} // namespace vsomeip_v3
diff --git a/implementation/security/src/security_impl.cpp b/implementation/security/src/security_impl.cpp
new file mode 100644
index 0000000..a60a6f8
--- /dev/null
+++ b/implementation/security/src/security_impl.cpp
@@ -0,0 +1,1631 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifdef _WIN32
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
+ #include <stdlib.h>
+ #define bswap_16(x) _byteswap_ushort(x)
+ #define bswap_32(x) _byteswap_ulong(x)
+#else
+ #include <byteswap.h>
+#endif
+
+#include "../include/security_impl.hpp"
+#include "../../configuration/include/configuration_element.hpp"
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+namespace vsomeip_v3 {
+
+static const std::uint8_t uid_width_ = sizeof(std::uint32_t);
+static const std::uint8_t gid_width_ = sizeof(std::uint32_t);
+static const std::uint8_t id_width_ = sizeof(std::uint16_t);
+static const std::uint8_t range_width_ = sizeof(std::uint32_t);
+
+static const std::uint8_t skip_union_length_ = sizeof(std::uint32_t);
+static const std::uint8_t skip_union_type_ = sizeof(std::uint32_t);
+static const std::uint8_t skip_union_length_type_ = sizeof(std::uint32_t) + sizeof(std::uint32_t);
+static const std::uint8_t skip_struct_length_ = sizeof(std::uint32_t);
+static const std::uint8_t skip_array_length_ = sizeof(std::uint32_t);
+
+security_impl::security_impl()
+ : policy_enabled_(false),
+ check_credentials_(false),
+ check_routing_credentials_(false),
+ allow_remote_clients_(true),
+ check_whitelist_(false),
+ is_configured_(false) {
+}
+
+void
+security_impl::load(const configuration_element &_element) {
+ load_policies(_element);
+ load_security_update_whitelist(_element);
+ load_routing_credentials(_element);
+
+ if (policy_enabled_ && check_credentials_)
+ VSOMEIP_INFO << "Security configuration is active.";
+
+ if (policy_enabled_ && !check_credentials_)
+ VSOMEIP_INFO << "Security configuration is active but in audit mode (allow all)";
+}
+
+bool
+security_impl::is_enabled() const {
+ return policy_enabled_;
+}
+
+bool
+security_impl::is_audit() const {
+ return check_credentials_;
+}
+
+bool
+security_impl::check_credentials(client_t _client, uid_t _uid,
+ gid_t _gid) {
+ if (!policy_enabled_) {
+ return true;
+ }
+
+ std::vector<std::shared_ptr<policy> > its_policies;
+ bool has_id(false);
+ {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ its_policies = any_client_policies_;
+ }
+
+ for (const auto &p : its_policies) {
+ for (auto its_credential : p->ids_) {
+ bool has_uid(false), has_gid(false);
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+
+ if (has_uid && has_gid) {
+ has_id = true;
+ break;
+ }
+ }
+
+ if ((has_id && p->allow_who_) || (!has_id && !p->allow_who_)) {
+ if (!store_client_to_uid_gid_mapping(_client,_uid, _gid)) {
+ std::string security_mode_text = "!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << _uid << "/" << _gid
+ << " : Check credentials failed as existing credentials would be overwritten"
+ << security_mode_text;
+ return !check_credentials_;
+ }
+ store_uid_gid_to_client_mapping(_uid, _gid, _client);
+ return true;
+ }
+ }
+
+ std::string security_mode_text = " ~> Skip!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << _uid << "/" << _gid
+ << " : Check credentials failed" << security_mode_text;
+
+ return !check_credentials_;
+}
+
+bool
+security_impl::is_client_allowed(uint32_t _uid, uint32_t _gid, client_t _client, service_t _service,
+ instance_t _instance, method_t _method, bool _is_request_service) const {
+ if (!policy_enabled_) {
+ return true;
+ }
+
+ uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
+ std::vector<std::shared_ptr<policy> > its_policies;
+ {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ its_policies = any_client_policies_;
+ }
+
+ if (_uid != ANY_UID
+ && _gid != ANY_GID) {
+ its_uid = _uid;
+ its_gid = _gid;
+ } else {
+ std::string security_mode_text = " ~> Skip!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
+ << " for client 0x" << std::hex << _client << " is not valid"
+ << ". Therefore it isn't allowed to communicate to service/instance "
+ << _service << "/" << _instance
+ << security_mode_text;
+
+ return !check_credentials_;
+ }
+
+ for (const auto &p : its_policies) {
+ bool has_uid(false), has_gid(false), has_service(false), has_instance_id(false), has_method_id(false);
+ for (auto its_credential : p->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= its_uid && its_uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= its_gid && its_gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+
+ if (has_uid && has_gid)
+ break;
+ }
+
+ for (auto its_offer : p->services_) {
+ if (std::get<0>(its_offer) == _service) {
+ for (auto its_ids : std::get<1>(its_offer)) {
+ has_service = has_instance_id = has_method_id = false;
+ for (auto its_instance_range : std::get<0>(its_ids)) {
+ if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
+ has_instance_id = true;
+ break;
+ }
+ }
+ if (!_is_request_service) {
+ for (auto its_method_range : std::get<1>(its_ids)) {
+ if (std::get<0>(its_method_range) <= _method && _method <= std::get<1>(its_method_range)) {
+ has_method_id = true;
+ break;
+ }
+ }
+ } else {
+ // handle VSOMEIP_REQUEST_SERVICE
+ has_method_id = true;
+ }
+
+ if (has_instance_id && has_method_id) {
+ has_service = true;
+ break;
+ }
+ }
+ if (has_service)
+ break;
+ }
+ }
+
+ if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
+ if (p->allow_what_) {
+ // allow policy
+ if (has_service) {
+ return true;
+ }
+ } else {
+ // deny policy
+ // allow client if the service / instance / !ANY_METHOD was not found
+ if ((!has_service && (_method != ANY_METHOD))
+ // allow client if the service / instance / ANY_METHOD was not found
+ // and it is a "deny nothing" policy
+ || (!has_service && (_method == ANY_METHOD) && p->services_.empty())) {
+ return true;
+ }
+ }
+ }
+ }
+
+ std::string security_mode_text = " ~> Skip!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
+ << " : Isn't allowed to communicate with service/instance/(method / event) " << std::hex
+ << _service << "/" << _instance << "/" << _method
+ << security_mode_text;
+
+ return !check_credentials_;
+}
+
+bool
+security_impl::is_offer_allowed(uint32_t _uid, uint32_t _gid, client_t _client, service_t _service,
+ instance_t _instance) const {
+ if (!policy_enabled_) {
+ return true;
+ }
+
+ uint32_t its_uid(ANY_UID), its_gid(ANY_GID);
+ std::vector<std::shared_ptr<policy> > its_policies;
+ {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ its_policies = any_client_policies_;
+ }
+
+ if (_uid != ANY_UID
+ && _gid != ANY_GID) {
+ its_uid = _uid;
+ its_gid = _gid;
+ } else {
+ std::string security_mode_text = " ~> Skip offer!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: uid/gid " << std::dec << _uid << "/" << _gid
+ << " for client 0x" << std::hex << _client << " is not valid"
+ << ". Therefore it isn't allowed to offer service/instance "
+ << _service << "/" << _instance
+ << security_mode_text;
+
+ return !check_credentials_;
+ }
+
+ for (const auto &p : its_policies) {
+ bool has_uid(false), has_gid(false), has_offer(false);
+ for (auto its_credential : p->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= its_uid && its_uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= its_gid && its_gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+
+ if (has_uid && has_gid)
+ break;
+ }
+
+ for (auto its_offer : p->offers_) {
+ has_offer = false;
+ if (std::get<0>(its_offer) == _service) {
+ for (auto its_instance_range : std::get<1>(its_offer)) {
+ if (std::get<0>(its_instance_range) <= _instance && _instance <= std::get<1>(its_instance_range)) {
+ has_offer = true;
+ break;
+ }
+ }
+ if (has_offer)
+ break;
+ }
+ }
+
+ if ((has_uid && has_gid && p->allow_who_) || ((!has_uid || !has_gid) && !p->allow_who_)) {
+ if (p->allow_what_ == has_offer) {
+ return true;
+ }
+ }
+ }
+
+ std::string security_mode_text = " ~> Skip offer!";
+ if (!check_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x" << std::hex << _client
+ << " with UID/GID=" << std::dec << its_uid << "/" << its_gid
+ << " isn't allowed to offer service/instance " << std::hex
+ << _service << "/" << _instance
+ << security_mode_text;
+
+ return !check_credentials_;
+}
+
+bool
+security_impl::store_client_to_uid_gid_mapping(
+ client_t _client, uint32_t _uid, uint32_t _gid) {
+ {
+ // store the client -> (uid, gid) mapping
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ auto found_client = ids_.find(_client);
+ if (found_client != ids_.end()) {
+ if (found_client->second != std::make_pair(_uid, _gid)) {
+ VSOMEIP_WARNING << "vSomeIP Security: Client 0x"
+ << std::hex << _client << " with UID/GID="
+ << std::dec << _uid << "/" << _gid << " : Overwriting existing credentials UID/GID="
+ << std::dec << std::get<0>(found_client->second) << "/"
+ << std::get<1>(found_client->second);
+ found_client->second = std::make_pair(_uid, _gid);
+ return true;
+ }
+ } else {
+ ids_[_client] = std::make_pair(_uid, _gid);
+ }
+ return true;
+ }
+}
+
+bool
+security_impl::get_client_to_uid_gid_mapping(client_t _client, std::pair<uint32_t, uint32_t> &_uid_gid) {
+ {
+ // get the UID / GID of the client
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ if (ids_.find(_client) != ids_.end()) {
+ _uid_gid = ids_[_client];
+ return true;
+ }
+ return false;
+ }
+}
+
+bool
+security_impl::remove_client_to_uid_gid_mapping(client_t _client) {
+ std::pair<uint32_t, uint32_t> its_uid_gid;
+ bool client_removed(false);
+ bool uid_gid_removed(false);
+ {
+ std::lock_guard<std::mutex> its_lock(ids_mutex_);
+ auto found_client = ids_.find(_client);
+ if (found_client != ids_.end()) {
+ its_uid_gid = found_client->second;
+ ids_.erase(found_client);
+ client_removed = true;
+ }
+ }
+ {
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ if (client_removed) {
+ auto found_uid_gid = uid_to_clients_.find(its_uid_gid);
+ if (found_uid_gid != uid_to_clients_.end()) {
+ auto its_client = found_uid_gid->second.find(_client);
+ if (its_client != found_uid_gid->second.end()) {
+ found_uid_gid->second.erase(its_client);
+ if (found_uid_gid->second.empty()) {
+ uid_to_clients_.erase(found_uid_gid);
+ }
+ uid_gid_removed = true;
+ }
+ }
+ } else {
+ for (auto its_uid_gid = uid_to_clients_.begin();
+ its_uid_gid != uid_to_clients_.end(); ++its_uid_gid) {
+ auto its_client = its_uid_gid->second.find(_client);
+ if (its_client != its_uid_gid->second.end()) {
+ its_uid_gid->second.erase(its_client);
+ if (its_uid_gid->second.empty()) {
+ uid_to_clients_.erase(its_uid_gid);
+ }
+ uid_gid_removed = true;
+ break;
+ }
+ }
+ }
+ }
+ return (client_removed && uid_gid_removed);
+}
+
+void
+security_impl::store_uid_gid_to_client_mapping(uint32_t _uid, uint32_t _gid,
+ client_t _client) {
+ {
+ // store the uid gid to clients mapping
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ std::set<client_t> mapped_clients;
+ if (uid_to_clients_.find(std::make_pair(_uid, _gid)) != uid_to_clients_.end()) {
+ mapped_clients = uid_to_clients_[std::make_pair(_uid, _gid)];
+ mapped_clients.insert(_client);
+ uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
+ } else {
+ mapped_clients.insert(_client);
+ uid_to_clients_[std::make_pair(_uid, _gid)] = mapped_clients;
+ }
+ }
+}
+
+bool
+security_impl::get_uid_gid_to_client_mapping(std::pair<uint32_t, uint32_t> _uid_gid,
+ std::set<client_t> &_clients) {
+ {
+ // get the clients corresponding to uid, gid
+ std::lock_guard<std::mutex> its_lock(uid_to_clients_mutex_);
+ if (uid_to_clients_.find(_uid_gid) != uid_to_clients_.end()) {
+ _clients = uid_to_clients_[_uid_gid];
+ return true;
+ }
+ return false;
+ }
+}
+
+bool
+security_impl::remove_security_policy(uint32_t _uid, uint32_t _gid) {
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ bool was_removed(false);
+ if (!any_client_policies_.empty()) {
+ std::vector<std::shared_ptr<policy>>::iterator p_it = any_client_policies_.begin();
+ while (p_it != any_client_policies_.end()) {
+ bool has_uid(false), has_gid(false);
+ for (auto its_credential : p_it->get()->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+ // only remove "credentials allow" policies to prevent removal of
+ // blacklist configured in file
+ if (has_uid && has_gid && p_it->get()->allow_who_) {
+ was_removed = true;
+ break;
+ }
+ }
+ if (was_removed) {
+ p_it = any_client_policies_.erase(p_it);
+ break;
+ } else {
+ ++p_it;
+ }
+ }
+ }
+ return was_removed;
+}
+
+void
+security_impl::update_security_policy(uint32_t _uid, uint32_t _gid, const std::shared_ptr<policy>& _policy) {
+ remove_security_policy(_uid, _gid);
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ any_client_policies_.push_back(_policy);
+}
+
+void
+security_impl::add_security_credentials(uint32_t _uid, uint32_t _gid,
+ const std::shared_ptr<policy>& _credentials_policy, client_t _client) {
+
+ bool was_found(false);
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ for (const auto& its_policy : any_client_policies_) {
+ bool has_uid(false), has_gid(false);
+ for (auto its_credential : its_policy->ids_) {
+ has_uid = has_gid = false;
+ for (auto its_range : std::get<0>(its_credential)) {
+ if (std::get<0>(its_range) <= _uid && _uid <= std::get<1>(its_range)) {
+ has_uid = true;
+ break;
+ }
+ }
+ for (auto its_range : std::get<1>(its_credential)) {
+ if (std::get<0>(its_range) <= _gid && _gid <= std::get<1>(its_range)) {
+ has_gid = true;
+ break;
+ }
+ }
+ if (has_uid && has_gid && its_policy->allow_who_) {
+ was_found = true;
+ break;
+ }
+ }
+ if (was_found) {
+ break;
+ }
+ }
+ // Do not add the new (credentials-only-policy) if a allow credentials policy with same credentials was found
+ if (!was_found) {
+ any_client_policies_.push_back(_credentials_policy);
+ VSOMEIP_INFO << __func__ << " Added security credentials at client: 0x"
+ << std::hex << _client << std::dec << " with UID: " << _uid << " GID: " << _gid;
+ }
+}
+
+bool
+security_impl::is_remote_client_allowed() const {
+ if (!check_credentials_) {
+ return true;
+ }
+ return allow_remote_clients_;
+}
+
+bool
+security_impl::parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid) const {
+
+ uint32_t its_uid = ANY_UID;
+ uint32_t its_gid = ANY_GID;
+
+ if (_buffer_size >= sizeof(uint32_t) * 2) {
+ std::memcpy(&its_uid, _buffer, sizeof(uint32_t));
+ _uid = bswap_32(its_uid);
+
+ std::memcpy(&its_gid, _buffer + sizeof(uint32_t), sizeof(uint32_t));
+ _gid = bswap_32(its_gid);
+
+ _buffer_size -= (uid_width_ + gid_width_);
+ _buffer += (uid_width_ + gid_width_);
+ return true;
+ }
+ return false;
+}
+
+bool
+security_impl::is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const {
+ bool uid_allowed(false);
+ {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ for (auto its_uid_range : uid_whitelist_) {
+ if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
+ uid_allowed = true;
+ break;
+ }
+ }
+ }
+
+ if (uid_allowed) {
+ std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
+ for (auto its_request : _policy->services_) {
+ auto its_requested_service = std::get<0>(its_request);
+ bool has_service(false);
+ for (auto its_service_range : service_interface_whitelist_) {
+ if (std::get<0>(its_service_range) <= its_requested_service
+ && its_requested_service <= std::get<1>(its_service_range)) {
+ has_service = true;
+ break;
+ }
+ }
+ if (!has_service) {
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy update requesting service ID: "
+ << std::hex << its_requested_service
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy update requesting service ID: "
+ << std::hex << its_requested_service
+ << " is not allowed! -> ignore update";
+ }
+ return !check_whitelist_;
+ }
+ }
+ return true;
+ } else {
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy update for UID: " << std::dec << _uid
+ << " is not allowed! -> ignore update";
+ }
+ return !check_whitelist_;
+ }
+}
+
+bool
+security_impl::is_policy_removal_allowed(uint32_t _uid) const {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ for (auto its_uid_range : uid_whitelist_) {
+ if (std::get<0>(its_uid_range) <= _uid && _uid <= std::get<1>(its_uid_range)) {
+ return true;
+ }
+ }
+
+ if (!check_whitelist_) {
+ VSOMEIP_INFO << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
+ << " is not allowed, but will be allowed due to whitelist audit mode is active!";
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Policy removal for UID: " << std::dec << _uid
+ << " is not allowed! -> ignore removal";
+ }
+ return !check_whitelist_;
+}
+
+bool
+security_impl::check_routing_credentials(client_t _client, uint32_t _uid, uint32_t _gid) const {
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ if ( std::get<0>(routing_credentials_) == _uid
+ && std::get<1>(routing_credentials_) == _gid) {
+ return true;
+ }
+
+ std::string security_mode_text = "!";
+ if (!check_routing_credentials_) {
+ security_mode_text = " but will be allowed due to audit mode is active!";
+ }
+ VSOMEIP_INFO << "vSomeIP Security: Client 0x"
+ << std::hex << _client << " and UID/GID=" << std::dec << _uid
+ << "/" << _gid << " : Check routing credentials failed as "
+ << "configured routing manager credentials "
+ << "do not match with routing manager credentials"
+ << security_mode_text;
+
+ return !check_routing_credentials_;
+}
+
+bool
+security_impl::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid, const std::shared_ptr<policy> &_policy) const {
+
+ uint32_t its_uid = ANY_UID;
+ uint32_t its_gid = ANY_GID;
+ bool has_error(false);
+
+ // get user ID String
+ if (parse_uid_gid(_buffer, _buffer_size, its_uid, its_gid)) {
+ _uid = its_uid;
+ _gid = its_gid;
+
+ // policy elements
+ std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
+ std::set<std::pair<uint32_t, uint32_t>> its_uids, its_gids;
+
+ // fill uid and gid range
+ std::get<0>(its_uid_range) = its_uid;
+ std::get<1>(its_uid_range) = its_uid;
+ std::get<0>(its_gid_range) = its_gid;
+ std::get<1>(its_gid_range) = its_gid;
+ its_uids.insert(its_uid_range);
+ its_gids.insert(its_gid_range);
+
+ _policy->ids_.insert(std::make_pair(its_uids, its_gids));
+ _policy->allow_who_ = true;
+ _policy->allow_what_ = true;
+
+ // get struct AclUpdate
+ uint32_t acl_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, acl_length)) {
+ // get requests array length
+ uint32_t requests_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, requests_array_length)) {
+ // loop through requests array consisting of n x "struct Request"
+ uint32_t parsed_req_bytes = 0;
+ while (parsed_req_bytes + skip_struct_length_ <= requests_array_length) {
+ // get request struct length
+ uint32_t req_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, req_length)) {
+ if (req_length != 0)
+ parsed_req_bytes += skip_struct_length_;
+
+ uint16_t its_service_id = 0;
+ ids_t its_instance_method_ranges;
+ // get serviceID
+ if (!parse_id(_buffer, _buffer_size, its_service_id)) {
+ has_error = true;
+ } else {
+ if (its_service_id == 0x00
+ || its_service_id == 0xFFFF) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
+ << its_service_id << " is not allowed!";
+ return false;
+ }
+ // add length of serviceID
+ parsed_req_bytes += id_width_;
+ }
+
+ // get instances array length
+ uint32_t instances_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, instances_array_length)) {
+ // loop trough instances array consisting of n x "struct Instance"
+ uint32_t parsed_inst_bytes = 0;
+ while (parsed_inst_bytes + skip_struct_length_ <= instances_array_length) {
+ // get instance struct length
+ uint32_t inst_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, inst_length)) {
+ if (inst_length != 0)
+ parsed_inst_bytes += skip_struct_length_;
+
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ // get "IdItem[] ids" array length
+ uint32_t ids_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
+ uint32_t parsed_ids_bytes = 0;
+ while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
+ if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ parsed_inst_bytes += (skip_array_length_ + ids_array_length);
+ }
+ // get "IdItem[] methods" array length
+ uint32_t methods_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, methods_array_length)) {
+ uint32_t parsed_method_bytes = 0;
+ while (parsed_method_bytes + skip_struct_length_ <= methods_array_length) {
+ if (!parse_id_item(_buffer, parsed_method_bytes, its_method_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ parsed_inst_bytes += (skip_array_length_ + methods_array_length);
+ }
+ }
+ }
+ parsed_req_bytes += (skip_array_length_ + instances_array_length);
+ }
+ if (!its_instance_method_ranges.empty()) {
+ _policy->services_.insert(
+ std::make_pair(its_service_id, its_instance_method_ranges));
+ }
+ }
+ }
+ }
+ // get offers array length
+ uint32_t offers_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, offers_array_length)){
+ // loop through offers array
+ uint32_t parsed_offers_bytes = 0;
+ while (parsed_offers_bytes + skip_struct_length_ <= offers_array_length) {
+ // get service ID
+ uint16_t its_service_id = 0;
+ ranges_t its_instance_ranges;
+ // get serviceID
+ if (!parse_id(_buffer, _buffer_size, its_service_id)) {
+ has_error = true;
+ } else {
+ if (its_service_id == 0x00
+ || its_service_id == 0xFFFF) {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
+ << its_service_id << " is not allowed!";
+ return false;
+ }
+ // add length of serviceID
+ parsed_offers_bytes += id_width_;
+ }
+
+ // get "IdItem[] ids" array length
+ uint32_t ids_array_length = 0;
+ if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
+ uint32_t parsed_ids_bytes = 0;
+ while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
+ if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
+ return false;
+ }
+ }
+ parsed_offers_bytes += (skip_array_length_ + ids_array_length);
+ }
+ if (!its_instance_ranges.empty()) {
+ _policy->offers_.insert(
+ std::make_pair(its_service_id, its_instance_ranges));
+ }
+ }
+ }
+ } else {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with empty request / offer section is not allowed!";
+ has_error = true;
+ }
+ } else {
+ VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy without UID / GID is not allowed!";
+ has_error = true;
+ }
+
+ if (!has_error)
+ return true;
+ else
+ return false;
+}
+
+bool
+security_impl::get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const {
+ uint32_t its_length = 0;
+ bool length_field_deployed(false);
+ // [TR_SOMEIP_00080] d If the length of the length field is not specified, a length of 0
+ // has to be assumed and no length field is in the message.
+ if (length_field_deployed) {
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_struct_length_;
+ _buffer += skip_struct_length_;
+ return true;
+ }
+ } else {
+ _length = 0;
+ return true;
+ }
+
+ return false;
+}
+
+bool
+security_impl::get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const {
+ uint32_t its_length = 0;
+
+ // [TR_SOMEIP_00125] d If the Interface Specification does not specify the length of the
+ // length field for a union, 32 bit length of the length field shall be used.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_union_length_;
+ _buffer += skip_union_length_;
+ return true;
+ }
+ return false;
+}
+
+bool
+security_impl::get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) const {
+
+ uint32_t its_length = 0;
+
+ // [TR_SOMEIP_00106] d The layout of arrays with dynamic length basically is based on
+ // the layout of fixed length arrays. To determine the size of the array the serialization
+ // adds a length field (default length 32 bit) in front of the data, which counts the bytes
+ // of the array. The length does not include the size of the length field. Thus, when
+ // transporting an array with zero elements the length is set to zero.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_length, _buffer, sizeof(uint32_t));
+ _length = bswap_32(its_length);
+ _buffer_size -= skip_array_length_;
+ _buffer += skip_array_length_;
+ return true;
+ }
+ return false;
+}
+
+bool
+security_impl::is_range(const byte_t* &_buffer, uint32_t &_buffer_size) const {
+
+ uint32_t its_type = 0;
+
+ // [TR_SOMEIP_00128] If the Interface Specification does not specify the length of the
+ // type field of a union, 32 bit length of the type field shall be used.
+ if (_buffer_size >= sizeof(uint32_t)) {
+ std::memcpy(&its_type, _buffer, sizeof(uint32_t));
+ its_type = bswap_32(its_type);
+ _buffer_size -= skip_union_type_;
+ _buffer += skip_union_type_;
+ if (its_type == 0x02) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool
+security_impl::parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes,
+ ranges_t& its_ranges, uint32_t &_buffer_size) const {
+
+ // get "union IdItem" length
+ uint32_t iditem_length = 0;
+ if (get_union_length(_buffer, _buffer_size, iditem_length)) {
+ // determine type of union
+ uint16_t its_first = 0;
+ uint16_t its_last = 0;
+ if (is_range(_buffer, _buffer_size)) {
+ // get range of instance IDs "struct IdRange" length
+ uint32_t range_length = 0;
+ if (get_struct_length(_buffer, _buffer_size, range_length)) {
+ // read first and last instance range
+ if (parse_range(_buffer, _buffer_size, its_first, its_last)) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ } else {
+ return false;
+ }
+ }
+ } else {
+ // a single instance ID
+ if (parse_id(_buffer, _buffer_size, its_first)) {
+ if (its_first != ANY_METHOD) {
+ if (its_first != 0x00) {
+ its_last = its_first;
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ } else {
+ return false;
+ }
+ } else {
+ its_first = 0x01;
+ its_last = 0xFFFE;
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ parsed_ids_bytes += (skip_union_length_type_ + iditem_length);
+ }
+ return true;
+}
+
+bool
+security_impl::parse_range(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint16_t &_first, uint16_t &_last) const {
+
+ uint16_t its_first = 0;
+ uint16_t its_last = 0;
+
+ if (_buffer_size >= sizeof(uint16_t) * 2) {
+ if (parse_id(_buffer, _buffer_size, its_first)) {
+ _first = its_first;
+ }
+ if (parse_id(_buffer, _buffer_size, its_last)) {
+ _last = its_last;
+ }
+ if (_first != _last
+ && (_first == ANY_METHOD || _last == ANY_METHOD)) {
+ return false;
+ }
+ if (_first != 0x0 && _last != 0x00
+ && _first <= _last) {
+ if (_first == ANY_METHOD &&
+ _last == ANY_METHOD) {
+ _first = 0x01;
+ _last = 0xFFFE;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool
+security_impl::parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id) const {
+ uint16_t its_id = 0;
+ if (_buffer_size >= sizeof(uint16_t)) {
+ std::memcpy(&its_id, _buffer, sizeof(uint16_t));
+ _id = bswap_16(its_id);
+ _buffer_size -= id_width_;
+ _buffer += id_width_;
+ return true;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Configuration
+///////////////////////////////////////////////////////////////////////////////
+void
+security_impl::load_policies(const configuration_element &_element) {
+#ifdef _WIN32
+ return;
+#endif
+ try {
+ auto optional = _element.tree_.get_child_optional("security");
+ if (!optional) {
+ return;
+ }
+ policy_enabled_ = true;
+ auto found_policy = _element.tree_.get_child("security");
+ for (auto its_security = found_policy.begin();
+ its_security != found_policy.end(); ++its_security) {
+ if (its_security->first == "check_credentials") {
+ if (its_security->second.data() == "true") {
+ check_credentials_ = true;
+ } else {
+ check_credentials_ = false;
+ }
+ } else if (its_security->first == "allow_remote_clients") {
+ if (its_security->second.data() == "true") {
+ allow_remote_clients_ = true;
+ } else {
+ allow_remote_clients_ = false;
+ }
+ } else if (its_security->first == "policies") {
+ for (auto its_policy = its_security->second.begin();
+ its_policy != its_security->second.end(); ++its_policy) {
+ load_policy(its_policy->second);
+ }
+ }
+ }
+ } catch (...) {
+ }
+}
+
+void
+security_impl::load_policy(const boost::property_tree::ptree &_tree) {
+ std::shared_ptr<policy> policy(std::make_shared<policy>());
+ bool allow_deny_set(false);
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ if (i->first == "credentials") {
+ std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
+ ranges_t its_uid_ranges, its_gid_ranges;
+
+ bool has_uid(false), has_gid(false);
+ bool has_uid_range(false), has_gid_range(false);
+ for (auto n = i->second.begin();
+ n != i->second.end(); ++n) {
+ std::string its_key(n->first);
+ std::string its_value(n->second.data());
+ if (its_key == "uid") {
+ if(n->second.data().empty()) {
+ load_ranges(n->second, its_uid_ranges);
+ has_uid_range = true;
+ } else {
+ if (its_value != "any") {
+ uint32_t its_uid;
+ std::stringstream its_converter;
+ its_converter << std::dec << its_value;
+ its_converter >> its_uid;
+ std::get<0>(its_uid_range) = its_uid;
+ std::get<1>(its_uid_range) = its_uid;
+ } else {
+ std::get<0>(its_uid_range) = 0;
+ std::get<1>(its_uid_range) = 0xFFFFFFFF;
+ }
+ has_uid = true;
+ }
+ } else if (its_key == "gid") {
+ if(n->second.data().empty()) {
+ load_ranges(n->second, its_gid_ranges);
+ has_gid_range = true;
+ } else {
+ if (its_value != "any") {
+ uint32_t its_gid;
+ std::stringstream its_converter;
+ its_converter << std::dec << its_value;
+ its_converter >> its_gid;
+ std::get<0>(its_gid_range) = its_gid;
+ std::get<1>(its_gid_range) = its_gid;
+ } else {
+ std::get<0>(its_gid_range) = 0;
+ std::get<1>(its_gid_range) = 0xFFFFFFFF;
+ }
+ has_gid = true;
+ }
+ } else if (its_key == "allow" || its_key == "deny") {
+ policy->allow_who_ = (its_key == "allow");
+ load_credential(n->second, policy->ids_);
+ }
+ }
+
+ if (has_uid && has_gid) {
+ std::set<std::pair<uint32_t, uint32_t>> its_uids, its_gids;
+
+ its_uids.insert(its_uid_range);
+ its_gids.insert(its_gid_range);
+
+ policy->allow_who_ = true;
+ policy->ids_.insert(std::make_pair(its_uids, its_gids));
+ }
+ if (has_uid_range && has_gid_range) {
+ policy->allow_who_ = true;
+ policy->ids_.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
+ }
+ } else if (i->first == "allow") {
+ if (allow_deny_set) {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"allow\" tag overrides "
+ << "already set \"deny\" tag. "
+ << "Either \"deny\" or \"allow\" is allowed.";
+ }
+ allow_deny_set = true;
+ policy->allow_what_ = true;
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ if (l->first == "requests") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ ids_t its_instance_method_ranges;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") { // legacy definition for instances
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ std::string value = k->second.data();
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ } else if (k->first == "instances") { // new instances definition
+ for (auto p = k->second.begin(); p != k->second.end(); ++p) {
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ for (auto m = p->second.begin(); m != p->second.end(); ++m) {
+ if (m->first == "ids") {
+ load_instance_ranges(m->second, its_instance_ranges);
+ } else if (m->first == "methods") {
+ load_instance_ranges(m->second, its_method_ranges);
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ }
+ }
+ if (its_instance_method_ranges.empty()) {
+ ranges_t its_legacy_instance_ranges;
+ ranges_t its_legacy_method_ranges;
+ its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ // try to only load instance ranges with any method to be allowed
+ load_instance_ranges(k->second, its_legacy_instance_ranges);
+ if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
+ its_legacy_method_ranges));
+ }
+ }
+ }
+ }
+ if (service != 0x0 && !its_instance_method_ranges.empty()) {
+ policy->services_.insert(
+ std::make_pair(service, its_instance_method_ranges));
+ }
+ }
+ } else if (l->first == "offers") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ ranges_t its_instance_ranges;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") { // legacy definition for instances
+ std::string value = k->second.data();
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else if (k->first == "instances") { // new instances definition
+ load_instance_ranges(k->second, its_instance_ranges);
+ }
+ }
+ if (service != 0x0 && !its_instance_ranges.empty()) {
+ policy->offers_.insert(
+ std::make_pair(service, its_instance_ranges));
+ }
+ }
+ }
+ }
+ } else if (i->first == "deny") {
+ if (allow_deny_set) {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: \"deny\" tag overrides "
+ << "already set \"allow\" tag. "
+ << "Either \"deny\" or \"allow\" is allowed.";
+ }
+ allow_deny_set = true;
+ policy->allow_what_ = false;
+ for (auto l = i->second.begin(); l != i->second.end(); ++l) {
+ if (l->first == "requests") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ ids_t its_instance_method_ranges;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") { // legacy definition for instances
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ std::string value = k->second.data();
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ its_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ } else if (k->first == "instances") { // new instances definition
+ for (auto p = k->second.begin(); p != k->second.end(); ++p) {
+ ranges_t its_instance_ranges;
+ ranges_t its_method_ranges;
+ for (auto m = p->second.begin(); m != p->second.end(); ++m) {
+ if (m->first == "ids") {
+ load_instance_ranges(m->second, its_instance_ranges);
+ } else if (m->first == "methods") {
+ load_instance_ranges(m->second, its_method_ranges);
+ }
+ if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
+ }
+ }
+ }
+ if (its_instance_method_ranges.empty()) {
+ ranges_t its_legacy_instance_ranges;
+ ranges_t its_legacy_method_ranges;
+ its_legacy_method_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ // try to only load instance ranges with any method to be allowed
+ load_instance_ranges(k->second, its_legacy_instance_ranges);
+ if (!its_legacy_instance_ranges.empty() && !its_legacy_method_ranges.empty()) {
+ its_instance_method_ranges.insert(std::make_pair(its_legacy_instance_ranges,
+ its_legacy_method_ranges));
+ }
+ }
+ }
+ }
+ if (service != 0x0 && !its_instance_method_ranges.empty()) {
+ policy->services_.insert(
+ std::make_pair(service, its_instance_method_ranges));
+ }
+ }
+ }
+ if (l->first == "offers") {
+ for (auto n = l->second.begin(); n != l->second.end(); ++n) {
+ service_t service = 0x0;
+ instance_t instance = 0x0;
+ ranges_t its_instance_ranges;
+ for (auto k = n->second.begin(); k != n->second.end(); ++k) {
+ std::stringstream its_converter;
+ if (k->first == "service") {
+ std::string value = k->second.data();
+ its_converter << std::hex << value;
+ its_converter >> service;
+ } else if (k->first == "instance") { // legacy definition for instances
+ std::string value = k->second.data();
+ if (value != "any") {
+ its_converter << std::hex << value;
+ its_converter >> instance;
+ if (instance != 0x0) {
+ its_instance_ranges.insert(std::make_pair(instance, instance));
+ }
+ } else {
+ its_instance_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ }
+ } else if (k->first == "instances") { // new instances definition
+ load_instance_ranges(k->second, its_instance_ranges);
+ }
+ }
+ if (service != 0x0 && !its_instance_ranges.empty()) {
+ policy->offers_.insert(
+ std::make_pair(service, its_instance_ranges));
+ }
+ }
+ }
+ }
+ }
+ }
+ std::lock_guard<std::mutex> its_lock(any_client_policies_mutex_);
+ any_client_policies_.push_back(policy);
+}
+
+void
+security_impl::load_credential(
+ const boost::property_tree::ptree &_tree, ids_t &_ids) {
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ ranges_t its_uid_ranges, its_gid_ranges;
+ for (auto j = i->second.begin(); j != i->second.end(); ++j) {
+ std::string its_key(j->first);
+ if (its_key == "uid") {
+ load_ranges(j->second, its_uid_ranges);
+ } else if (its_key == "gid") {
+ load_ranges(j->second, its_gid_ranges);
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
+ << "Malformed credential (contains illegal key \""
+ << its_key << "\"";
+ }
+ }
+
+ _ids.insert(std::make_pair(its_uid_ranges, its_gid_ranges));
+ }
+}
+
+bool
+security_impl::load_routing_credentials(const configuration_element &_element) {
+ try {
+ auto its_routing_cred = _element.tree_.get_child("routing-credentials");
+ if (is_configured_) {
+ VSOMEIP_WARNING << "vSomeIP Security: Multiple definitions of routing-credentials."
+ << " Ignoring definition from " << _element.name_;
+ } else {
+ for (auto i = its_routing_cred.begin();
+ i != its_routing_cred.end();
+ ++i) {
+ std::string its_key(i->first);
+ std::string its_value(i->second.data());
+ std::stringstream its_converter;
+ if (its_key == "uid") {
+ uint32_t its_uid(0);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_uid;
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ std::get<0>(routing_credentials_) = its_uid;
+ } else if (its_key == "gid") {
+ uint32_t its_gid(0);
+ if (its_value.find("0x") == 0) {
+ its_converter << std::hex << its_value;
+ } else {
+ its_converter << std::dec << its_value;
+ }
+ its_converter >> its_gid;
+ std::lock_guard<std::mutex> its_lock(routing_credentials_mutex_);
+ std::get<1>(routing_credentials_) = its_gid;
+ }
+ }
+ check_routing_credentials_ = true;
+ is_configured_ = true;
+ }
+ } catch (...) {
+ return false;
+ }
+ return true;
+}
+
+
+void
+security_impl::load_security_update_whitelist(const configuration_element &_element) {
+#ifdef _WIN32
+ return;
+#endif
+ try {
+ auto optional = _element.tree_.get_child_optional("security-update-whitelist");
+ if (!optional) {
+ return;
+ }
+ auto found_whitelist = _element.tree_.get_child("security-update-whitelist");
+ for (auto its_whitelist = found_whitelist.begin();
+ its_whitelist != found_whitelist.end(); ++its_whitelist) {
+
+ if (its_whitelist->first == "uids") {
+ {
+ std::lock_guard<std::mutex> its_lock(uid_whitelist_mutex_);
+ load_ranges(its_whitelist->second, uid_whitelist_);
+ }
+ } else if (its_whitelist->first == "services") {
+ {
+ std::lock_guard<std::mutex> its_lock(service_interface_whitelist_mutex_);
+ load_service_ranges(its_whitelist->second, service_interface_whitelist_);
+ }
+ } else if (its_whitelist->first == "check-whitelist") {
+ if (its_whitelist->second.data() == "true") {
+ check_whitelist_ = true;
+ } else {
+ check_whitelist_ = false;
+ }
+ }
+ }
+ } catch (...) {
+ }
+}
+
+void
+security_impl::load_ranges(
+ const boost::property_tree::ptree &_tree, ranges_t &_range) {
+ ranges_t its_ranges;
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ auto its_data = i->second;
+ if (!its_data.data().empty()) {
+ uint32_t its_id;
+ std::stringstream its_converter;
+ its_converter << std::dec << its_data.data();
+ its_converter >> its_id;
+ its_ranges.insert(std::make_pair(its_id, its_id));
+ } else {
+ uint32_t its_first, its_last;
+ bool has_first(false), has_last(false);
+ for (auto j = its_data.begin(); j != its_data.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_value(j->second.data());
+ if (its_key == "first") {
+ if (its_value == "max") {
+ its_first = 0xFFFFFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::dec << j->second.data();
+ its_converter >> its_first;
+ }
+ has_first = true;
+ } else if (its_key == "last") {
+ if (its_value == "max") {
+ its_last = 0xFFFFFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::dec << j->second.data();
+ its_converter >> its_last;
+ }
+ has_last = true;
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
+ << " Malformed range. Contains illegal key ("
+ << its_key << ")";
+ }
+ }
+
+ if (has_first && has_last) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+
+ _range = its_ranges;
+}
+
+void
+security_impl::load_instance_ranges(
+ const boost::property_tree::ptree &_tree, ranges_t &_range) {
+ ranges_t its_ranges;
+ const std::string& key(_tree.data());
+ if (key == "any") {
+ its_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ _range = its_ranges;
+ return;
+ }
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ auto its_data = i->second;
+ if (!its_data.data().empty()) {
+ uint32_t its_id = 0x0;
+ std::stringstream its_converter;
+ its_converter << std::hex << its_data.data();
+ its_converter >> its_id;
+ if (its_id != 0x0) {
+ its_ranges.insert(std::make_pair(its_id, its_id));
+ }
+ } else {
+ uint32_t its_first, its_last;
+ bool has_first(false), has_last(false);
+ for (auto j = its_data.begin(); j != its_data.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_value(j->second.data());
+ if (its_key == "first") {
+ if (its_value == "max") {
+ its_first = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_first;
+ }
+ has_first = true;
+ } else if (its_key == "last") {
+ if (its_value == "max") {
+ its_last = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_last;
+ }
+ has_last = true;
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security configuration: "
+ << " Malformed range. Contains illegal key ("
+ << its_key << ")";
+ }
+ }
+
+ if (has_first && has_last) {
+ if( its_last > its_first) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ }
+
+ _range = its_ranges;
+}
+
+void
+security_impl::load_service_ranges(
+ const boost::property_tree::ptree &_tree, std::set<std::pair<service_t, service_t>> &_ranges) {
+ std::set<std::pair<service_t, service_t>> its_ranges;
+ const std::string& key(_tree.data());
+ if (key == "any") {
+ its_ranges.insert(std::make_pair(0x01, 0xFFFF));
+ _ranges = its_ranges;
+ return;
+ }
+ for (auto i = _tree.begin(); i != _tree.end(); ++i) {
+ auto its_data = i->second;
+ if (!its_data.data().empty()) {
+ service_t its_id = 0x0;
+ std::stringstream its_converter;
+ its_converter << std::hex << its_data.data();
+ its_converter >> its_id;
+ if (its_id != 0x0) {
+ its_ranges.insert(std::make_pair(its_id, its_id));
+ }
+ } else {
+ service_t its_first, its_last;
+ bool has_first(false), has_last(false);
+ for (auto j = its_data.begin(); j != its_data.end(); ++j) {
+ std::string its_key(j->first);
+ std::string its_value(j->second.data());
+ if (its_key == "first") {
+ if (its_value == "max") {
+ its_first = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_first;
+ }
+ has_first = true;
+ } else if (its_key == "last") {
+ if (its_value == "max") {
+ its_last = 0xFFFF;
+ } else {
+ std::stringstream its_converter;
+ its_converter << std::hex << j->second.data();
+ its_converter >> its_last;
+ }
+ has_last = true;
+ } else {
+ VSOMEIP_WARNING << "vSomeIP Security: Security interface whitelist configuration: "
+ << " Malformed range. Contains illegal key ("
+ << its_key << ")";
+ }
+ }
+
+ if (has_first && has_last) {
+ if( its_last >= its_first) {
+ its_ranges.insert(std::make_pair(its_first, its_last));
+ }
+ }
+ }
+ }
+
+ _ranges = its_ranges;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Manage the security object
+////////////////////////////////////////////////////////////////////////////////
+static std::shared_ptr<security_impl> *the_security_ptr__(nullptr);
+static std::mutex the_security_mutex__;
+
+std::shared_ptr<security_impl>
+security_impl::get() {
+#ifndef _WIN32
+ std::lock_guard<std::mutex> its_lock(the_security_mutex__);
+#endif
+ if(the_security_ptr__ == nullptr) {
+ the_security_ptr__ = new std::shared_ptr<security_impl>();
+ }
+ if (the_security_ptr__ != nullptr) {
+ if (!(*the_security_ptr__)) {
+ *the_security_ptr__ = std::make_shared<security_impl>();
+ }
+ return (*the_security_ptr__);
+ }
+ return (nullptr);
+}
+
+#ifndef _WIN32
+static void security_teardown(void) __attribute__((destructor));
+static void security_teardown(void)
+{
+ if (the_security_ptr__ != nullptr) {
+ std::lock_guard<std::mutex> itsLock(the_security_mutex__);
+ the_security_ptr__->reset();
+ delete the_security_ptr__;
+ the_security_ptr__ = nullptr;
+ }
+}
+#endif
+
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/include/configuration_option_impl.hpp b/implementation/service_discovery/include/configuration_option_impl.hpp
index 1d231e8..567762d 100644
--- a/implementation/service_discovery/include/configuration_option_impl.hpp
+++ b/implementation/service_discovery/include/configuration_option_impl.hpp
@@ -1,46 +1,47 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_CONFIGURATION_OPTION_IMPL_HPP
-#define VSOMEIP_SD_CONFIGURATION_OPTION_IMPL_HPP
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "option_impl.hpp"
-
-namespace vsomeip {
-
-class serializer;
-class deserializer;
-
-namespace sd {
-
-class configuration_option_impl: public option_impl {
-
-public:
- configuration_option_impl();
- virtual ~configuration_option_impl();
- bool operator==(const configuration_option_impl &_other) const;
-
- void add_item(const std::string &_key, const std::string &_value);
- void remove_item(const std::string &_key);
-
- std::vector<std::string> get_keys() const;
- std::vector<std::string> get_values() const;
- std::string get_value(const std::string &_key) const;
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- std::map<std::string, std::string> configuration_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_CONFIGURATION_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_CONFIGURATION_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_CONFIGURATION_OPTION_IMPL_HPP_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "option_impl.hpp"
+
+namespace vsomeip_v3 {
+
+class serializer;
+class deserializer;
+
+namespace sd {
+
+class configuration_option_impl: public option_impl {
+
+public:
+ configuration_option_impl();
+ virtual ~configuration_option_impl();
+
+ bool operator==(const option_impl &_other) const;
+
+ void add_item(const std::string &_key, const std::string &_value);
+ void remove_item(const std::string &_key);
+
+ std::vector<std::string> get_keys() const;
+ std::vector<std::string> get_values() const;
+ std::string get_value(const std::string &_key) const;
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ std::map<std::string, std::string> configuration_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_CONFIGURATION_OPTION_IMPL_HPP_
diff --git a/implementation/service_discovery/include/constants.hpp b/implementation/service_discovery/include/constants.hpp
index 31bff53..c50fac1 100644
--- a/implementation/service_discovery/include/constants.hpp
+++ b/implementation/service_discovery/include/constants.hpp
@@ -1,15 +1,15 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SD_CONSTANTS_HPP
-#define VSOMEIP_SD_CONSTANTS_HPP
+#ifndef VSOMEIP_V3_SD_CONSTANTS_HPP_
+#define VSOMEIP_V3_SD_CONSTANTS_HPP_
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
const service_t service = 0xFFFF;
@@ -32,6 +32,6 @@ const uint8_t udp = 0x11;
} // namespace protocol
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SD_CONSTANTS_HPP
+#endif // VSOMEIP_V3_SD_CONSTANTS_HPP_
diff --git a/implementation/service_discovery/include/defines.hpp b/implementation/service_discovery/include/defines.hpp
index 1f884d2..b7e840b 100644
--- a/implementation/service_discovery/include/defines.hpp
+++ b/implementation/service_discovery/include/defines.hpp
@@ -6,8 +6,6 @@
#ifndef VSOMEIP_SD_DEFINES_HPP
#define VSOMEIP_SD_DEFINES_HPP
-#include "../../configuration/include/internal.hpp"
-
#define VSOMEIP_MAX_TCP_SD_PAYLOAD 4075 // Available for entries & options
#define VSOMEIP_MAX_UDP_SD_PAYLOAD 1380
@@ -16,8 +14,13 @@
#define VSOMEIP_SOMEIP_SD_ENTRY_SIZE 16
#define VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE 12
#define VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE 24
+#define VSOMEIP_SOMEIP_SD_LOAD_BALANCING_OPTION_SIZE 8
+#define VSOMEIP_SOMEIP_SD_PROTECTION_OPTION_SIZE 12
+
#define VSOMEIP_SOMEIP_SD_OPTION_LENGTH_SIZE 4
#define VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE 3
+#define VSOMEIP_SOMEIP_SD_EMPTY_MESSAGE_SIZE 28
+#define VSOMEIP_SOMEIP_SD_SPACE_FOR_PAYLOAD VSOMEIP_MAX_UDP_MESSAGE_SIZE - VSOMEIP_SOMEIP_SD_EMPTY_MESSAGE_SIZE;
@@ -27,7 +30,7 @@
#define VSOMEIP_SD_SERVICE 0xFFFF
#define VSOMEIP_SD_INSTANCE 0x0000
#define VSOMEIP_SD_METHOD 0x8100
-#define VSOMEIP_SD_CLIENT (VSOMEIP_DIAGNOSIS_ADDRESS << 8) // SIP_SD_1139
+#define VSOMEIP_SD_CLIENT 0x0
#define VSOMEIP_SD_DEFAULT_ENABLED true
diff --git a/implementation/service_discovery/include/deserializer.hpp b/implementation/service_discovery/include/deserializer.hpp
index a1b45be..97ebcd4 100755
--- a/implementation/service_discovery/include/deserializer.hpp
+++ b/implementation/service_discovery/include/deserializer.hpp
@@ -1,30 +1,31 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_DESERIALIZER_HPP
-#define VSOMEIP_SD_DESERIALIZER_HPP
-
-#include "../../message/include/deserializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class message_impl;
-
-class deserializer: public vsomeip::deserializer {
-public:
- deserializer(std::uint32_t _shrink_buffer_threshold);
- deserializer(uint8_t *_data, std::size_t _length,
- std::uint32_t _shrink_buffer_threshold);
- deserializer(const deserializer &_other);
- virtual ~deserializer();
-
- message_impl * deserialize_sd_message();
-};
-
-} // namespace sd
-} // vsomeip
-
-#endif // VSOMEIP_SD_DESERIALIZER_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_DESERIALIZER_HPP
+#define VSOMEIP_V3_SD_DESERIALIZER_HPP
+
+#include "../../message/include/deserializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class message_impl;
+
+class deserializer
+ : public vsomeip_v3::deserializer {
+public:
+ deserializer(std::uint32_t _shrink_buffer_threshold);
+ deserializer(uint8_t *_data, std::size_t _length,
+ std::uint32_t _shrink_buffer_threshold);
+ deserializer(const deserializer &_other);
+ virtual ~deserializer();
+
+ message_impl * deserialize_sd_message();
+};
+
+} // namespace sd
+} // vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_DESERIALIZER_HPP
diff --git a/implementation/service_discovery/include/entry_impl.hpp b/implementation/service_discovery/include/entry_impl.hpp
index b41a94c..39d5416 100755
--- a/implementation/service_discovery/include/entry_impl.hpp
+++ b/implementation/service_discovery/include/entry_impl.hpp
@@ -1,81 +1,81 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_ENTRY_IMPL_HPP
-#define VSOMEIP_SD_ENTRY_IMPL_HPP
-
-#include <memory>
-#include <vector>
-
-#include <vsomeip/primitive_types.hpp>
-#include <vsomeip/internal/serializable.hpp>
-
-#include "enumeration_types.hpp"
-#include "message_element_impl.hpp"
-
-#define VSOMEIP_MAX_OPTION_RUN 2
-
-namespace vsomeip {
-
-class deserializer;
-
-namespace sd {
-
-class option_impl;
-class message_impl;
-
-class entry_impl: public message_element_impl {
-public:
- virtual ~entry_impl();
-
- // public interface
- entry_type_e get_type() const;
-
- service_t get_service() const;
- void set_service(service_t _service);
-
- instance_t get_instance() const;
- void set_instance(instance_t _instance);
-
- major_version_t get_major_version() const;
- void set_major_version(major_version_t _major_version);
-
- ttl_t get_ttl() const;
- void set_ttl(ttl_t _ttl);
-
- const std::vector<uint8_t> & get_options(uint8_t _run) const;
- void assign_option(const std::shared_ptr<option_impl> &_option);
-
- bool is_service_entry() const;
- bool is_eventgroup_entry() const;
-
- void set_type(entry_type_e _type);
-
- virtual bool serialize(vsomeip::serializer *_to) const;
- virtual bool deserialize(vsomeip::deserializer *_from);
-
- uint8_t get_num_options(uint8_t _run) const;
-
-protected:
- entry_type_e type_;
- service_t service_;
- instance_t instance_;
- major_version_t major_version_;
- ttl_t ttl_;
-
- std::vector<uint8_t> options_[VSOMEIP_MAX_OPTION_RUN];
-
- uint8_t num_options_[VSOMEIP_MAX_OPTION_RUN];
- std::uint8_t index1_;
- std::uint8_t index2_;
-
- entry_impl();
- entry_impl(const entry_impl &_entry);
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_ENTRY_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_ENTRY_IMPL_HPP
+#define VSOMEIP_V3_SD_ENTRY_IMPL_HPP
+
+#include <memory>
+#include <vector>
+
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/internal/serializable.hpp>
+
+#include "enumeration_types.hpp"
+#include "message_element_impl.hpp"
+
+#define VSOMEIP_MAX_OPTION_RUN 2
+
+namespace vsomeip_v3 {
+
+class deserializer;
+
+namespace sd {
+
+class option_impl;
+class message_impl;
+
+class entry_impl: public message_element_impl {
+public:
+ virtual ~entry_impl();
+
+ // public interface
+ entry_type_e get_type() const;
+
+ service_t get_service() const;
+ void set_service(service_t _service);
+
+ instance_t get_instance() const;
+ void set_instance(instance_t _instance);
+
+ major_version_t get_major_version() const;
+ void set_major_version(major_version_t _major_version);
+
+ ttl_t get_ttl() const;
+ void set_ttl(ttl_t _ttl);
+
+ const std::vector<uint8_t> & get_options(uint8_t _run) const;
+ void assign_option(const std::shared_ptr<option_impl> &_option);
+
+ bool is_service_entry() const;
+ bool is_eventgroup_entry() const;
+
+ void set_type(entry_type_e _type);
+
+ virtual bool serialize(vsomeip_v3::serializer *_to) const;
+ virtual bool deserialize(vsomeip_v3::deserializer *_from);
+
+ uint8_t get_num_options(uint8_t _run) const;
+
+protected:
+ entry_type_e type_;
+ service_t service_;
+ instance_t instance_;
+ major_version_t major_version_;
+ ttl_t ttl_;
+
+ std::vector<uint8_t> options_[VSOMEIP_MAX_OPTION_RUN];
+
+ uint8_t num_options_[VSOMEIP_MAX_OPTION_RUN];
+ std::uint8_t index1_;
+ std::uint8_t index2_;
+
+ entry_impl();
+ entry_impl(const entry_impl &_entry);
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_ENTRY_IMPL_HPP
diff --git a/implementation/service_discovery/include/enumeration_types.hpp b/implementation/service_discovery/include/enumeration_types.hpp
index 59538e5..63d0378 100644
--- a/implementation/service_discovery/include/enumeration_types.hpp
+++ b/implementation/service_discovery/include/enumeration_types.hpp
@@ -5,10 +5,10 @@
#include <cstdint>
-#ifndef VSOMEIP_SD_ENUMERATION_TYPES_HPP
-#define VSOMEIP_SD_ENUMERATION_TYPES_HPP
+#ifndef VSOMEIP_V3_SD_ENUMERATION_TYPES_HPP
+#define VSOMEIP_V3_SD_ENUMERATION_TYPES_HPP
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
enum class option_type_e
@@ -20,6 +20,7 @@ enum class option_type_e
IP6_ENDPOINT = 0x6,
IP4_MULTICAST = 0x14,
IP6_MULTICAST = 0x16,
+ SELECTIVE = 0x20,
UNKNOWN = 0xFF
};
@@ -47,6 +48,6 @@ enum class layer_four_protocol_e
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SD_ENUMERATION_TYPES_HPP
+#endif // VSOMEIP_V3_SD_ENUMERATION_TYPES_HPP
diff --git a/implementation/service_discovery/include/eventgroupentry_impl.hpp b/implementation/service_discovery/include/eventgroupentry_impl.hpp
index 3a5d897..08b25a6 100755
--- a/implementation/service_discovery/include/eventgroupentry_impl.hpp
+++ b/implementation/service_discovery/include/eventgroupentry_impl.hpp
@@ -1,68 +1,73 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_EVENTGROUPENTRY_IMPL_HPP
-#define VSOMEIP_SD_EVENTGROUPENTRY_IMPL_HPP
-
-#include "entry_impl.hpp"
-#include "../../endpoints/include/endpoint_definition.hpp"
-#include "message_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class eventgroupentry_impl: public entry_impl {
-public:
- eventgroupentry_impl();
- eventgroupentry_impl(const eventgroupentry_impl &_entry);
- virtual ~eventgroupentry_impl();
-
- eventgroup_t get_eventgroup() const;
- void set_eventgroup(eventgroup_t _eventgroup);
-
- uint16_t get_reserved() const;
- void set_reserved(uint16_t _reserved);
-
- uint8_t get_counter() const;
- void set_counter(uint8_t _counter);
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
- bool operator==(const eventgroupentry_impl& _other) const {
- return (ttl_ == _other.ttl_ &&
- service_ == _other.service_ &&
- instance_ == _other.instance_ &&
- eventgroup_ == _other.eventgroup_ &&
- index1_ == _other.index1_ &&
- index2_ == _other.index2_ &&
- num_options_[0] == _other.num_options_[0] &&
- num_options_[1] == _other.num_options_[1] &&
- major_version_ == _other.major_version_ &&
- counter_ == _other.counter_);
- }
-
- bool is_matching_subscribe(const eventgroupentry_impl& _other,
- const message_impl::options_t& _options) const;
-
- void add_target(const std::shared_ptr<endpoint_definition> &_target);
- std::shared_ptr<endpoint_definition> get_target(bool _reliable) const;
-
-private:
- eventgroup_t eventgroup_;
- uint16_t reserved_;
-
- // counter field to differentiate parallel subscriptions on same event group
- // 4Bit only (max 16. parralel subscriptions)
- uint8_t counter_;
-
- std::shared_ptr<endpoint_definition> target_reliable_;
- std::shared_ptr<endpoint_definition> target_unreliable_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_SD_EVENTGROUPENTRY_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_EVENTGROUPENTRY_IMPL_HPP_
+#define VSOMEIP_V3_SD_EVENTGROUPENTRY_IMPL_HPP_
+
+#include "entry_impl.hpp"
+#include "../../endpoints/include/endpoint_definition.hpp"
+#include "message_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class selective_option_impl;
+
+class eventgroupentry_impl: public entry_impl {
+public:
+ eventgroupentry_impl();
+ eventgroupentry_impl(const eventgroupentry_impl &_entry);
+ virtual ~eventgroupentry_impl();
+
+ eventgroup_t get_eventgroup() const;
+ void set_eventgroup(eventgroup_t _eventgroup);
+
+ uint16_t get_reserved() const;
+ void set_reserved(uint16_t _reserved);
+
+ uint8_t get_counter() const;
+ void set_counter(uint8_t _counter);
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+ bool operator==(const eventgroupentry_impl& _other) const {
+ return (ttl_ == _other.ttl_ &&
+ service_ == _other.service_ &&
+ instance_ == _other.instance_ &&
+ eventgroup_ == _other.eventgroup_ &&
+ index1_ == _other.index1_ &&
+ index2_ == _other.index2_ &&
+ num_options_[0] == _other.num_options_[0] &&
+ num_options_[1] == _other.num_options_[1] &&
+ major_version_ == _other.major_version_ &&
+ counter_ == _other.counter_);
+ }
+
+ bool matches(const eventgroupentry_impl &_other,
+ const message_impl::options_t &_options) const;
+
+ void add_target(const std::shared_ptr<endpoint_definition> &_target);
+ std::shared_ptr<endpoint_definition> get_target(bool _reliable) const;
+
+ std::shared_ptr<selective_option_impl> get_selective_option() const;
+
+private:
+ eventgroup_t eventgroup_;
+ uint16_t reserved_;
+
+ // counter field to differentiate parallel subscriptions on same event group
+ // 4Bit only (max 16. parralel subscriptions)
+ uint8_t counter_;
+
+ std::shared_ptr<endpoint_definition> target_reliable_;
+ std::shared_ptr<endpoint_definition> target_unreliable_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_EVENTGROUPENTRY_IMPL_HPP_
+
diff --git a/implementation/service_discovery/include/ip_option_impl.hpp b/implementation/service_discovery/include/ip_option_impl.hpp
index a2a7660..c83d745 100644
--- a/implementation/service_discovery/include/ip_option_impl.hpp
+++ b/implementation/service_discovery/include/ip_option_impl.hpp
@@ -1,23 +1,25 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SD_IP_OPTION_IMPL_HPP
-#define VSOMEIP_SD_IP_OPTION_IMPL_HPP
+#ifndef VSOMEIP_V3_SD_IP_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_IP_OPTION_IMPL_HPP_
#include <vsomeip/primitive_types.hpp>
#include "option_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
-class ip_option_impl: public option_impl {
+class ip_option_impl
+ : public option_impl {
public:
ip_option_impl();
+ ip_option_impl(const uint16_t _port, const bool _is_reliable);
virtual ~ip_option_impl();
- virtual bool operator ==(const ip_option_impl &_other) const;
+ virtual bool operator ==(const option_impl &_other) const;
uint16_t get_port() const;
void set_port(uint16_t _port);
@@ -27,8 +29,8 @@ public:
virtual bool is_multicast() const = 0;
- virtual bool serialize(vsomeip::serializer *_to) const = 0;
- virtual bool deserialize(vsomeip::deserializer *_from) = 0;
+ virtual bool serialize(vsomeip_v3::serializer *_to) const = 0;
+ virtual bool deserialize(vsomeip_v3::deserializer *_from) = 0;
protected:
layer_four_protocol_e protocol_;
@@ -36,6 +38,7 @@ protected:
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_IP_OPTION_IMPL_HPP_
-#endif // VSOMEIP_SD_IP_OPTION_IMPL_HPP
diff --git a/implementation/service_discovery/include/ipv4_option_impl.hpp b/implementation/service_discovery/include/ipv4_option_impl.hpp
index 8ede63d..15c04b2 100644
--- a/implementation/service_discovery/include/ipv4_option_impl.hpp
+++ b/implementation/service_discovery/include/ipv4_option_impl.hpp
@@ -1,36 +1,42 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_IPV4_OPTION_IMPL_HPP
-#define VSOMEIP_SD_IPV4_OPTION_IMPL_HPP
-
-#include <vsomeip/primitive_types.hpp>
-
-#include "ip_option_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class ipv4_option_impl: public ip_option_impl {
-public:
- ipv4_option_impl(bool _is_multicast);
- virtual ~ipv4_option_impl();
- bool operator ==(const ipv4_option_impl &_other) const;
-
- const ipv4_address_t & get_address() const;
- void set_address(const ipv4_address_t &_address);
-
- bool is_multicast() const;
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- ipv4_address_t address_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_IPV4_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_IPV4_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_IPV4_OPTION_IMPL_HPP_
+
+#include <boost/asio/ip/address.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "ip_option_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class ipv4_option_impl: public ip_option_impl {
+public:
+ ipv4_option_impl();
+ ipv4_option_impl(const boost::asio::ip::address &_address,
+ const uint16_t _port, const bool _is_reliable);
+ virtual ~ipv4_option_impl();
+
+ bool operator ==(const option_impl &_other) const;
+
+ const ipv4_address_t & get_address() const;
+ void set_address(const ipv4_address_t &_address);
+
+ bool is_multicast() const;
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ ipv4_address_t address_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_IPV4_OPTION_IMPL_HPP_
+
diff --git a/implementation/service_discovery/include/ipv6_option_impl.hpp b/implementation/service_discovery/include/ipv6_option_impl.hpp
index 92701c0..d896300 100644
--- a/implementation/service_discovery/include/ipv6_option_impl.hpp
+++ b/implementation/service_discovery/include/ipv6_option_impl.hpp
@@ -1,36 +1,42 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_IPV6_OPTION_IMPL_HPP
-#define VSOMEIP_SD_IPV6_OPTION_IMPL_HPP
-
-#include <vsomeip/primitive_types.hpp>
-
-#include "ip_option_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class ipv6_option_impl: public ip_option_impl {
-public:
- ipv6_option_impl(bool _is_multicast);
- virtual ~ipv6_option_impl();
- bool operator ==(const ipv6_option_impl &_other) const;
-
- const ipv6_address_t & get_address() const;
- void set_address(const ipv6_address_t &_address);
-
- bool is_multicast() const;
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- ipv6_address_t address_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_IPV6_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_IPV6_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_IPV6_OPTION_IMPL_HPP_
+
+#include <boost/asio/ip/address.hpp>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "ip_option_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class ipv6_option_impl
+ : public ip_option_impl {
+public:
+ ipv6_option_impl();
+ ipv6_option_impl(const boost::asio::ip::address &_address,
+ const uint16_t _port, const bool _is_reliable);
+ virtual ~ipv6_option_impl();
+
+ bool operator ==(const option_impl &_other) const;
+
+ const ipv6_address_t & get_address() const;
+ void set_address(const ipv6_address_t &_address);
+
+ bool is_multicast() const;
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ ipv6_address_t address_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_IPV6_OPTION_IMPL_HPP_
diff --git a/implementation/service_discovery/include/load_balancing_option_impl.hpp b/implementation/service_discovery/include/load_balancing_option_impl.hpp
index 767c345..dafcfc7 100755
--- a/implementation/service_discovery/include/load_balancing_option_impl.hpp
+++ b/implementation/service_discovery/include/load_balancing_option_impl.hpp
@@ -1,38 +1,40 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_LOAD_BALANCING_OPTION_IMPL_HPP
-#define VSOMEIP_SD_LOAD_BALANCING_OPTION_IMPL_HPP
-
-#include "primitive_types.hpp"
-#include "option_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class load_balancing_option_impl: public option_impl {
-public:
- load_balancing_option_impl();
- virtual ~load_balancing_option_impl();
- bool operator ==(const load_balancing_option_impl &_other) const;
-
- priority_t get_priority() const;
- void set_priority(priority_t _priority);
-
- weight_t get_weight() const;
- void set_weight(weight_t _weight);
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- priority_t priority_;
- weight_t weight_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_LOAD_BALANCING_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_LOAD_BALANCING_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_LOAD_BALANCING_OPTION_IMPL_HPP_
+
+#include "primitive_types.hpp"
+#include "option_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class load_balancing_option_impl: public option_impl {
+public:
+ load_balancing_option_impl();
+ virtual ~load_balancing_option_impl();
+
+ bool operator ==(const option_impl &_other) const;
+
+ priority_t get_priority() const;
+ void set_priority(priority_t _priority);
+
+ weight_t get_weight() const;
+ void set_weight(weight_t _weight);
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ priority_t priority_;
+ weight_t weight_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_LOAD_BALANCING_OPTION_IMPL_HPP_
+
diff --git a/implementation/service_discovery/include/message_element_impl.hpp b/implementation/service_discovery/include/message_element_impl.hpp
index 835326a..29b5d86 100755
--- a/implementation/service_discovery/include/message_element_impl.hpp
+++ b/implementation/service_discovery/include/message_element_impl.hpp
@@ -1,28 +1,29 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_MESSAGE_ELEMENT_IMPL_HPP
-#define VSOMEIP_SD_MESSAGE_ELEMENT_IMPL_HPP
-
-namespace vsomeip {
-namespace sd {
-
-class message_impl;
-
-class message_element_impl {
-public:
- message_element_impl();
-
- message_impl * get_owning_message() const;
- void set_owning_message(message_impl *_owner);
-
-protected:
- message_impl *owner_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_MESSAGE_ELEMENT_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_MESSAGE_ELEMENT_IMPL_HPP_
+#define VSOMEIP_V3_SD_MESSAGE_ELEMENT_IMPL_HPP_
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class message_impl;
+
+class message_element_impl {
+public:
+ message_element_impl();
+
+ message_impl * get_owning_message() const;
+ void set_owning_message(message_impl *_owner);
+
+protected:
+ message_impl *owner_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_MESSAGE_ELEMENT_IMPL_HPP_
+
diff --git a/implementation/service_discovery/include/message_impl.hpp b/implementation/service_discovery/include/message_impl.hpp
index 83d3a64..b9e858d 100755
--- a/implementation/service_discovery/include/message_impl.hpp
+++ b/implementation/service_discovery/include/message_impl.hpp
@@ -1,127 +1,127 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_MESSAGE_IMPL_HPP
-#define VSOMEIP_SD_MESSAGE_IMPL_HPP
-
-#include <memory>
-#include <vector>
-#include <atomic>
-#include <mutex>
-
-#include <vsomeip/message.hpp>
-
-#include "../include/primitive_types.hpp"
-#include "../../message/include/message_base_impl.hpp"
-#include "../../endpoints/include/endpoint_definition.hpp"
-
-# if _MSC_VER >= 1300
-/*
-* Diamond inheritance is used for the vsomeip::message_base base class.
-* The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class"
-* A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class
-* by using a common abstract base class. This is also called cross delegation.
-*/
-# pragma warning( disable : 4250 )
-# endif
-
-namespace vsomeip {
-namespace sd {
-
-class entry_impl;
-class eventgroupentry_impl;
-class serviceentry_impl;
-
-class option_impl;
-class configuration_option_impl;
-class ipv4_option_impl;
-class ipv6_option_impl;
-class load_balancing_option_impl;
-class protection_option_impl;
-
-class message_impl: public vsomeip::message, public vsomeip::message_base_impl {
-public:
- typedef std::vector<std::shared_ptr<entry_impl>> entries_t;
- typedef std::vector<std::shared_ptr<option_impl>> options_t;
- struct forced_initial_events_t {
- std::shared_ptr<vsomeip::endpoint_definition> target_;
- vsomeip::service_t service_;
- vsomeip::instance_t instance_;
- vsomeip::eventgroup_t eventgroup_;
- };
- message_impl();
- virtual ~message_impl();
-
- length_t get_length() const;
- void set_length(length_t _length);
-
- bool get_reboot_flag() const;
- void set_reboot_flag(bool _is_set);
-
- bool get_unicast_flag() const;
- void set_unicast_flag(bool _is_set);
-
- std::shared_ptr<eventgroupentry_impl> create_eventgroup_entry();
- std::shared_ptr<serviceentry_impl> create_service_entry();
-
- std::shared_ptr<configuration_option_impl> create_configuration_option();
- std::shared_ptr<ipv4_option_impl> create_ipv4_option(bool _is_multicast);
- std::shared_ptr<ipv6_option_impl> create_ipv6_option(bool _is_multicast);
- std::shared_ptr<load_balancing_option_impl> create_load_balancing_option();
- std::shared_ptr<protection_option_impl> create_protection_option();
-
- const entries_t & get_entries() const;
- const options_t & get_options() const;
-
- int16_t get_option_index(const std::shared_ptr<option_impl> &_option) const;
- uint32_t get_options_length();
-
- std::shared_ptr<payload> get_payload() const;
- void set_payload(std::shared_ptr<payload> _payload);
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
- length_t get_someip_length() const;
-
- std::uint8_t get_number_required_acks() const;
- std::uint8_t get_number_contained_acks() const;
- void set_number_required_acks(std::uint8_t _required_acks);
- void increase_number_required_acks(std::uint8_t _amount = 1);
- void decrease_number_required_acks(std::uint8_t _amount = 1);
- void increase_number_contained_acks();
- bool all_required_acks_contained() const;
- std::unique_lock<std::mutex> get_message_lock();
-
- void forced_initial_events_add(forced_initial_events_t _entry);
- const std::vector<forced_initial_events_t> forced_initial_events_get();
-
- void set_initial_events_required(bool _initial_events_required);
- bool initial_events_required() const;
-
-private:
- entry_impl * deserialize_entry(vsomeip::deserializer *_from);
- option_impl * deserialize_option(vsomeip::deserializer *_from);
-
-private:
- flags_t flags_;
- uint32_t options_length_;
-
- entries_t entries_;
- options_t options_;
- std::atomic<std::uint8_t> number_required_acks_;
- std::atomic<std::uint8_t> number_contained_acks_;
- std::mutex message_mutex_;
-
- std::mutex forced_initial_events_mutex_;
- std::vector<forced_initial_events_t> forced_initial_events_info_;
-
- std::atomic<bool> initial_events_required_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_SD_MESSAGE_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_MESSAGE_IMPL_HPP_
+#define VSOMEIP_V3_SD_MESSAGE_IMPL_HPP_
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <vsomeip/message.hpp>
+
+#include "../include/primitive_types.hpp"
+#include "../../message/include/message_base_impl.hpp"
+#include "../../endpoints/include/endpoint_definition.hpp"
+
+# if _MSC_VER >= 1300
+/*
+* Diamond inheritance is used for the vsomeip::message_base base class.
+* The Microsoft compiler put warning (C4250) using a desired c++ feature: "Delegating to a sister class"
+* A powerful technique that arises from using virtual inheritance is to delegate a method from a class in another class
+* by using a common abstract base class. This is also called cross delegation.
+*/
+# pragma warning( disable : 4250 )
+# endif
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class entry_impl;
+class eventgroupentry_impl;
+class serviceentry_impl;
+
+class option_impl;
+class configuration_option_impl;
+class ipv4_option_impl;
+class ipv6_option_impl;
+class load_balancing_option_impl;
+class protection_option_impl;
+class selective_option_impl;
+
+class message_impl
+ : public vsomeip_v3::message, public vsomeip_v3::message_base_impl {
+public:
+ typedef std::vector<std::shared_ptr<entry_impl>> entries_t;
+ typedef std::vector<std::shared_ptr<option_impl>> options_t;
+ struct forced_initial_events_t {
+ std::shared_ptr<vsomeip_v3::endpoint_definition> target_;
+ vsomeip_v3::service_t service_;
+ vsomeip_v3::instance_t instance_;
+ vsomeip_v3::eventgroup_t eventgroup_;
+ };
+ message_impl();
+ virtual ~message_impl();
+
+ length_t get_length() const;
+ void set_length(length_t _length);
+
+ length_t get_size() const;
+
+ bool get_reboot_flag() const;
+ void set_reboot_flag(bool _is_set);
+
+ bool get_unicast_flag() const;
+ void set_unicast_flag(bool _is_set);
+
+ bool has_entry() const;
+ bool has_option() const;
+
+ const entries_t & get_entries() const;
+ const options_t & get_options() const;
+
+ bool add_entry_data(const std::shared_ptr<entry_impl> &_entry,
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ const std::shared_ptr<entry_impl> &_other = nullptr);
+
+ std::shared_ptr<option_impl> find_option(
+ const std::shared_ptr<option_impl> &_option) const;
+
+ int16_t get_option_index(const std::shared_ptr<option_impl> &_option) const;
+ std::shared_ptr<option_impl> get_option(int16_t _index) const;
+ uint32_t get_options_length();
+
+ std::shared_ptr<payload> get_payload() const;
+ void set_payload(std::shared_ptr<payload> _payload);
+
+ uint8_t get_check_result() const;
+ void set_check_result(uint8_t _check_result);
+ bool is_valid_crc() const;
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+ length_t get_someip_length() const;
+
+ void forced_initial_events_add(forced_initial_events_t _entry);
+ const std::vector<forced_initial_events_t> forced_initial_events_get();
+
+ void set_initial_events_required(bool _initial_events_required);
+ bool initial_events_required() const;
+
+ uid_t get_uid() const;
+ gid_t get_gid() const;
+
+private:
+ entry_impl * deserialize_entry(vsomeip_v3::deserializer *_from);
+ option_impl * deserialize_option(vsomeip_v3::deserializer *_from);
+
+private:
+ flags_t flags_;
+ uint32_t options_length_;
+
+ entries_t entries_;
+ options_t options_;
+
+ std::mutex message_mutex_;
+
+ std::uint32_t current_message_size_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_MESSAGE_IMPL_HPP_
diff --git a/implementation/service_discovery/include/option_impl.hpp b/implementation/service_discovery/include/option_impl.hpp
index c4426e9..e171c74 100644
--- a/implementation/service_discovery/include/option_impl.hpp
+++ b/implementation/service_discovery/include/option_impl.hpp
@@ -1,44 +1,50 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_OPTION_IMPL_HPP
-#define VSOMEIP_SD_OPTION_IMPL_HPP
-
-#include <cstdint>
-
-#include "enumeration_types.hpp"
-#include "message_element_impl.hpp"
-
-namespace vsomeip {
-
-class serializer;
-class deserializer;
-
-namespace sd {
-
-class message_impl;
-
-class option_impl: public message_element_impl {
-public:
- option_impl();
- virtual ~option_impl();
-
- virtual bool operator ==(const option_impl &_other) const;
-
- uint16_t get_length() const;
- option_type_e get_type() const;
-
- virtual bool serialize(vsomeip::serializer *_to) const;
- virtual bool deserialize(vsomeip::deserializer *_from);
-
-protected:
- uint16_t length_;
- option_type_e type_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_INTERNAL_SD_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_OPTION_IMPL_HPP_
+
+#include <cstdint>
+#include <memory>
+
+#include "enumeration_types.hpp"
+#include "message_element_impl.hpp"
+
+namespace vsomeip_v3 {
+
+class serializer;
+class deserializer;
+
+namespace sd {
+
+class message_impl;
+
+class option_impl: public message_element_impl {
+public:
+ option_impl();
+ virtual ~option_impl();
+
+ virtual bool operator ==(const option_impl &_other) const;
+ bool equals(const std::shared_ptr<option_impl> &_other) const;
+
+ uint16_t get_length() const;
+ option_type_e get_type() const;
+
+ inline uint32_t get_size() const {
+ return static_cast<uint32_t>(length_) + 3;
+ }
+
+ virtual bool serialize(vsomeip_v3::serializer *_to) const;
+ virtual bool deserialize(vsomeip_v3::deserializer *_from);
+
+protected:
+ uint16_t length_;
+ option_type_e type_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_OPTION_IMPL_HPP_
diff --git a/implementation/service_discovery/include/primitive_types.hpp b/implementation/service_discovery/include/primitive_types.hpp
index f3a0c9f..fd093e9 100644
--- a/implementation/service_discovery/include/primitive_types.hpp
+++ b/implementation/service_discovery/include/primitive_types.hpp
@@ -1,14 +1,14 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <cstdint>
-#ifndef VSOMEIP_SD_PRIMITIVE_TYPES_HPP
-#define VSOMEIP_SD_PRIMITIVE_TYPES_HPP
+#ifndef VSOMEIP_V3_SD_PRIMITIVE_TYPES_HPP_
+#define VSOMEIP_V3_SD_PRIMITIVE_TYPES_HPP_
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
// Load balancing
@@ -23,6 +23,6 @@ typedef uint32_t crc_t;
typedef uint8_t flags_t;
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SD_PRIMITIVE_TYPES_HPP
+#endif // VSOMEIP_V3_SD_PRIMITIVE_TYPES_HPP_
diff --git a/implementation/service_discovery/include/protection_option_impl.hpp b/implementation/service_discovery/include/protection_option_impl.hpp
index 33d5849..792d7cc 100755
--- a/implementation/service_discovery/include/protection_option_impl.hpp
+++ b/implementation/service_discovery/include/protection_option_impl.hpp
@@ -1,38 +1,39 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_PROTECTION_OPTION_IMPL_HPP
-#define VSOMEIP_SD_PROTECTION_OPTION_IMPL_HPP
-
-#include "../include/primitive_types.hpp"
-#include "../include/option_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class protection_option_impl: public option_impl {
-public:
- protection_option_impl();
- virtual ~protection_option_impl();
- bool operator ==(const protection_option_impl &_other) const;
-
- alive_counter_t get_alive_counter() const;
- void set_alive_counter(alive_counter_t _counter);
-
- crc_t get_crc() const;
- void set_crc(crc_t _crc);
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- alive_counter_t counter_;
- crc_t crc_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_PROTECTION_OPTION_IMPL_HPP
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_PROTECTION_OPTION_IMPL_HPP_
+#define VSOMEIP_V3_SD_PROTECTION_OPTION_IMPL_HPP_
+
+#include "../include/primitive_types.hpp"
+#include "../include/option_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class protection_option_impl: public option_impl {
+public:
+ protection_option_impl();
+ virtual ~protection_option_impl();
+
+ bool operator ==(const option_impl &_other) const;
+
+ alive_counter_t get_alive_counter() const;
+ void set_alive_counter(alive_counter_t _counter);
+
+ crc_t get_crc() const;
+ void set_crc(crc_t _crc);
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ alive_counter_t counter_;
+ crc_t crc_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_PROTECTION_OPTION_IMPL_HPP_
diff --git a/implementation/service_discovery/include/remote_subscription_ack.hpp b/implementation/service_discovery/include/remote_subscription_ack.hpp
new file mode 100644
index 0000000..1bc8792
--- /dev/null
+++ b/implementation/service_discovery/include/remote_subscription_ack.hpp
@@ -0,0 +1,64 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_REMOTE_SUBSCRIPTION_ACK_HPP_
+#define VSOMEIP_V3_SD_REMOTE_SUBSCRIPTION_ACK_HPP_
+
+#include <memory>
+#include <mutex>
+#include <set>
+
+namespace vsomeip_v3 {
+
+class remote_subscription;
+
+namespace sd {
+
+class message_impl;
+
+class remote_subscription_ack {
+public:
+ remote_subscription_ack(const boost::asio::ip::address &_address);
+
+ // The complete flag signals whether or not all subscribes
+ // of a message have been inserted.
+ bool is_complete() const;
+ void complete();
+
+ // The done flag signals whether or not all subscribes
+ // have been processed.
+ bool is_done() const;
+ void done();
+
+ std::vector<std::shared_ptr<message_impl> > get_messages() const;
+ std::shared_ptr<message_impl> get_current_message() const;
+ std::shared_ptr<message_impl> add_message();
+
+ boost::asio::ip::address get_target_address() const;
+
+ bool is_pending() const;
+
+ std::set<std::shared_ptr<remote_subscription> > get_subscriptions() const;
+ void add_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription);
+ bool has_subscription() const;
+
+ std::unique_lock<std::recursive_mutex> get_lock();
+
+private:
+ std::recursive_mutex mutex_;
+ std::vector<std::shared_ptr<message_impl> > messages_;
+ bool is_complete_;
+ bool is_done_;
+
+ const boost::asio::ip::address target_address_;
+
+ std::set<std::shared_ptr<remote_subscription> > subscriptions_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_REMOTE_SUBSCRIPTION_ACK_HPP_
diff --git a/implementation/service_discovery/include/request.hpp b/implementation/service_discovery/include/request.hpp
index b835202..0e6e2ec 100644
--- a/implementation/service_discovery/include/request.hpp
+++ b/implementation/service_discovery/include/request.hpp
@@ -1,16 +1,16 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SD_REQUEST_HPP
-#define VSOMEIP_SD_REQUEST_HPP
+#ifndef VSOMEIP_V3_SD_REQUEST_HPP_
+#define VSOMEIP_V3_SD_REQUEST_HPP_
#include <memory>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
@@ -41,6 +41,6 @@ private:
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SD_SUBSCRIPTION_HPP
+#endif // VSOMEIP_V3_SD_REQUEST_HPP_
diff --git a/implementation/service_discovery/include/runtime.hpp b/implementation/service_discovery/include/runtime.hpp
index 670a7bb..0772de4 100644
--- a/implementation/service_discovery/include/runtime.hpp
+++ b/implementation/service_discovery/include/runtime.hpp
@@ -1,36 +1,38 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_RUNTIME_HPP
-#define VSOMEIP_SD_RUNTIME_HPP
-
-#include <memory>
-
-namespace vsomeip {
-
-class configuration;
-
-namespace sd {
-
-class message_impl;
-class service_discovery;
-class service_discovery_host;
-
-class runtime {
-public:
- virtual ~runtime() {
- }
-
- virtual std::shared_ptr<service_discovery> create_service_discovery(
- service_discovery_host *_host,
- std::shared_ptr<vsomeip::configuration> _configuration) const = 0;
- virtual std::shared_ptr<message_impl> create_message() const = 0;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_RUNTIME_HPP
-
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_RUNTIME_HPP_
+#define VSOMEIP_V3_SD_RUNTIME_HPP_
+
+#include <memory>
+
+namespace vsomeip_v3 {
+
+class configuration;
+
+namespace sd {
+
+class message_impl;
+class service_discovery;
+class service_discovery_host;
+
+class runtime {
+public:
+ virtual ~runtime()
+#ifndef ANDROID
+ {}
+#else
+ ;
+#endif
+
+ virtual std::shared_ptr<service_discovery> create_service_discovery(
+ service_discovery_host *_host,
+ std::shared_ptr<configuration> _configuration) const = 0;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_RUNTIME_HPP_
diff --git a/implementation/service_discovery/include/runtime_impl.hpp b/implementation/service_discovery/include/runtime_impl.hpp
index 0a9baaf..0010de6 100644
--- a/implementation/service_discovery/include/runtime_impl.hpp
+++ b/implementation/service_discovery/include/runtime_impl.hpp
@@ -1,15 +1,15 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SD_RUNTIME_IMPL_HPP
-#define VSOMEIP_SD_RUNTIME_IMPL_HPP
+#ifndef VSOMEIP_V3_SD_RUNTIME_IMPL_HPP_
+#define VSOMEIP_V3_SD_RUNTIME_IMPL_HPP_
#include <vsomeip/plugin.hpp>
#include "runtime.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
class runtime_impl
@@ -22,10 +22,10 @@ public:
std::shared_ptr<service_discovery> create_service_discovery(
service_discovery_host *_host,
std::shared_ptr<configuration> _configuration) const;
- std::shared_ptr<message_impl> create_message() const;
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_RUNTIME_IMPL_HPP_
-#endif // VSOMEIP_SD_RUNTIME_IMPL_HPP
diff --git a/implementation/service_discovery/include/selective_option_impl.hpp b/implementation/service_discovery/include/selective_option_impl.hpp
new file mode 100644
index 0000000..0660f1e
--- /dev/null
+++ b/implementation/service_discovery/include/selective_option_impl.hpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_SELECTIVE_OPTION_IMPL_HPP
+#define VSOMEIP_V3_SD_SELECTIVE_OPTION_IMPL_HPP
+
+#include <set>
+
+#include <vsomeip/primitive_types.hpp>
+
+#include "option_impl.hpp"
+
+namespace vsomeip_v3 {
+
+class serializer;
+class deserializer;
+
+namespace sd {
+
+class selective_option_impl: public option_impl {
+
+public:
+ selective_option_impl();
+ virtual ~selective_option_impl();
+
+ bool operator==(const option_impl &_other) const;
+
+ std::set<client_t> get_clients() const;
+ bool add_client(client_t _client);
+ bool remove_client(client_t _client);
+ bool has_clients() const;
+ bool has_client(client_t _client);
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ std::set<client_t> clients_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_SELECTIVE_OPTION_IMPL_HPP
diff --git a/implementation/service_discovery/include/service_discovery.hpp b/implementation/service_discovery/include/service_discovery.hpp
index e1c3dc4..0a5adc0 100644
--- a/implementation/service_discovery/include/service_discovery.hpp
+++ b/implementation/service_discovery/include/service_discovery.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SERVICE_DISCOVERY_HPP
-#define VSOMEIP_SERVICE_DISCOVERY_HPP
+#ifndef VSOMEIP_V3_SD_SERVICE_DISCOVERY_HPP_
+#define VSOMEIP_V3_SD_SERVICE_DISCOVERY_HPP_
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/address.hpp>
@@ -16,7 +16,7 @@
#include "../../endpoints/include/endpoint.hpp"
#include "../include/service_discovery_host.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
@@ -38,13 +38,11 @@ public:
virtual void release_service(service_t _service, instance_t _instance) = 0;
virtual void subscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client,
- subscription_type_e _subscription_type) = 0;
+ eventgroup_t _eventgroup, major_version_t _major,
+ ttl_t _ttl, client_t _client) = 0;
virtual void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client) = 0;
virtual void unsubscribe_all(service_t _service, instance_t _instance) = 0;
- virtual void unsubscribe_client(service_t _service, instance_t _instance,
- client_t _client) = 0;
virtual bool send(bool _is_announcing) = 0;
@@ -52,34 +50,27 @@ public:
const boost::asio::ip::address &_sender,
const boost::asio::ip::address &_destination) = 0;
- virtual void send_subscriptions(service_t _service, instance_t _instance,
- client_t _client, bool _reliable) = 0;
-
virtual void on_endpoint_connected(
service_t _service, instance_t _instance,
- const std::shared_ptr<const vsomeip::endpoint> &_endpoint) = 0;
+ const std::shared_ptr<endpoint> &_endpoint) = 0;
- virtual void offer_service(service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info) = 0;
- virtual void stop_offer_service(service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info) = 0;
+ virtual void offer_service(const std::shared_ptr<serviceinfo> &_info) = 0;
+ virtual void stop_offer_service(const std::shared_ptr<serviceinfo> &_info) = 0;
virtual void set_diagnosis_mode(const bool _activate) = 0;
virtual bool get_diagnosis_mode() = 0;
- virtual void remote_subscription_acknowledge(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- client_t _client, bool _accepted,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id) = 0;
+ virtual void update_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription) = 0;
- virtual void register_offer_acceptance_handler(
- vsomeip::offer_acceptance_handler_t _handler) = 0;
+ virtual void register_sd_acceptance_handler(
+ sd_acceptance_handler_t _handler) = 0;
virtual void register_reboot_notification_handler(
reboot_notification_handler_t _handler) = 0;
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_SERVICE_DISCOVERY_HPP
+#endif // VSOMEIP_V3_SD_SERVICE_DISCOVERY_HPP_
diff --git a/implementation/service_discovery/include/service_discovery_host.hpp b/implementation/service_discovery/include/service_discovery_host.hpp
index 9c346fd..94b67ec 100644
--- a/implementation/service_discovery/include/service_discovery_host.hpp
+++ b/implementation/service_discovery/include/service_discovery_host.hpp
@@ -1,10 +1,10 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SERVICE_DISCOVERY_HOST_HPP
-#define VSOMEIP_SERVICE_DISCOVERY_HOST_HPP
+#ifndef VSOMEIP_V3_SERVICE_DISCOVERY_HOST_HPP_
+#define VSOMEIP_V3_SERVICE_DISCOVERY_HOST_HPP_
#include <map>
#include <memory>
@@ -13,11 +13,12 @@
#include <boost/asio/ip/address.hpp>
#include <boost/asio/io_service.hpp>
+#include "../../routing/include/function_types.hpp"
#include "../../routing/include/types.hpp"
#include <vsomeip/message.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
class endpoint;
@@ -39,10 +40,9 @@ public:
virtual std::shared_ptr<eventgroupinfo> find_eventgroup(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) const = 0;
- virtual bool send(client_t _client, std::shared_ptr<message> _message,
- bool _flush) = 0;
+ virtual bool send(client_t _client, std::shared_ptr<message> _message) = 0;
- virtual bool send_to(const std::shared_ptr<endpoint_definition> &_target,
+ virtual bool send_via_sd(const std::shared_ptr<endpoint_definition> &_target,
const byte_t *_data, uint32_t _size, uint16_t _sd_port) = 0;
virtual void add_routing_info(service_t _service, instance_t _instance,
@@ -57,37 +57,30 @@ public:
virtual void update_routing_info(std::chrono::milliseconds _elapsed) = 0;
- virtual void on_unsubscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup,
- std::shared_ptr<endpoint_definition> _target) = 0;
-
- virtual void on_subscribe_ack(service_t _service, instance_t _instance,
- const boost::asio::ip::address &_address, uint16_t _port) = 0;
+ virtual void on_remote_unsubscribe(
+ std::shared_ptr<remote_subscription> &_subscription) = 0;
virtual void on_subscribe_ack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) = 0;
+ event_t _event, remote_subscription_id_t _subscription_id) = 0;
- virtual std::shared_ptr<endpoint> find_or_create_remote_client(
+ virtual void on_subscribe_ack_with_multicast(
service_t _service, instance_t _instance,
- bool _reliable, client_t _client) = 0;
+ const boost::asio::ip::address &_address, uint16_t _port) = 0;
+
+ virtual std::shared_ptr<endpoint> find_or_create_remote_client(
+ service_t _service, instance_t _instance, bool _reliable, client_t _client) = 0;
virtual void expire_subscriptions(const boost::asio::ip::address &_address) = 0;
virtual void expire_services(const boost::asio::ip::address &_address) = 0;
- virtual void on_remote_subscription(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<endpoint_definition> &_subscriber,
- const std::shared_ptr<endpoint_definition> &_target, ttl_t _ttl,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id,
- const std::function<void(remote_subscription_state_e, client_t)>& _callback) = 0;
+ virtual void on_remote_subscribe(
+ std::shared_ptr<remote_subscription> &_subscription,
+ const remote_subscription_callback_t& _callback) = 0;
virtual void on_subscribe_nack(client_t _client,
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- event_t _event, pending_subscription_id_t _subscription_id) = 0;
-
- virtual bool has_identified(client_t _client, service_t _service,
- instance_t _instance, bool _reliable) = 0;
+ event_t _event, remote_subscription_id_t _subscription_id) = 0;
virtual std::chrono::steady_clock::time_point expire_subscriptions(bool _force) = 0;
@@ -95,13 +88,10 @@ public:
service_t _service, instance_t _instance) const = 0;
virtual std::map<instance_t, std::shared_ptr<serviceinfo>> get_offered_service_instances(
service_t _service) const = 0;
-
- virtual void send_initial_events(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup,
- const std::shared_ptr<endpoint_definition>& _subscriber) = 0;
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SERVICE_DISCOVERY_HOST_HPP_
-#endif // VSOMEIP_SERVICE_DISCOVERY_HOST_HPP
diff --git a/implementation/service_discovery/include/service_discovery_impl.hpp b/implementation/service_discovery/include/service_discovery_impl.hpp
index 77dbae9..ba3c723 100644
--- a/implementation/service_discovery/include/service_discovery_impl.hpp
+++ b/implementation/service_discovery/include/service_discovery_impl.hpp
@@ -1,10 +1,10 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SERVICE_DISCOVERY_IMPL
-#define VSOMEIP_SERVICE_DISCOVERY_IMPL
+#ifndef VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_
+#define VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_
#include <map>
#include <memory>
@@ -16,16 +16,19 @@
#include <boost/asio/steady_timer.hpp>
-#include "service_discovery.hpp"
+#include "../../configuration/include/configuration.hpp"
#include "../../endpoints/include/endpoint_definition.hpp"
#include "../../routing/include/types.hpp"
+#include "../../routing/include/remote_subscription.hpp"
+
+#include "service_discovery.hpp"
#include "ip_option_impl.hpp"
#include "ipv4_option_impl.hpp"
#include "ipv6_option_impl.hpp"
#include "deserializer.hpp"
-#include "../../configuration/include/configuration.hpp"
+#include "message_impl.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
class serializer;
@@ -35,29 +38,29 @@ namespace sd {
class entry_impl;
class eventgroupentry_impl;
class option_impl;
+class remote_subscription_ack;
class request;
class serviceentry_impl;
class service_discovery_host;
class subscription;
-typedef std::map<service_t, std::map<instance_t, std::shared_ptr<request> > > requests_t;
-
-struct subscriber_t {
- std::shared_ptr<endpoint_definition> subscriber;
- std::shared_ptr<endpoint_definition> target;
- std::shared_ptr<sd_message_identifier_t> response_message_id_;
- std::shared_ptr<eventgroupinfo> eventgroupinfo_;
- vsomeip::ttl_t ttl_;
- vsomeip::major_version_t major_;
- std::uint16_t reserved_;
- std::uint8_t counter_;
+typedef std::map<service_t,
+ std::map<instance_t,
+ std::shared_ptr<request>
+ >
+ > requests_t;
+
+struct entry_data_t {
+ std::shared_ptr<entry_impl> entry_;
+ std::vector<std::shared_ptr<option_impl> > options_;
+ std::shared_ptr<entry_impl> other_;
};
class service_discovery_impl: public service_discovery,
public std::enable_shared_from_this<service_discovery_impl> {
public:
service_discovery_impl(service_discovery_host *_host,
- std::shared_ptr<configuration> _configuration);
+ const std::shared_ptr<configuration>& _configuration);
virtual ~service_discovery_impl();
boost::asio::io_service & get_io();
@@ -71,13 +74,11 @@ public:
void release_service(service_t _service, instance_t _instance);
void subscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client,
- subscription_type_e _subscription_type);
+ eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl,
+ client_t _client);
void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, client_t _client);
void unsubscribe_all(service_t _service, instance_t _instance);
- void unsubscribe_client(service_t _service, instance_t _instance,
- client_t _client);
bool send(bool _is_announcing);
@@ -87,23 +88,20 @@ public:
void on_endpoint_connected(
service_t _service, instance_t _instance,
- const std::shared_ptr<const vsomeip::endpoint> &_endpoint);
+ const std::shared_ptr<endpoint> &_endpoint);
- void offer_service(service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info);
- void stop_offer_service(service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info);
+ void offer_service(const std::shared_ptr<serviceinfo> &_info);
+ void stop_offer_service(const std::shared_ptr<serviceinfo> &_info);
void set_diagnosis_mode(const bool _activate);
bool get_diagnosis_mode();
- void remote_subscription_acknowledge(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- client_t _client, bool _acknowledged,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id);
- void register_offer_acceptance_handler(offer_acceptance_handler_t _handler);
+ void update_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription);
+
+ void register_sd_acceptance_handler(sd_acceptance_handler_t _handler);
void register_reboot_notification_handler(
reboot_notification_handler_t _handler);
private:
@@ -114,55 +112,43 @@ private:
const boost::asio::ip::address &_destination,
bool _reboot_flag, session_t _session);
- void insert_option(std::shared_ptr<message_impl> &_message,
- std::shared_ptr<entry_impl> _entry,
- const boost::asio::ip::address &_address, uint16_t _port,
- bool _is_reliable);
- void insert_find_entries(std::shared_ptr<message_impl> &_message,
- const requests_t &_requests, uint32_t _start,
- uint32_t &_size, bool &_done);
- void insert_offer_entries(std::shared_ptr<message_impl> &_message,
- const services_t &_services, uint32_t &_start,
- uint32_t _size, bool &_done, bool _ignore_phase);
- bool insert_offer_service(std::shared_ptr<message_impl> _message,
- service_t _service, instance_t _instance,
- const std::shared_ptr<const serviceinfo> &_info,
- uint32_t &_size);
+ void insert_find_entries(std::vector<std::shared_ptr<message_impl> > &_messages,
+ const requests_t &_requests);
+ void insert_offer_entries(std::vector<std::shared_ptr<message_impl> > &_messages,
+ const services_t &_services, bool _ignore_phase);
+ void insert_offer_service(std::vector<std::shared_ptr<message_impl> > &_messages,
+ const std::shared_ptr<const serviceinfo> &_info);
enum remote_offer_type_e : std::uint8_t {
RELIABLE_UNRELIABLE,
RELIABLE,
UNRELIABLE,
UNKNOWN = 0xff
};
- bool insert_subscription(std::shared_ptr<message_impl> &_message,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<subscription> &_subscription,
- remote_offer_type_e _offer_type);
- bool insert_nack_subscription_on_resubscribe(std::shared_ptr<message_impl> &_message,
+
+ entry_data_t create_eventgroup_entry(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<subscription> &_subscription,
+ const std::shared_ptr<subscription> &_subscription,
remote_offer_type_e _offer_type);
- void insert_subscription_ack(std::shared_ptr<message_impl> &_message,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+
+ void insert_subscription_ack(
+ const std::shared_ptr<remote_subscription_ack>& _acknowledgement,
const std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl,
- uint8_t _counter, major_version_t _major, uint16_t _reserved,
- const std::shared_ptr<endpoint_definition> &_target = nullptr);
- void insert_subscription_nack(std::shared_ptr<message_impl> &_message, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- uint8_t _counter, major_version_t _major, uint16_t _reserved);
+ const std::shared_ptr<endpoint_definition> &_target = nullptr,
+ const client_t _client = VSOMEIP_ROUTING_CLIENT);
void process_serviceentry(std::shared_ptr<serviceentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
- bool _unicast_flag,
- std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes,
- bool _accept_offers);
+ bool _unicast_flag, std::vector<std::shared_ptr<message_impl> > &_resubscribes,
+ bool _received_via_mcast, bool _accept_offers);
void process_offerservice_serviceentry(
service_t _service, instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl,
const boost::asio::ip::address &_reliable_address,
uint16_t _reliable_port,
const boost::asio::ip::address &_unreliable_address,
- uint16_t _unreliable_port, std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes);
+ uint16_t _unreliable_port,
+ std::vector<std::shared_ptr<message_impl> > &_resubscribes,
+ bool _received_via_mcast);
void send_offer_service(
const std::shared_ptr<const serviceinfo> &_info, service_t _service,
instance_t _instance, major_version_t _major, minor_version_t _minor,
@@ -176,11 +162,9 @@ private:
void process_eventgroupentry(
std::shared_ptr<eventgroupentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
- std::shared_ptr < message_impl > &its_message_response,
+ std::shared_ptr<remote_subscription_ack> &_acknowledgement,
const boost::asio::ip::address &_destination,
- const std::shared_ptr<sd_message_identifier_t> &_message_id,
- bool _is_stop_subscribe_subscribe,
- bool _force_initial_events);
+ bool _is_stop_subscribe_subscribe, bool _force_initial_events);
void handle_eventgroup_subscription(service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
major_version_t _major, ttl_t _ttl, uint8_t _counter, uint16_t _reserved,
@@ -188,22 +172,30 @@ private:
bool _is_first_reliable,
const boost::asio::ip::address &_second_address, uint16_t _second_port,
bool _is_second_reliable,
- std::shared_ptr < message_impl > &its_message,
- const std::shared_ptr<sd_message_identifier_t> &_message_id,
- bool _is_stop_subscribe_subscribe,
- bool _force_initial_events);
+ std::shared_ptr<remote_subscription_ack> &_acknowledgement,
+ bool _is_stop_subscribe_subscribe, bool _force_initial_events,
+ const std::set<client_t> &_clients,
+ const std::shared_ptr<eventgroupinfo>& _info);
void handle_eventgroup_subscription_ack(service_t _service,
instance_t _instance, eventgroup_t _eventgroup,
major_version_t _major, ttl_t _ttl, uint8_t _counter,
+ const std::set<client_t> &_clients,
const boost::asio::ip::address &_address, uint16_t _port);
void handle_eventgroup_subscription_nack(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter);
- void serialize_and_send(std::shared_ptr<message_impl> _message,
+ instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter,
+ const std::set<client_t> &_clients);
+
+ bool send(const std::vector<std::shared_ptr<message_impl>> &_messages);
+ bool serialize_and_send(
+ const std::vector<std::shared_ptr<message_impl>> &_messages,
const boost::asio::ip::address &_address);
+ void update_acknowledgement(
+ const std::shared_ptr<remote_subscription_ack> &_acknowledgement);
+
bool is_tcp_connected(service_t _service,
instance_t _instance,
- std::shared_ptr<vsomeip::endpoint_definition> its_endpoint);
+ const std::shared_ptr<endpoint_definition>& its_endpoint);
void start_ttl_timer();
void stop_ttl_timer();
@@ -221,33 +213,14 @@ private:
bool check_static_header_fields(
const std::shared_ptr<const message> &_message) const;
bool check_layer_four_protocol(
- const std::shared_ptr<const ip_option_impl> _ip_option) const;
- void get_subscription_endpoints(std::shared_ptr<endpoint>& _unreliable,
- std::shared_ptr<endpoint>& _reliable,
- boost::asio::ip::address* _address,
- bool* _has_address,
- service_t _service, instance_t _instance,
- client_t _client) const;
-
- void send_subscriptions(service_t _service, instance_t _instance, client_t _client, bool _reliable);
-
- template<class Option, typename AddressType>
- std::shared_ptr<option_impl> find_existing_option(
- std::shared_ptr<message_impl> &_message,
- AddressType _address, uint16_t _port,
- layer_four_protocol_e _protocol,
- option_type_e _option_type);
- template<class Option, typename AddressType>
- bool check_message_for_ip_option_and_assign_existing(
- std::shared_ptr<message_impl> &_message,
- std::shared_ptr<entry_impl> _entry, AddressType _address,
- uint16_t _port, layer_four_protocol_e _protocol,
- option_type_e _option_type);
- template<class Option, typename AddressType>
- void assign_ip_option_to_entry(std::shared_ptr<Option> _option,
- AddressType _address, uint16_t _port,
- layer_four_protocol_e _protocol,
- std::shared_ptr<entry_impl> _entry);
+ const std::shared_ptr<const ip_option_impl>& _ip_option) const;
+
+ void get_subscription_endpoints(service_t _service, instance_t _instance,
+ std::shared_ptr<endpoint>& _reliable,
+ std::shared_ptr<endpoint>& _unreliable) const;
+ void get_subscription_address(const std::shared_ptr<endpoint> &_reliable,
+ const std::shared_ptr<endpoint> &_unreliable,
+ boost::asio::ip::address &_address) const;
std::shared_ptr<request> find_request(service_t _service, instance_t _instance);
@@ -261,71 +234,57 @@ private:
void on_repetition_phase_timer_expired(
const boost::system::error_code &_error,
- std::shared_ptr<boost::asio::steady_timer> _timer,
+ const std::shared_ptr<boost::asio::steady_timer>& _timer,
std::uint8_t _repetition, std::uint32_t _last_delay);
void on_find_repetition_phase_timer_expired(
const boost::system::error_code &_error,
- std::shared_ptr<boost::asio::steady_timer> _timer,
+ const std::shared_ptr<boost::asio::steady_timer>& _timer,
std::uint8_t _repetition, std::uint32_t _last_delay);
void move_offers_into_main_phase(
const std::shared_ptr<boost::asio::steady_timer> &_timer);
- void fill_message_with_offer_entries(
- std::shared_ptr<runtime> _runtime,
- std::shared_ptr<message_impl> _message,
- std::vector<std::shared_ptr<message_impl>> &_messages,
- const services_t &_offers, bool _ignore_phase);
-
- void fill_message_with_find_entries(
- std::shared_ptr<runtime> _runtime,
- std::shared_ptr<message_impl> _message,
- std::vector<std::shared_ptr<message_impl>> &_messages,
- const requests_t &_requests);
-
- bool serialize_and_send_messages(
- const std::vector<std::shared_ptr<message_impl>> &_messages);
-
- bool send_stop_offer(service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info);
+ bool send_stop_offer(const std::shared_ptr<serviceinfo>& _info);
void start_main_phase_timer();
void on_main_phase_timer_expired(const boost::system::error_code &_error);
void send_uni_or_multicast_offerservice(
- service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor,
const std::shared_ptr<const serviceinfo> &_info,
bool _unicast_flag);
bool last_offer_shorter_half_offer_delay_ago();
void send_unicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ const std::shared_ptr<const serviceinfo> &_info);
void send_multicast_offer_service(
- const std::shared_ptr<const serviceinfo>& _info, service_t _service,
- instance_t _instance, major_version_t _major,
- minor_version_t _minor);
+ const std::shared_ptr<const serviceinfo>& _info);
bool check_source_address(const boost::asio::ip::address &its_source_address) const;
- void update_subscription_expiration_timer(const std::shared_ptr<message_impl> &_message);
+ void update_subscription_expiration_timer(
+ const std::vector<std::shared_ptr<message_impl> > &_messages);
- void remote_subscription_acknowledge_subscriber(
+ void remote_subscription_acknowledge(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<subscriber_t> &_subscriber, bool _acknowledged);
+ const std::shared_ptr<remote_subscription> &_subscription);
- void remote_subscription_not_acknowledge_subscriber(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<subscriber_t> &_subscriber, bool _acknowledged);
+ bool check_stop_subscribe_subscribe(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t &_options) const;
- void remote_subscription_not_acknowledge_all(service_t _service, instance_t _instance);
+ bool has_opposite(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t &_options) const;
- void remote_subscription_not_acknowledge_all();
+ bool has_same(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t &_options) const;
- bool check_stop_subscribe_subscribe(message_impl::entries_t::const_iterator _iter,
- message_impl::entries_t::const_iterator _end,
- const message_impl::options_t& _options) const;
+ bool is_subscribed(
+ const std::shared_ptr<eventgroupentry_impl> &_entry,
+ const message_impl::options_t &_options) const;
configuration::ttl_factor_t get_ttl_factor(
service_t _service, instance_t _instance,
@@ -333,8 +292,11 @@ private:
void on_last_msg_received_timer_expired(const boost::system::error_code &_error);
void stop_last_msg_received_timer();
+ remote_offer_type_e get_remote_offer_type(
+ service_t _service, instance_t _instance) const;
+ remote_offer_type_e get_remote_offer_type(
+ const std::shared_ptr<subscription> &_subscription) const;
- remote_offer_type_e get_remote_offer_type(service_t _service, instance_t _instance);
bool update_remote_offer_type(service_t _service, instance_t _instance,
remote_offer_type_e _offer_type,
const boost::asio::ip::address &_reliable_address,
@@ -343,11 +305,33 @@ private:
const boost::asio::ip::address &_address);
void remove_remote_offer_type_by_ip(const boost::asio::ip::address &_address);
- std::vector<std::tuple<service_t, instance_t, eventgroup_t,
- std::shared_ptr<endpoint_definition>>>
- get_eventgroups_requiring_initial_events(
- const std::shared_ptr<message_impl>& _response) const;
+ std::shared_ptr<subscription> create_subscription(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, ttl_t _ttl,
+ const std::shared_ptr<endpoint> &_reliable,
+ const std::shared_ptr<endpoint> &_unreliable);
+ std::shared_ptr<remote_subscription> get_remote_subscription(
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup);
+
+ void send_subscription_ack(
+ const std::shared_ptr<remote_subscription_ack> &_acknowledgement);
+
+ std::shared_ptr<option_impl> create_ip_option(
+ const boost::asio::ip::address &_address, uint16_t _port,
+ bool _is_reliable) const;
+
+ void send_subscription(const std::shared_ptr<subscription> &_subscription,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup, const client_t _client);
+
+ void add_entry_data(std::vector<std::shared_ptr<message_impl>> &_messages,
+ const entry_data_t &_data);
+
+ void add_entry_data_to_remote_subscription_ack_msg(
+ const std::shared_ptr<remote_subscription_ack>& _acknowledgement,
+ const entry_data_t &_data);
private:
boost::asio::io_service &io_;
@@ -365,10 +349,12 @@ private:
requests_t requested_;
std::mutex requested_mutex_;
std::map<service_t,
- std::map<instance_t,
- std::map<eventgroup_t,
- std::map<client_t,
- std::shared_ptr<subscription> > > > > subscribed_;
+ std::map<instance_t,
+ std::map<eventgroup_t,
+ std::shared_ptr<subscription>
+ >
+ >
+ > subscribed_;
std::mutex subscribed_mutex_;
std::mutex serialize_mutex_;
@@ -434,10 +420,11 @@ private:
std::atomic<bool> is_diagnosis_;
std::mutex pending_remote_subscriptions_mutex_;
- std::map<service_t,
- std::map<instance_t,
- std::map<eventgroup_t,
- std::map<client_t, std::vector<std::shared_ptr<subscriber_t>>>>>> pending_remote_subscriptions_;
+ std::map<std::shared_ptr<remote_subscription>,
+ std::shared_ptr<remote_subscription_ack>
+ > pending_remote_subscriptions_;
+ std::mutex acknowledgement_mutex_;
+
std::mutex response_mutex_;
configuration::ttl_map_t ttl_factor_offers_;
@@ -447,18 +434,19 @@ private:
boost::asio::steady_timer last_msg_received_timer_;
std::chrono::milliseconds last_msg_received_timer_timeout_;
- std::mutex remote_offer_types_mutex_;
+ mutable std::mutex remote_offer_types_mutex_;
std::map<std::pair<service_t, instance_t>, remote_offer_type_e> remote_offer_types_;
std::map<boost::asio::ip::address, std::set<std::pair<service_t, instance_t>>> remote_offers_by_ip_;
reboot_notification_handler_t reboot_notification_handler_;
- offer_acceptance_handler_t offer_acceptance_handler_;
+ sd_acceptance_handler_t sd_acceptance_handler_;
std::mutex offer_mutex_;
std::mutex check_ttl_mutex_;
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_SERVICE_DISCOVERY_IMPL_
-#endif // VSOMEIP_SERVICE_DISCOVERY_IMPL
diff --git a/implementation/service_discovery/include/serviceentry_impl.hpp b/implementation/service_discovery/include/serviceentry_impl.hpp
index c8ad7d0..f7b2b92 100644
--- a/implementation/service_discovery/include/serviceentry_impl.hpp
+++ b/implementation/service_discovery/include/serviceentry_impl.hpp
@@ -1,32 +1,32 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SD_SERVICEENTRY_IMPL_HPP
-#define VSOMEIP_SD_SERVICEENTRY_IMPL_HPP
-
-#include "entry_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-class serviceentry_impl: public entry_impl {
-public:
- serviceentry_impl();
- virtual ~serviceentry_impl();
-
- minor_version_t get_minor_version() const;
- void set_minor_version(minor_version_t _version);
-
- bool serialize(vsomeip::serializer *_to) const;
- bool deserialize(vsomeip::deserializer *_from);
-
-private:
- minor_version_t minor_version_;
-};
-
-} // namespace sd
-} // namespace vsomeip
-
-#endif // VSOMEIP_SD_SERVICEENTRY_IMPL_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SD_SERVICEENTRY_IMPL_HPP
+#define VSOMEIP_V3_SD_SERVICEENTRY_IMPL_HPP
+
+#include "entry_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+class serviceentry_impl: public entry_impl {
+public:
+ serviceentry_impl();
+ virtual ~serviceentry_impl();
+
+ minor_version_t get_minor_version() const;
+ void set_minor_version(minor_version_t _version);
+
+ bool serialize(vsomeip_v3::serializer *_to) const;
+ bool deserialize(vsomeip_v3::deserializer *_from);
+
+private:
+ minor_version_t minor_version_;
+};
+
+} // namespace sd
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_SERVICEENTRY_IMPL_HPP
diff --git a/implementation/service_discovery/include/subscription.hpp b/implementation/service_discovery/include/subscription.hpp
index 3c3bfe8..f172348 100644
--- a/implementation/service_discovery/include/subscription.hpp
+++ b/implementation/service_discovery/include/subscription.hpp
@@ -1,39 +1,52 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_SD_SUBSCRIPTION_HPP
-#define VSOMEIP_SD_SUBSCRIPTION_HPP
+#ifndef VSOMEIP_V3_SD_SUBSCRIPTION_HPP_
+#define VSOMEIP_V3_SD_SUBSCRIPTION_HPP_
+#include <map>
#include <memory>
+#include <mutex>
+#include <set>
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/enumeration_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
namespace sd {
+enum class subscription_state_e : uint8_t {
+ ST_ACKNOWLEDGED = 0x00,
+ ST_NOT_ACKNOWLEDGED = 0x01,
+ ST_RESUBSCRIBING = 0x2,
+ ST_RESUBSCRIBING_NOT_ACKNOWLEDGED = 0x3,
+ ST_UNKNOWN = 0xFF
+};
+
class subscription {
public:
- subscription(major_version_t _major, ttl_t _ttl,
- std::shared_ptr<endpoint> _reliable,
- std::shared_ptr<endpoint> _unreliable,
- subscription_type_e _subscription_type,
- uint8_t _counter);
- ~subscription();
+ subscription() = default;
+ ~subscription() = default;
major_version_t get_major() const;
+ void set_major(major_version_t _major);
+
ttl_t get_ttl() const;
void set_ttl(ttl_t _ttl);
+
std::shared_ptr<endpoint> get_endpoint(bool _reliable) const;
- void set_endpoint(std::shared_ptr<endpoint> _endpoint, bool _reliable);
+ void set_endpoint(const std::shared_ptr<endpoint>& _endpoint, bool _reliable);
+
+ bool is_selective() const;
+ void set_selective(const bool _is_selective);
- bool is_acknowledged() const;
- void set_acknowledged(bool _is_acknowledged);
+ subscription_state_e get_state(const client_t _client) const;
+ void set_state(const client_t _client, subscription_state_e _state);
bool is_tcp_connection_established() const;
void set_tcp_connection_established(bool _is_established);
@@ -41,9 +54,11 @@ public:
bool is_udp_connection_established() const;
void set_udp_connection_established(bool _is_established);
- subscription_type_e get_subscription_type() const;
-
- uint8_t get_counter() const;
+ bool add_client(const client_t _client);
+ bool remove_client(const client_t _client);
+ std::set<client_t> get_clients() const;
+ bool has_client() const;
+ bool has_client(const client_t _client) const;
private:
major_version_t major_;
@@ -52,16 +67,17 @@ private:
std::shared_ptr<endpoint> reliable_;
std::shared_ptr<endpoint> unreliable_;
- bool is_acknowledged_;
+ bool is_selective_;
+
bool tcp_connection_established_;
bool udp_connection_established_;
- subscription_type_e subscription_type_;
-
- uint8_t counter_;
+ mutable std::mutex clients_mutex_;
+ std::map<client_t, subscription_state_e> clients_; // client-> is acknowledged?
};
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SD_SUBSCRIPTION_HPP_
-#endif // VSOMEIP_SD_SUBSCRIPTION_HPP
diff --git a/implementation/service_discovery/src/configuration_option_impl.cpp b/implementation/service_discovery/src/configuration_option_impl.cpp
index e09c7c9..7f050f2 100755
--- a/implementation/service_discovery/src/configuration_option_impl.cpp
+++ b/implementation/service_discovery/src/configuration_option_impl.cpp
@@ -1,126 +1,133 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <cstring>
-
-#include "../include/configuration_option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-configuration_option_impl::configuration_option_impl() {
- length_ = 2; // always contains "Reserved" and the trailing '\0'
- type_ = option_type_e::CONFIGURATION;
-}
-
-configuration_option_impl::~configuration_option_impl() {
-}
-
-bool configuration_option_impl::operator ==(
- const configuration_option_impl &_other) const {
- return (option_impl::operator ==(_other)
- && configuration_ == _other.configuration_);
-}
-
-void configuration_option_impl::add_item(const std::string &_key,
- const std::string &_value) {
- configuration_[_key] = _value;
- length_ = uint16_t(length_ + _key.length() + _value.length() + 2u); // +2 for the '=' and length
-}
-
-void configuration_option_impl::remove_item(const std::string &_key) {
- auto it = configuration_.find(_key);
- if (it != configuration_.end()) {
- length_ = uint16_t(length_ - (it->first.length() + it->second.length() + 2u));
- configuration_.erase(it);
- }
-}
-
-std::vector<std::string> configuration_option_impl::get_keys() const {
- std::vector < std::string > l_keys;
- for (auto elem : configuration_)
- l_keys.push_back(elem.first);
- return l_keys;
-}
-
-std::vector<std::string> configuration_option_impl::get_values() const {
- std::vector < std::string > l_values;
- for (auto elem : configuration_)
- l_values.push_back(elem.second);
- return l_values;
-}
-
-std::string configuration_option_impl::get_value(
- const std::string &_key) const {
- std::string l_value("");
- auto l_elem = configuration_.find(_key);
- if (l_elem != configuration_.end())
- l_value = l_elem->second;
- return l_value;
-}
-
-bool configuration_option_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful;
- std::string configuration_string;
-
- for (auto i = configuration_.begin(); i != configuration_.end(); ++i) {
- char l_length = char(1 + i->first.length() + i->second.length());
- configuration_string.push_back(l_length);
- configuration_string.append(i->first);
- configuration_string.push_back('=');
- configuration_string.append(i->second);
- }
- configuration_string.push_back('\0');
-
- is_successful = option_impl::serialize(_to);
- if (is_successful) {
- is_successful = _to->serialize(
- reinterpret_cast<const uint8_t*>(configuration_string.c_str()),
- uint32_t(configuration_string.length()));
- }
-
- return is_successful;
-}
-
-bool configuration_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from);
- uint8_t l_itemLength = 0;
- std::string l_item(256, 0), l_key, l_value;
-
- do {
- l_itemLength = 0;
- l_key.clear();
- l_value.clear();
- l_item.assign(256, '\0');
-
- is_successful = is_successful && _from->deserialize(l_itemLength);
- if (l_itemLength > 0) {
- is_successful = is_successful
- && _from->deserialize(l_item, static_cast<std::size_t>(l_itemLength));
-
- if (is_successful) {
- size_t l_eqPos = l_item.find('='); //SWS_SD_00292
- l_key = l_item.substr(0, l_eqPos);
-
- //if no "=" is found, no value is present for key (SWS_SD_00466)
- if( l_eqPos != std::string::npos )
- l_value = l_item.substr(l_eqPos + 1);
- if (configuration_.end() == configuration_.find(l_key)) {
- configuration_[l_key] = l_value;
- } else {
- // TODO: log reason for failing deserialization
- is_successful = false;
- }
- }
- }
- } while (is_successful && _from->get_remaining() > 0);
-
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstring>
+
+#include "../include/configuration_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+configuration_option_impl::configuration_option_impl() {
+ length_ = 2; // always contains "Reserved" and the trailing '\0'
+ type_ = option_type_e::CONFIGURATION;
+}
+
+configuration_option_impl::~configuration_option_impl() {
+}
+
+bool
+configuration_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(option_impl::operator ==(_other));
+
+ if (is_equal) {
+ const configuration_option_impl &its_other
+ = dynamic_cast<const configuration_option_impl &>(_other);
+ is_equal = (configuration_ == its_other.configuration_);
+ }
+
+ return is_equal;
+}
+
+void configuration_option_impl::add_item(const std::string &_key,
+ const std::string &_value) {
+ configuration_[_key] = _value;
+ length_ = uint16_t(length_ + _key.length() + _value.length() + 2u); // +2 for the '=' and length
+}
+
+void configuration_option_impl::remove_item(const std::string &_key) {
+ auto it = configuration_.find(_key);
+ if (it != configuration_.end()) {
+ length_ = uint16_t(length_ - (it->first.length() + it->second.length() + 2u));
+ configuration_.erase(it);
+ }
+}
+
+std::vector<std::string> configuration_option_impl::get_keys() const {
+ std::vector < std::string > l_keys;
+ for (const auto& elem : configuration_)
+ l_keys.push_back(elem.first);
+ return l_keys;
+}
+
+std::vector<std::string> configuration_option_impl::get_values() const {
+ std::vector < std::string > l_values;
+ for (const auto& elem : configuration_)
+ l_values.push_back(elem.second);
+ return l_values;
+}
+
+std::string configuration_option_impl::get_value(
+ const std::string &_key) const {
+ std::string l_value("");
+ auto l_elem = configuration_.find(_key);
+ if (l_elem != configuration_.end())
+ l_value = l_elem->second;
+ return l_value;
+}
+
+bool configuration_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful;
+ std::string configuration_string;
+
+ for (auto i = configuration_.begin(); i != configuration_.end(); ++i) {
+ char l_length = char(1 + i->first.length() + i->second.length());
+ configuration_string.push_back(l_length);
+ configuration_string.append(i->first);
+ configuration_string.push_back('=');
+ configuration_string.append(i->second);
+ }
+ configuration_string.push_back('\0');
+
+ is_successful = option_impl::serialize(_to);
+ if (is_successful) {
+ is_successful = _to->serialize(
+ reinterpret_cast<const uint8_t*>(configuration_string.c_str()),
+ uint32_t(configuration_string.length()));
+ }
+
+ return is_successful;
+}
+
+bool configuration_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from);
+ uint8_t l_itemLength = 0;
+ std::string l_item(256, 0), l_key, l_value;
+
+ do {
+ l_itemLength = 0;
+ l_key.clear();
+ l_value.clear();
+ l_item.assign(256, '\0');
+
+ is_successful = is_successful && _from->deserialize(l_itemLength);
+ if (l_itemLength > 0) {
+ is_successful = is_successful
+ && _from->deserialize(l_item, static_cast<std::size_t>(l_itemLength));
+
+ if (is_successful) {
+ size_t l_eqPos = l_item.find('='); //SWS_SD_00292
+ l_key = l_item.substr(0, l_eqPos);
+
+ //if no "=" is found, no value is present for key (SWS_SD_00466)
+ if( l_eqPos != std::string::npos )
+ l_value = l_item.substr(l_eqPos + 1);
+ if (configuration_.end() == configuration_.find(l_key)) {
+ configuration_[l_key] = l_value;
+ } else {
+ // TODO: log reason for failing deserialization
+ is_successful = false;
+ }
+ }
+ }
+ } while (is_successful && _from->get_remaining() > 0);
+
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/deserializer.cpp b/implementation/service_discovery/src/deserializer.cpp
index a8c0a46..88ce3be 100644
--- a/implementation/service_discovery/src/deserializer.cpp
+++ b/implementation/service_discovery/src/deserializer.cpp
@@ -1,41 +1,41 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/deserializer.hpp"
-#include "../include/message_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-deserializer::deserializer(std::uint32_t _shrink_buffer_threshold)
- : vsomeip::deserializer(_shrink_buffer_threshold) {
-}
-
-deserializer::deserializer(uint8_t *_data, std::size_t _length,
- std::uint32_t _shrink_buffer_threshold)
- : vsomeip::deserializer(_data, _length, _shrink_buffer_threshold) {
-}
-
-deserializer::deserializer(const deserializer &_other)
- : vsomeip::deserializer(_other) {
-}
-
-deserializer::~deserializer() {
-}
-
-message_impl * deserializer::deserialize_sd_message() {
- message_impl* deserialized_message = new message_impl;
- if (0 != deserialized_message) {
- if (false == deserialized_message->deserialize(this)) {
- delete deserialized_message;
- deserialized_message = 0;
- }
- }
-
- return deserialized_message;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/deserializer.hpp"
+#include "../include/message_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+deserializer::deserializer(std::uint32_t _shrink_buffer_threshold)
+ : vsomeip_v3::deserializer(_shrink_buffer_threshold) {
+}
+
+deserializer::deserializer(uint8_t *_data, std::size_t _length,
+ std::uint32_t _shrink_buffer_threshold)
+ : vsomeip_v3::deserializer(_data, _length, _shrink_buffer_threshold) {
+}
+
+deserializer::deserializer(const deserializer &_other)
+ : vsomeip_v3::deserializer(_other) {
+}
+
+deserializer::~deserializer() {
+}
+
+message_impl * deserializer::deserialize_sd_message() {
+ message_impl* deserialized_message = new message_impl;
+ if (0 != deserialized_message) {
+ if (false == deserialized_message->deserialize(this)) {
+ delete deserialized_message;
+ deserialized_message = 0;
+ }
+ }
+
+ return deserialized_message;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/entry_impl.cpp b/implementation/service_discovery/src/entry_impl.cpp
index ecab203..1fa1c89 100755
--- a/implementation/service_discovery/src/entry_impl.cpp
+++ b/implementation/service_discovery/src/entry_impl.cpp
@@ -1,189 +1,195 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <algorithm>
-
-#include "../include/entry_impl.hpp"
-#include "../include/message_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-#include "../../logging/include/logger.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-// TODO: throw exception if this constructor is used
-entry_impl::entry_impl() {
- type_ = entry_type_e::UNKNOWN;
- major_version_ = 0;
- service_ = 0x0;
- instance_ = 0x0;
- ttl_ = 0x0;
- num_options_[0] = 0;
- num_options_[1] = 0;
- index1_ = 0;
- index2_ = 0;
-}
-
-entry_impl::entry_impl(const entry_impl &_entry) {
- type_ = _entry.type_;
- major_version_ = _entry.major_version_;
- service_ = _entry.service_;
- instance_ = _entry.instance_;
- ttl_ = _entry.ttl_;
- num_options_[0] = _entry.num_options_[0];
- num_options_[1] = _entry.num_options_[1];
- index1_ = _entry.index1_;
- index2_ = _entry.index2_;
-}
-
-entry_impl::~entry_impl() {
-}
-
-entry_type_e entry_impl::get_type() const {
- return type_;
-}
-
-void entry_impl::set_type(entry_type_e _type) {
- type_ = _type;
-}
-
-service_t entry_impl::get_service() const {
- return service_;
-}
-
-void entry_impl::set_service(service_t _service) {
- service_ = _service;
-}
-
-instance_t entry_impl::get_instance() const {
- return instance_;
-}
-
-void entry_impl::set_instance(instance_t _instance) {
- instance_ = _instance;
-}
-
-major_version_t entry_impl::get_major_version() const {
- return major_version_;
-}
-
-void entry_impl::set_major_version(major_version_t _major_version) {
- major_version_ = _major_version;
-}
-
-ttl_t entry_impl::get_ttl() const {
- return ttl_;
-}
-
-void entry_impl::set_ttl(ttl_t _ttl) {
- ttl_ = _ttl;
-}
-
-const std::vector<uint8_t> & entry_impl::get_options(uint8_t _run) const {
- static std::vector<uint8_t> invalid_options;
- if (_run > 0 && _run <= VSOMEIP_MAX_OPTION_RUN)
- return options_[_run - 1];
-
- return invalid_options;
-}
-
-void entry_impl::assign_option(const std::shared_ptr<option_impl> &_option) {
- uint8_t option_index = uint8_t(get_owning_message()->get_option_index(_option));
- if (options_[0].empty() ||
- options_[0][0] == option_index + 1 ||
- options_[0][options_[0].size() - 1] + 1 == option_index) {
- options_[0].push_back(option_index);
- std::sort(options_[0].begin(), options_[0].end());
- num_options_[0]++;
- } else if (options_[1].empty() ||
- options_[1][0] == option_index + 1 ||
- options_[1][options_[1].size() - 1] + 1 == option_index) {
- options_[1].push_back(option_index);
- std::sort(options_[1].begin(), options_[1].end());
- num_options_[1]++;
- } else {
- VSOMEIP_WARNING << "Option is not referenced by entries array, maximum number of endpoint options reached!";
- }
-}
-
-bool entry_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = (0 != _to
- && _to->serialize(static_cast<uint8_t>(type_)));
-
- uint8_t index_first_option_run = 0;
- if (options_[0].size() > 0)
- index_first_option_run = options_[0][0];
- is_successful = is_successful && _to->serialize(index_first_option_run);
-
- uint8_t index_second_option_run = 0;
- if (options_[1].size() > 0)
- index_second_option_run = options_[1][0];
- is_successful = is_successful && _to->serialize(index_second_option_run);
-
- uint8_t number_of_options = uint8_t((((uint8_t) options_[0].size()) << 4)
- | (((uint8_t) options_[1].size()) & 0x0F));
- is_successful = is_successful && _to->serialize(number_of_options);
-
- is_successful = is_successful
- && _to->serialize(static_cast<uint16_t>(service_));
-
- is_successful = is_successful
- && _to->serialize(static_cast<uint16_t>(instance_));
-
- return is_successful;
-}
-
-bool entry_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = (0 != _from);
-
- uint8_t its_type(0);
- is_successful = is_successful && _from->deserialize(its_type);
- type_ = static_cast<entry_type_e>(its_type);
-
- is_successful = is_successful && _from->deserialize(index1_);
-
- is_successful = is_successful && _from->deserialize(index2_);
-
- uint8_t its_numbers(0);
- is_successful = is_successful && _from->deserialize(its_numbers);
-
- num_options_[0] = uint8_t(its_numbers >> 4);
- num_options_[1] = uint8_t(its_numbers & 0xF);
-
- for (uint16_t i = index1_; i < index1_ + num_options_[0]; ++i)
- options_[0].push_back((uint8_t)(i));
-
- for (uint16_t i = index2_; i < index2_ + num_options_[1]; ++i)
- options_[1].push_back((uint8_t)(i));
-
- uint16_t its_id(0);
- is_successful = is_successful && _from->deserialize(its_id);
- service_ = static_cast<service_t>(its_id);
-
- is_successful = is_successful && _from->deserialize(its_id);
- instance_ = static_cast<instance_t>(its_id);
-
- return is_successful;
-}
-
-bool entry_impl::is_service_entry() const {
- return (type_ <= entry_type_e::REQUEST_SERVICE);
-}
-
-bool entry_impl::is_eventgroup_entry() const {
- return (type_ >= entry_type_e::FIND_EVENT_GROUP
- && type_ <= entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
-}
-
-uint8_t entry_impl::get_num_options(uint8_t _run) const {
- if (_run < 1 || _run > VSOMEIP_MAX_OPTION_RUN) {
- return 0x0;
- }
- return num_options_[_run-1];
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <algorithm>
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/entry_impl.hpp"
+#include "../include/message_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+// TODO: throw exception if this constructor is used
+entry_impl::entry_impl() {
+ type_ = entry_type_e::UNKNOWN;
+ major_version_ = 0;
+ service_ = 0x0;
+ instance_ = 0x0;
+ ttl_ = 0x0;
+ num_options_[0] = 0;
+ num_options_[1] = 0;
+ index1_ = 0;
+ index2_ = 0;
+}
+
+entry_impl::entry_impl(const entry_impl &_entry) {
+ type_ = _entry.type_;
+ major_version_ = _entry.major_version_;
+ service_ = _entry.service_;
+ instance_ = _entry.instance_;
+ ttl_ = _entry.ttl_;
+ num_options_[0] = _entry.num_options_[0];
+ num_options_[1] = _entry.num_options_[1];
+ index1_ = _entry.index1_;
+ index2_ = _entry.index2_;
+}
+
+entry_impl::~entry_impl() {
+}
+
+entry_type_e entry_impl::get_type() const {
+ return type_;
+}
+
+void entry_impl::set_type(entry_type_e _type) {
+ type_ = _type;
+}
+
+service_t entry_impl::get_service() const {
+ return service_;
+}
+
+void entry_impl::set_service(service_t _service) {
+ service_ = _service;
+}
+
+instance_t entry_impl::get_instance() const {
+ return instance_;
+}
+
+void entry_impl::set_instance(instance_t _instance) {
+ instance_ = _instance;
+}
+
+major_version_t entry_impl::get_major_version() const {
+ return major_version_;
+}
+
+void entry_impl::set_major_version(major_version_t _major_version) {
+ major_version_ = _major_version;
+}
+
+ttl_t entry_impl::get_ttl() const {
+ return ttl_;
+}
+
+void entry_impl::set_ttl(ttl_t _ttl) {
+ ttl_ = _ttl;
+}
+
+const std::vector<uint8_t> & entry_impl::get_options(uint8_t _run) const {
+ static std::vector<uint8_t> invalid_options;
+ if (_run > 0 && _run <= VSOMEIP_MAX_OPTION_RUN)
+ return options_[_run - 1];
+
+ return invalid_options;
+}
+
+void entry_impl::assign_option(const std::shared_ptr<option_impl> &_option) {
+ int16_t i = get_owning_message()->get_option_index(_option);
+ if (i > -1 && i < 256) {
+ uint8_t its_index = static_cast<uint8_t>(i);
+ if (options_[0].empty() ||
+ options_[0][0] == its_index + 1 ||
+ options_[0][options_[0].size() - 1] + 1 == its_index) {
+ options_[0].push_back(its_index);
+ std::sort(options_[0].begin(), options_[0].end());
+ num_options_[0]++;
+ } else if (options_[1].empty() ||
+ options_[1][0] == its_index + 1 ||
+ options_[1][options_[1].size() - 1] + 1 == its_index) {
+ options_[1].push_back(its_index);
+ std::sort(options_[1].begin(), options_[1].end());
+ num_options_[1]++;
+ } else {
+ VSOMEIP_WARNING << "Option is not referenced by entries array, maximum number of endpoint options reached!";
+ }
+ } else {
+ VSOMEIP_ERROR << "Option could not be found.";
+ }
+}
+
+bool entry_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = (0 != _to
+ && _to->serialize(static_cast<uint8_t>(type_)));
+
+ uint8_t index_first_option_run = 0;
+ if (options_[0].size() > 0)
+ index_first_option_run = options_[0][0];
+ is_successful = is_successful && _to->serialize(index_first_option_run);
+
+ uint8_t index_second_option_run = 0;
+ if (options_[1].size() > 0)
+ index_second_option_run = options_[1][0];
+ is_successful = is_successful && _to->serialize(index_second_option_run);
+
+ uint8_t number_of_options = uint8_t((((uint8_t) options_[0].size()) << 4)
+ | (((uint8_t) options_[1].size()) & 0x0F));
+ is_successful = is_successful && _to->serialize(number_of_options);
+
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint16_t>(service_));
+
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint16_t>(instance_));
+
+ return is_successful;
+}
+
+bool entry_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = (0 != _from);
+
+ uint8_t its_type(0);
+ is_successful = is_successful && _from->deserialize(its_type);
+ type_ = static_cast<entry_type_e>(its_type);
+
+ is_successful = is_successful && _from->deserialize(index1_);
+
+ is_successful = is_successful && _from->deserialize(index2_);
+
+ uint8_t its_numbers(0);
+ is_successful = is_successful && _from->deserialize(its_numbers);
+
+ num_options_[0] = uint8_t(its_numbers >> 4);
+ num_options_[1] = uint8_t(its_numbers & 0xF);
+
+ for (uint16_t i = index1_; i < index1_ + num_options_[0]; ++i)
+ options_[0].push_back((uint8_t)(i));
+
+ for (uint16_t i = index2_; i < index2_ + num_options_[1]; ++i)
+ options_[1].push_back((uint8_t)(i));
+
+ uint16_t its_id(0);
+ is_successful = is_successful && _from->deserialize(its_id);
+ service_ = static_cast<service_t>(its_id);
+
+ is_successful = is_successful && _from->deserialize(its_id);
+ instance_ = static_cast<instance_t>(its_id);
+
+ return is_successful;
+}
+
+bool entry_impl::is_service_entry() const {
+ return (type_ <= entry_type_e::REQUEST_SERVICE);
+}
+
+bool entry_impl::is_eventgroup_entry() const {
+ return (type_ >= entry_type_e::FIND_EVENT_GROUP
+ && type_ <= entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
+}
+
+uint8_t entry_impl::get_num_options(uint8_t _run) const {
+ if (_run < 1 || _run > VSOMEIP_MAX_OPTION_RUN) {
+ return 0x0;
+ }
+ return num_options_[_run-1];
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/eventgroupentry_impl.cpp b/implementation/service_discovery/src/eventgroupentry_impl.cpp
index 17fd63b..bd5a491 100755
--- a/implementation/service_discovery/src/eventgroupentry_impl.cpp
+++ b/implementation/service_discovery/src/eventgroupentry_impl.cpp
@@ -1,247 +1,227 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/constants.hpp"
-#include "../include/eventgroupentry_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-#include "../include/ipv4_option_impl.hpp"
-#include "../include/ipv6_option_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-eventgroupentry_impl::eventgroupentry_impl() :
- reserved_(0) {
- eventgroup_ = 0xFFFF;
- counter_ = 0;
-}
-
-eventgroupentry_impl::eventgroupentry_impl(const eventgroupentry_impl &_entry)
- : entry_impl(_entry),
- reserved_(0) {
- eventgroup_ = _entry.eventgroup_;
- counter_ = _entry.counter_;
-}
-
-eventgroupentry_impl::~eventgroupentry_impl() {
-}
-
-eventgroup_t eventgroupentry_impl::get_eventgroup() const {
- return eventgroup_;
-}
-
-void eventgroupentry_impl::set_eventgroup(eventgroup_t _eventgroup) {
- eventgroup_ = _eventgroup;
-}
-
-uint16_t eventgroupentry_impl::get_reserved() const {
- return reserved_;
-}
-
-void eventgroupentry_impl::set_reserved(uint16_t _reserved) {
- reserved_ = _reserved;
-}
-
-uint8_t eventgroupentry_impl::get_counter() const {
- return counter_;
-}
-
-void eventgroupentry_impl::set_counter(uint8_t _counter) {
- counter_ = _counter;
-}
-
-bool eventgroupentry_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = entry_impl::serialize(_to);
-
- is_successful = is_successful && _to->serialize(major_version_);
-
- is_successful = is_successful
- && _to->serialize(static_cast<uint32_t>(ttl_), true);
-
- // 4Bit only for counter field
- if (counter_ >= 16) {
- is_successful = false;
- }
- uint16_t counter_and_reserved = protocol::reserved_word;
- if (!reserved_ ) {
- //reserved was not set -> just store counter as uint16
- counter_and_reserved = static_cast<uint16_t>(counter_);
- }
- else {
- //reserved contains values -> put reserved and counter into 16 bit variable
- counter_and_reserved = (uint16_t) (((uint16_t) reserved_ << 4) | counter_);
- }
-
- is_successful = is_successful
- && _to->serialize((uint8_t)(counter_and_reserved >> 8)); // serialize reserved part 1
- is_successful = is_successful
- && _to->serialize((uint8_t)counter_and_reserved); // serialize reserved part 2 and counter
- is_successful = is_successful
- && _to->serialize(static_cast<uint16_t>(eventgroup_));
-
- return is_successful;
-}
-
-bool eventgroupentry_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = entry_impl::deserialize(_from);
-
- uint8_t tmp_major_version(0);
- is_successful = is_successful && _from->deserialize(tmp_major_version);
- major_version_ = static_cast<major_version_t>(tmp_major_version);
-
- uint32_t its_ttl(0);
- is_successful = is_successful && _from->deserialize(its_ttl, true);
- ttl_ = static_cast<ttl_t>(its_ttl);
-
- uint8_t reserved1(0), reserved2(0);
- is_successful = is_successful && _from->deserialize(reserved1); // deserialize reserved part 1
- is_successful = is_successful && _from->deserialize(reserved2); // deserialize reserved part 2 and counter
-
- reserved_ = (uint16_t) (((uint16_t)reserved1 << 8) | reserved2); // combine reserved parts and counter
- reserved_ = (uint16_t) (reserved_ >> 4); //remove counter from reserved field
-
- //set 4 bits of reserved part 2 field to zero
- counter_ = (uint8_t) (reserved2 & (~(0xF0)));
-
- // 4Bit only for counter field
- if (counter_ >= 16) {
- is_successful = false;
- }
- uint16_t its_eventgroup = 0;
- is_successful = is_successful && _from->deserialize(its_eventgroup);
- eventgroup_ = static_cast<eventgroup_t>(its_eventgroup);
-
- return is_successful;
-}
-
-bool eventgroupentry_impl::is_matching_subscribe(
- const eventgroupentry_impl& _other,
- const message_impl::options_t& _options) const {
- if (ttl_ == 0
- && _other.ttl_ > 0
- && service_ == _other.service_
- && instance_ == _other.instance_
- && eventgroup_ == _other.eventgroup_
- && index1_ == _other.index1_
- && index2_ == _other.index2_
- && num_options_[0] == _other.num_options_[0]
- && num_options_[1] == _other.num_options_[1]
- && major_version_ == _other.major_version_
- && counter_ == _other.counter_) {
- return true;
- } else if (ttl_ == 0
- && _other.ttl_ > 0
- && service_ == _other.service_
- && instance_ == _other.instance_
- && eventgroup_ == _other.eventgroup_
- && major_version_ == _other.major_version_
- && counter_ == _other.counter_) {
- // check if entries reference options at different indexes but the
- // options itself are identical
- // check if number of options referenced is the same
- if (num_options_[0] + num_options_[1]
- != _other.num_options_[0] + _other.num_options_[1] ||
- num_options_[0] + num_options_[1] == 0) {
- return false;
- }
- // read out ip options of current and _other
- std::vector<std::shared_ptr<ip_option_impl>> its_options_current;
- std::vector<std::shared_ptr<ip_option_impl>> its_options_other;
- const std::size_t its_options_size = _options.size();
- for (const auto option_run : {0,1}) {
- for (const auto option_index : options_[option_run]) {
- if (its_options_size > option_index) {
- switch (_options[option_index]->get_type()) {
- case option_type_e::IP4_ENDPOINT:
- its_options_current.push_back(
- std::static_pointer_cast<ipv4_option_impl>(
- _options[option_index]));
- break;
- case option_type_e::IP6_ENDPOINT:
- its_options_current.push_back(
- std::static_pointer_cast<ipv6_option_impl>(
- _options[option_index]));
- break;
- default:
- break;
- }
- }
- }
- for (const auto option_index : _other.options_[option_run]) {
- if (its_options_size > option_index) {
- switch (_options[option_index]->get_type()) {
- case option_type_e::IP4_ENDPOINT:
- its_options_other.push_back(
- std::static_pointer_cast<ipv4_option_impl>(
- _options[option_index]));
- break;
- case option_type_e::IP6_ENDPOINT:
- its_options_other.push_back(
- std::static_pointer_cast<ipv6_option_impl>(
- _options[option_index]));
- break;
- default:
- break;
- }
- }
- }
- }
-
- if (!its_options_current.size() || !its_options_other.size()) {
- return false;
- }
-
- // search every option of current in other
- for (const auto& c : its_options_current) {
- bool found(false);
- for (const auto& o : its_options_other) {
- if (*c == *o) {
- switch (c->get_type()) {
- case option_type_e::IP4_ENDPOINT:
- if (static_cast<ipv4_option_impl*>(c.get())->get_address()
- == static_cast<ipv4_option_impl*>(o.get())->get_address()) {
- found = true;
- }
- break;
- case option_type_e::IP6_ENDPOINT:
- if (static_cast<ipv6_option_impl*>(c.get())->get_address()
- == static_cast<ipv6_option_impl*>(o.get())->get_address()) {
- found = true;
- }
- break;
- default:
- break;
- }
- }
- if (found) {
- break;
- }
- }
- if (!found) {
- return false;
- }
- }
- return true;
- }
- return false;
-}
-
-void eventgroupentry_impl::add_target(
- const std::shared_ptr<endpoint_definition> &_target) {
- if (_target->is_reliable()) {
- target_reliable_ = _target;
- } else {
- target_unreliable_ = _target;
- }
-}
-
-std::shared_ptr<endpoint_definition> eventgroupentry_impl::get_target(
- bool _reliable) const {
- return _reliable ? target_reliable_ : target_unreliable_;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/internal/logger.hpp>
+
+#include "../include/constants.hpp"
+#include "../include/eventgroupentry_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+#include "../include/ipv4_option_impl.hpp"
+#include "../include/ipv6_option_impl.hpp"
+#include "../include/selective_option_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+eventgroupentry_impl::eventgroupentry_impl() :
+ reserved_(0) {
+ eventgroup_ = 0xFFFF;
+ counter_ = 0;
+}
+
+eventgroupentry_impl::eventgroupentry_impl(const eventgroupentry_impl &_entry)
+ : entry_impl(_entry),
+ reserved_(0) {
+ eventgroup_ = _entry.eventgroup_;
+ counter_ = _entry.counter_;
+}
+
+eventgroupentry_impl::~eventgroupentry_impl() {
+}
+
+eventgroup_t eventgroupentry_impl::get_eventgroup() const {
+ return eventgroup_;
+}
+
+void eventgroupentry_impl::set_eventgroup(eventgroup_t _eventgroup) {
+ eventgroup_ = _eventgroup;
+}
+
+uint16_t eventgroupentry_impl::get_reserved() const {
+ return reserved_;
+}
+
+void eventgroupentry_impl::set_reserved(uint16_t _reserved) {
+ reserved_ = _reserved;
+}
+
+uint8_t eventgroupentry_impl::get_counter() const {
+ return counter_;
+}
+
+void eventgroupentry_impl::set_counter(uint8_t _counter) {
+ counter_ = _counter;
+}
+
+bool eventgroupentry_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = entry_impl::serialize(_to);
+ is_successful = is_successful && _to->serialize(major_version_);
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint32_t>(ttl_), true);
+ is_successful = is_successful
+ && _to->serialize(protocol::reserved_word);
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint16_t>(eventgroup_));
+
+ return is_successful;
+}
+
+bool eventgroupentry_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = entry_impl::deserialize(_from);
+
+ uint8_t tmp_major_version(0);
+ is_successful = is_successful && _from->deserialize(tmp_major_version);
+ major_version_ = static_cast<major_version_t>(tmp_major_version);
+
+ uint32_t its_ttl(0);
+ is_successful = is_successful && _from->deserialize(its_ttl, true);
+ ttl_ = static_cast<ttl_t>(its_ttl);
+
+ is_successful = is_successful && _from->deserialize(reserved_);
+
+ uint16_t its_eventgroup = 0;
+ is_successful = is_successful && _from->deserialize(its_eventgroup);
+ eventgroup_ = static_cast<eventgroup_t>(its_eventgroup);
+
+ return is_successful;
+}
+
+bool eventgroupentry_impl::matches(const eventgroupentry_impl& _other,
+ const message_impl::options_t& _options) const {
+ if (service_ == _other.service_
+ && instance_ == _other.instance_
+ && eventgroup_ == _other.eventgroup_
+ && major_version_ == _other.major_version_
+ && counter_ == _other.counter_) {
+
+ // Check, whether options are identical
+ if (index1_ == _other.index1_
+ && index2_ == _other.index2_
+ && num_options_[0] == _other.num_options_[0]
+ && num_options_[1] == _other.num_options_[1]) {
+ return true;
+ }
+
+ // check if entries reference options at different indexes but the
+ // options itself are identical
+ // check if number of options referenced is the same
+ if (num_options_[0] + num_options_[1]
+ != _other.num_options_[0] + _other.num_options_[1] ||
+ num_options_[0] + num_options_[1] == 0) {
+ return false;
+ }
+
+ // read out ip options of current and _other
+ std::vector<std::shared_ptr<ip_option_impl>> its_options_current;
+ std::vector<std::shared_ptr<ip_option_impl>> its_options_other;
+ const std::size_t its_options_size = _options.size();
+ for (const auto option_run : {0,1}) {
+ for (const auto option_index : options_[option_run]) {
+ if (its_options_size > option_index) {
+ switch (_options[option_index]->get_type()) {
+ case option_type_e::IP4_ENDPOINT:
+ its_options_current.push_back(
+ std::static_pointer_cast<ipv4_option_impl>(
+ _options[option_index]));
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ its_options_current.push_back(
+ std::static_pointer_cast<ipv6_option_impl>(
+ _options[option_index]));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ for (const auto option_index : _other.options_[option_run]) {
+ if (its_options_size > option_index) {
+ switch (_options[option_index]->get_type()) {
+ case option_type_e::IP4_ENDPOINT:
+ its_options_other.push_back(
+ std::static_pointer_cast<ipv4_option_impl>(
+ _options[option_index]));
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ its_options_other.push_back(
+ std::static_pointer_cast<ipv6_option_impl>(
+ _options[option_index]));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if (!its_options_current.size() || !its_options_other.size()) {
+ return false;
+ }
+
+ // search every option of current in other
+ for (const auto& c : its_options_current) {
+ bool found(false);
+ for (const auto& o : its_options_other) {
+ if (*c == *o) {
+ switch (c->get_type()) {
+ case option_type_e::IP4_ENDPOINT:
+ if (static_cast<ipv4_option_impl*>(c.get())->get_address()
+ == static_cast<ipv4_option_impl*>(o.get())->get_address()) {
+ found = true;
+ }
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ if (static_cast<ipv6_option_impl*>(c.get())->get_address()
+ == static_cast<ipv6_option_impl*>(o.get())->get_address()) {
+ found = true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void eventgroupentry_impl::add_target(
+ const std::shared_ptr<endpoint_definition> &_target) {
+ if (_target->is_reliable()) {
+ target_reliable_ = _target;
+ } else {
+ target_unreliable_ = _target;
+ }
+}
+
+std::shared_ptr<endpoint_definition> eventgroupentry_impl::get_target(
+ bool _reliable) const {
+ return _reliable ? target_reliable_ : target_unreliable_;
+}
+
+std::shared_ptr<selective_option_impl>
+eventgroupentry_impl::get_selective_option() const {
+ for (const auto i : {0, 1}) {
+ for (const auto j : options_[i]) {
+ auto its_option = std::dynamic_pointer_cast<
+ selective_option_impl>(owner_->get_option(j));
+ if (its_option)
+ return its_option;
+ }
+ }
+ return nullptr;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/ip_option_impl.cpp b/implementation/service_discovery/src/ip_option_impl.cpp
index 0684dc8..0f83511 100644
--- a/implementation/service_discovery/src/ip_option_impl.cpp
+++ b/implementation/service_discovery/src/ip_option_impl.cpp
@@ -4,27 +4,41 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <vsomeip/constants.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/constants.hpp"
#include "../include/ip_option_impl.hpp"
#include "../../message/include/deserializer.hpp"
#include "../../message/include/serializer.hpp"
-namespace vsomeip {
+
+namespace vsomeip_v3 {
namespace sd {
-ip_option_impl::ip_option_impl() :
- protocol_(layer_four_protocol_e::UNKNOWN),
- port_(0xFFFF) {
+ip_option_impl::ip_option_impl()
+ : protocol_(layer_four_protocol_e::UNKNOWN), port_(0) {
+}
+
+ip_option_impl::ip_option_impl(const uint16_t _port, const bool _is_reliable)
+ : protocol_(_is_reliable ?
+ layer_four_protocol_e::TCP : layer_four_protocol_e::UDP),
+ port_(_port) {
}
ip_option_impl::~ip_option_impl() {
}
-bool ip_option_impl::operator ==(const ip_option_impl &_other) const {
- return (option_impl::operator ==(_other)
- && protocol_ == _other.protocol_
- && port_ == _other.port_);
+bool
+ip_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(option_impl::operator ==(_other));
+
+ if (is_equal) {
+ const ip_option_impl &its_other
+ = dynamic_cast<const ip_option_impl &>(_other);
+ is_equal = (protocol_ == its_other.protocol_
+ && port_ == its_other.port_);
+ }
+ return is_equal;
}
unsigned short ip_option_impl::get_port() const {
@@ -45,5 +59,4 @@ void ip_option_impl::set_layer_four_protocol(
}
} // namespace sd
-} // namespace vsomeip
-
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/ipv4_option_impl.cpp b/implementation/service_discovery/src/ipv4_option_impl.cpp
index 22ee7d8..f3389e8 100644
--- a/implementation/service_discovery/src/ipv4_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv4_option_impl.cpp
@@ -1,75 +1,89 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <vsomeip/constants.hpp>
-
-#include "../include/constants.hpp"
-#include "../include/defines.hpp"
-#include "../include/ipv4_option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-ipv4_option_impl::ipv4_option_impl(bool _is_multicast) :
- address_({0}) {
- length_ = (1 + 4 + 1 + 1 + 2);
- type_ = (
- _is_multicast ?
- option_type_e::IP4_MULTICAST : option_type_e::IP4_ENDPOINT);
-}
-
-ipv4_option_impl::~ipv4_option_impl() {
-}
-
-bool ipv4_option_impl::operator ==(const ipv4_option_impl &_other) const {
- return (ip_option_impl::operator ==(_other)
- && address_ == _other.address_);
-}
-
-const ipv4_address_t & ipv4_option_impl::get_address() const {
- return address_;
-}
-
-void ipv4_option_impl::set_address(const ipv4_address_t &_address) {
- address_ = _address;
-}
-
-bool ipv4_option_impl::is_multicast() const {
- return (type_ == option_type_e::IP4_MULTICAST);
-}
-
-bool ipv4_option_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = option_impl::serialize(_to);
- _to->serialize(&address_[0], uint32_t(address_.size()));
- _to->serialize(protocol::reserved_byte);
- _to->serialize(static_cast<uint8_t>(protocol_));
- _to->serialize(port_);
- return is_successful;
-}
-
-bool ipv4_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from)
- && length_ == VSOMEIP_SD_IPV4_OPTION_LENGTH;
- uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
- _from->deserialize(address_.data(), 4);
- _from->deserialize(its_reserved);
- _from->deserialize(its_reserved);
- switch (static_cast<layer_four_protocol_e>(its_reserved)) {
- case layer_four_protocol_e::TCP:
- case layer_four_protocol_e::UDP:
- protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
- break;
- default:
- protocol_ = layer_four_protocol_e::UNKNOWN;
- }
- _from->deserialize(port_);
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
-
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <vsomeip/constants.hpp>
+
+#include "../include/constants.hpp"
+#include "../include/defines.hpp"
+#include "../include/ipv4_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+ipv4_option_impl::ipv4_option_impl()
+ : address_({0}) {
+ length_ = (1 + 4 + 1 + 1 + 2);
+}
+
+ipv4_option_impl::ipv4_option_impl(const boost::asio::ip::address &_address,
+ const uint16_t _port, const bool _is_reliable)
+ : ip_option_impl(_port, _is_reliable), address_(_address.to_v4().to_bytes()) {
+ type_ = (_address.is_multicast() ?
+ option_type_e::IP4_MULTICAST : option_type_e::IP4_ENDPOINT);
+ length_ = (1 + 4 + 1 + 1 + 2);
+}
+
+ipv4_option_impl::~ipv4_option_impl() {
+}
+
+bool
+ipv4_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(ip_option_impl::operator ==(_other));
+ if (is_equal) {
+ const ipv4_option_impl &its_other
+ = dynamic_cast<const ipv4_option_impl &>(_other);
+ is_equal = (address_ == its_other.address_);
+ }
+ return is_equal;
+}
+
+const ipv4_address_t & ipv4_option_impl::get_address() const {
+ return address_;
+}
+
+void ipv4_option_impl::set_address(const ipv4_address_t &_address) {
+ address_ = _address;
+
+ boost::asio::ip::address_v4 its_address(_address);
+ type_ = (its_address.is_multicast() ?
+ option_type_e::IP4_MULTICAST : option_type_e::IP4_ENDPOINT);
+}
+
+bool ipv4_option_impl::is_multicast() const {
+ return (type_ == option_type_e::IP4_MULTICAST);
+}
+
+bool ipv4_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = option_impl::serialize(_to);
+ _to->serialize(&address_[0], uint32_t(address_.size()));
+ _to->serialize(protocol::reserved_byte);
+ _to->serialize(static_cast<uint8_t>(protocol_));
+ _to->serialize(port_);
+ return is_successful;
+}
+
+bool ipv4_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from)
+ && length_ == VSOMEIP_SD_IPV4_OPTION_LENGTH;
+ uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
+ _from->deserialize(address_.data(), 4);
+ _from->deserialize(its_reserved);
+ _from->deserialize(its_reserved);
+ switch (static_cast<layer_four_protocol_e>(its_reserved)) {
+ case layer_four_protocol_e::TCP:
+ case layer_four_protocol_e::UDP:
+ protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
+ break;
+ default:
+ protocol_ = layer_four_protocol_e::UNKNOWN;
+ }
+ _from->deserialize(port_);
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/ipv6_option_impl.cpp b/implementation/service_discovery/src/ipv6_option_impl.cpp
index e4de3d6..1baba0f 100755
--- a/implementation/service_discovery/src/ipv6_option_impl.cpp
+++ b/implementation/service_discovery/src/ipv6_option_impl.cpp
@@ -1,75 +1,91 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <cstring>
-
-#include "../include/constants.hpp"
-#include "../include/defines.hpp"
-#include "../include/ipv6_option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-ipv6_option_impl::ipv6_option_impl(bool _is_multicast) :
- address_({0}) {
- length_ = (1 + 16 + 1 + 1 + 2);
- type_ = (
- _is_multicast ?
- option_type_e::IP6_MULTICAST : option_type_e::IP6_ENDPOINT);
-}
-
-ipv6_option_impl::~ipv6_option_impl() {
-}
-
-bool ipv6_option_impl::operator ==(const ipv6_option_impl &_other) const {
- return (ip_option_impl::operator ==(_other)
- && address_ == _other.address_);
-}
-
-const ipv6_address_t & ipv6_option_impl::get_address() const {
- return address_;
-}
-
-void ipv6_option_impl::set_address(const ipv6_address_t &_address) {
- address_ = _address;
-}
-
-bool ipv6_option_impl::is_multicast() const {
- return (type_ == option_type_e::IP6_MULTICAST);
-}
-
-bool ipv6_option_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = option_impl::serialize(_to);
- _to->serialize(&address_[0], uint32_t(address_.size()));
- _to->serialize(protocol::reserved_byte);
- _to->serialize(static_cast<uint8_t>(protocol_));
- _to->serialize(port_);
- return is_successful;
-}
-
-bool ipv6_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from)
- && length_ == VSOMEIP_SD_IPV6_OPTION_LENGTH;;
- uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
- _from->deserialize(address_.data(), 16);
- _from->deserialize(its_reserved);
- _from->deserialize(its_reserved);
- switch (static_cast<layer_four_protocol_e>(its_reserved)) {
- case layer_four_protocol_e::TCP:
- case layer_four_protocol_e::UDP:
- protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
- break;
- default:
- protocol_ = layer_four_protocol_e::UNKNOWN;
- }
- _from->deserialize(port_);
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
-
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstring>
+
+#include "../include/constants.hpp"
+#include "../include/defines.hpp"
+#include "../include/ipv6_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+ipv6_option_impl::ipv6_option_impl()
+ : address_({0}) {
+ length_ = (1 + 16 + 1 + 1 + 2);
+}
+
+ipv6_option_impl::ipv6_option_impl(const boost::asio::ip::address &_address,
+ const uint16_t _port, const bool _is_reliable)
+ : ip_option_impl(_port, _is_reliable), address_(_address.to_v6().to_bytes()) {
+ type_ = (_address.is_multicast() ?
+ option_type_e::IP6_MULTICAST : option_type_e::IP6_ENDPOINT);
+ length_ = (1 + 16 + 1 + 1 + 2);
+}
+
+ipv6_option_impl::~ipv6_option_impl() {
+}
+
+bool
+ipv6_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(ip_option_impl::operator ==(_other));
+
+ if (is_equal) {
+ const ipv6_option_impl &its_other
+ = dynamic_cast<const ipv6_option_impl &>(_other);
+ is_equal = (address_ == its_other.address_);
+ }
+
+ return is_equal;
+}
+
+const ipv6_address_t & ipv6_option_impl::get_address() const {
+ return address_;
+}
+
+void ipv6_option_impl::set_address(const ipv6_address_t &_address) {
+ address_ = _address;
+
+ boost::asio::ip::address_v6 its_address(_address);
+ type_ = (its_address.is_multicast() ?
+ option_type_e::IP6_MULTICAST : option_type_e::IP6_ENDPOINT);
+}
+
+bool ipv6_option_impl::is_multicast() const {
+ return (type_ == option_type_e::IP6_MULTICAST);
+}
+
+bool ipv6_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = option_impl::serialize(_to);
+ _to->serialize(&address_[0], uint32_t(address_.size()));
+ _to->serialize(protocol::reserved_byte);
+ _to->serialize(static_cast<uint8_t>(protocol_));
+ _to->serialize(port_);
+ return is_successful;
+}
+
+bool ipv6_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from)
+ && length_ == VSOMEIP_SD_IPV6_OPTION_LENGTH;;
+ uint8_t its_reserved(static_cast<std::uint8_t>(layer_four_protocol_e::UNKNOWN));
+ _from->deserialize(address_.data(), 16);
+ _from->deserialize(its_reserved);
+ _from->deserialize(its_reserved);
+ switch (static_cast<layer_four_protocol_e>(its_reserved)) {
+ case layer_four_protocol_e::TCP:
+ case layer_four_protocol_e::UDP:
+ protocol_ = static_cast<layer_four_protocol_e>(its_reserved);
+ break;
+ default:
+ protocol_ = layer_four_protocol_e::UNKNOWN;
+ }
+ _from->deserialize(port_);
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/load_balancing_option_impl.cpp b/implementation/service_discovery/src/load_balancing_option_impl.cpp
index 937dd4d..a26509e 100755
--- a/implementation/service_discovery/src/load_balancing_option_impl.cpp
+++ b/implementation/service_discovery/src/load_balancing_option_impl.cpp
@@ -1,70 +1,77 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/load_balancing_option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-load_balancing_option_impl::load_balancing_option_impl() {
- length_ = 1 + 2 + 2;
- type_ = option_type_e::LOAD_BALANCING;
- priority_ = 0;
- weight_ = 0;
-}
-
-load_balancing_option_impl::~load_balancing_option_impl() {
-}
-
-bool load_balancing_option_impl::operator ==(
- const load_balancing_option_impl &_other) const {
- return (option_impl::operator ==(_other)
- && priority_ == _other.priority_
- && priority_ == _other.weight_);
-}
-
-priority_t load_balancing_option_impl::get_priority() const {
- return priority_;
-}
-
-void load_balancing_option_impl::set_priority(priority_t _priority) {
- priority_ = _priority;
-}
-
-weight_t load_balancing_option_impl::get_weight() const {
- return weight_;
-}
-
-void load_balancing_option_impl::set_weight(weight_t _weight) {
- weight_ = _weight;
-}
-
-bool load_balancing_option_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = option_impl::serialize(_to);
- is_successful = is_successful
- && _to->serialize(static_cast<uint16_t>(priority_));
- is_successful = is_successful
- && _to->serialize(static_cast<uint16_t>(weight_));
- return is_successful;
-}
-
-bool load_balancing_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from);
-
- uint16_t tmp_priority = 0;
- is_successful = is_successful && _from->deserialize(tmp_priority);
- priority_ = static_cast<priority_t>(tmp_priority);
-
- uint16_t tmp_weight = 0;
- is_successful = is_successful && _from->deserialize(tmp_weight);
- weight_ = static_cast<weight_t>(tmp_weight);
-
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/load_balancing_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+load_balancing_option_impl::load_balancing_option_impl() {
+ length_ = 1 + 2 + 2;
+ type_ = option_type_e::LOAD_BALANCING;
+ priority_ = 0;
+ weight_ = 0;
+}
+
+load_balancing_option_impl::~load_balancing_option_impl() {
+}
+
+bool
+load_balancing_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(option_impl::operator ==(_other));
+
+ if (is_equal) {
+ const load_balancing_option_impl &its_other
+ = dynamic_cast<const load_balancing_option_impl &>(_other);
+ is_equal = (priority_ == its_other.priority_
+ && priority_ == its_other.weight_);
+ }
+
+ return is_equal;
+}
+
+priority_t load_balancing_option_impl::get_priority() const {
+ return priority_;
+}
+
+void load_balancing_option_impl::set_priority(priority_t _priority) {
+ priority_ = _priority;
+}
+
+weight_t load_balancing_option_impl::get_weight() const {
+ return weight_;
+}
+
+void load_balancing_option_impl::set_weight(weight_t _weight) {
+ weight_ = _weight;
+}
+
+bool load_balancing_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = option_impl::serialize(_to);
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint16_t>(priority_));
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint16_t>(weight_));
+ return is_successful;
+}
+
+bool load_balancing_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from);
+
+ uint16_t tmp_priority = 0;
+ is_successful = is_successful && _from->deserialize(tmp_priority);
+ priority_ = static_cast<priority_t>(tmp_priority);
+
+ uint16_t tmp_weight = 0;
+ is_successful = is_successful && _from->deserialize(tmp_weight);
+ weight_ = static_cast<weight_t>(tmp_weight);
+
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/message_element_impl.cpp b/implementation/service_discovery/src/message_element_impl.cpp
index fb89d85..281a0a7 100755
--- a/implementation/service_discovery/src/message_element_impl.cpp
+++ b/implementation/service_discovery/src/message_element_impl.cpp
@@ -1,24 +1,24 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/message_element_impl.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-message_element_impl::message_element_impl() {
- owner_ = 0;
-}
-
-message_impl * message_element_impl::get_owning_message() const {
- return owner_;
-}
-
-void message_element_impl::set_owning_message(message_impl *_owner) {
- owner_ = _owner;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/message_element_impl.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+message_element_impl::message_element_impl() {
+ owner_ = 0;
+}
+
+message_impl * message_element_impl::get_owning_message() const {
+ return owner_;
+}
+
+void message_element_impl::set_owning_message(message_impl *_owner) {
+ owner_ = _owner;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/message_impl.cpp b/implementation/service_discovery/src/message_impl.cpp
index e3b54ec..a203ce7 100755
--- a/implementation/service_discovery/src/message_impl.cpp
+++ b/implementation/service_discovery/src/message_impl.cpp
@@ -1,442 +1,431 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <typeinfo>
-
-#include <vsomeip/constants.hpp>
-#include <vsomeip/defines.hpp>
-
-#include "../include/constants.hpp"
-#include "../include/defines.hpp"
-#include "../include/eventgroupentry_impl.hpp"
-#include "../include/serviceentry_impl.hpp"
-#include "../include/configuration_option_impl.hpp"
-#include "../include/ipv4_option_impl.hpp"
-#include "../include/ipv6_option_impl.hpp"
-#include "../include/load_balancing_option_impl.hpp"
-#include "../include/protection_option_impl.hpp"
-#include "../include/message_impl.hpp"
-#include "../../logging/include/logger.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/payload_impl.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-message_impl::message_impl() :
- flags_(0x0),
- options_length_(0x0),
- number_required_acks_(0x0),
- number_contained_acks_(0x0),
- initial_events_required_(false) {
- header_.service_ = 0xFFFF;
- header_.method_ = 0x8100;
- header_.protocol_version_ = 0x01;
-}
-
-message_impl::~message_impl() {
-}
-
-length_t message_impl::get_length() const {
- length_t current_length = VSOMEIP_SOMEIP_SD_DATA_SIZE;
- if( entries_.size()) {
- current_length += VSOMEIP_SOMEIP_SD_ENTRY_LENGTH_SIZE;
- current_length += uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
- }
-
- current_length += VSOMEIP_SOMEIP_SD_OPTION_LENGTH_SIZE;
- if(options_.size()) {
- for (size_t i = 0; i < options_.size(); ++i) {
- current_length += (options_[i]->get_length()
- + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE);
- }
- }
- return current_length;
-}
-
-#define VSOMEIP_REBOOT_FLAG 0x80
-
-bool message_impl::get_reboot_flag() const {
- return ((flags_ & VSOMEIP_REBOOT_FLAG) != 0);
-}
-
-void message_impl::set_reboot_flag(bool _is_set) {
- if (_is_set)
- flags_ |= flags_t(VSOMEIP_REBOOT_FLAG);
- else
- flags_ &= flags_t(~VSOMEIP_REBOOT_FLAG);
-}
-
-#define VSOMEIP_UNICAST_FLAG 0x40
-
-bool message_impl::get_unicast_flag() const {
- return ((flags_ & VSOMEIP_UNICAST_FLAG) != 0);
-}
-
-void message_impl::set_unicast_flag(bool _is_set) {
- if (_is_set)
- flags_ |= flags_t(VSOMEIP_UNICAST_FLAG);
- else
- flags_ &= flags_t(~VSOMEIP_UNICAST_FLAG);
-}
-
-void message_impl::set_length(length_t _length) {
- (void)_length;
-}
-
-std::shared_ptr<eventgroupentry_impl> message_impl::create_eventgroup_entry() {
- std::shared_ptr < eventgroupentry_impl
- > its_entry(std::make_shared<eventgroupentry_impl>());
- //TODO: throw OutOfMemoryException if allocation fails
- its_entry->set_owning_message(this);
- entries_.push_back(its_entry);
- return its_entry;
-}
-
-std::shared_ptr<serviceentry_impl> message_impl::create_service_entry() {
- std::shared_ptr < serviceentry_impl
- > its_entry(std::make_shared<serviceentry_impl>());
- //TODO: throw OutOfMemoryException if allocation fails
- its_entry->set_owning_message(this);
- entries_.push_back(its_entry);
- return its_entry;
-}
-
-std::shared_ptr<configuration_option_impl> message_impl::create_configuration_option() {
- std::shared_ptr < configuration_option_impl
- > its_option(std::make_shared<configuration_option_impl>());
- //TODO: throw OutOfMemoryException if allocation fails
- its_option->set_owning_message(this);
- options_.push_back(its_option);
- return its_option;
-}
-
-std::shared_ptr<ipv4_option_impl> message_impl::create_ipv4_option(
- bool _is_multicast) {
- std::shared_ptr < ipv4_option_impl
- > its_option(std::make_shared < ipv4_option_impl > (_is_multicast));
- //TODO: throw OutOfMemoryException if allocation fails
- its_option->set_owning_message(this);
- options_.push_back(its_option);
- return its_option;
-}
-
-std::shared_ptr<ipv6_option_impl> message_impl::create_ipv6_option(
- bool _is_multicast) {
- std::shared_ptr < ipv6_option_impl
- > its_option(std::make_shared < ipv6_option_impl > (_is_multicast));
- //TODO: throw OutOfMemoryException if allocation fails
- its_option->set_owning_message(this);
- options_.push_back(its_option);
- return its_option;
-}
-
-std::shared_ptr<load_balancing_option_impl> message_impl::create_load_balancing_option() {
- std::shared_ptr < load_balancing_option_impl
- > its_option(std::make_shared<load_balancing_option_impl>());
- //TODO: throw OutOfMemoryException if allocation fails
- its_option->set_owning_message(this);
- options_.push_back(its_option);
- return its_option;
-}
-
-std::shared_ptr<protection_option_impl> message_impl::create_protection_option() {
- std::shared_ptr < protection_option_impl
- > its_option(std::make_shared<protection_option_impl>());
- //TODO: throw OutOfMemoryException if allocation fails
- its_option->set_owning_message(this);
- options_.push_back(its_option);
- return its_option;
-}
-
-const message_impl::entries_t & message_impl::get_entries() const {
- return entries_;
-}
-
-const message_impl::options_t & message_impl::get_options() const {
- return options_;
-}
-
-// TODO: throw exception to signal "OptionNotFound"
-int16_t message_impl::get_option_index(
- const std::shared_ptr<option_impl> &_option) const {
- int16_t i = 0;
-
- while (i < int16_t(options_.size())) {
- if (options_[i] == _option)
- return i;
- i++;
- }
-
- return -1;
-}
-
-uint32_t message_impl::get_options_length() {
- return options_length_;
-}
-
-std::shared_ptr<payload> message_impl::get_payload() const {
- return std::make_shared<payload_impl>();
-}
-
-void message_impl::set_payload(std::shared_ptr<payload> _payload) {
- (void)_payload;
-}
-
-bool message_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = header_.serialize(_to);
-
- is_successful = is_successful && _to->serialize(flags_);
- is_successful = is_successful
- && _to->serialize(protocol::reserved_long, true);
-
- uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
- is_successful = is_successful && _to->serialize(entries_length);
-
- for (const auto& its_entry : entries_)
- is_successful = is_successful && its_entry && its_entry->serialize(_to);
-
- uint32_t options_length = 0;
- for (const auto& its_option : options_)
- options_length += its_option ? its_option->get_length()
- + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE : 0;
- is_successful = is_successful && _to->serialize(options_length);
-
- for (const auto& its_option : options_)
- is_successful = is_successful && its_option && its_option->serialize(_to);
-
- return is_successful;
-}
-
-bool message_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful;
- bool option_is_successful(true);
-
- // header
- is_successful = header_.deserialize(_from);
-
- // flags
- is_successful = is_successful && _from->deserialize(flags_);
-
- // reserved
- uint32_t reserved;
- is_successful = is_successful && _from->deserialize(reserved, true);
-
- // entries
- uint32_t entries_length = 0;
- is_successful = is_successful && _from->deserialize(entries_length);
-
- // backup the current remaining length
- uint32_t save_remaining = uint32_t(_from->get_remaining());
- if (!is_successful) {
- // couldn't deserialize entries length
- return is_successful;
- } else if (entries_length > save_remaining) {
- // not enough data available to deserialize entries array
- is_successful = false;
- return is_successful;
- }
-
- // set remaining bytes to length of entries array
- _from->set_remaining(entries_length);
-
- // deserialize the entries
- while (is_successful && _from->get_remaining()) {
- std::shared_ptr < entry_impl > its_entry(deserialize_entry(_from));
- if (its_entry) {
- entries_.push_back(its_entry);
- if (its_entry->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP
- && its_entry->get_ttl() > 0) {
- const std::uint8_t num_options =
- static_cast<std::uint8_t>(
- its_entry->get_num_options(1) +
- its_entry->get_num_options(2));
- number_required_acks_ =
- static_cast<std::uint8_t>(number_required_acks_
- + num_options);
- }
- } else {
- is_successful = false;
- }
- }
-
- // set length to remaining bytes after entries array
- _from->set_remaining(save_remaining - entries_length);
-
- // Don't try to deserialize options if there aren't any
- if(_from->get_remaining() == 0) {
- return is_successful;
- }
-
- // deserialize the options
- is_successful = is_successful && _from->deserialize(options_length_);
-
- // check if there is unreferenced data behind the last option and discard it
- if(_from->get_remaining() > options_length_) {
- _from->set_remaining(options_length_);
- }
-
- while (option_is_successful && _from->get_remaining()) {
- std::shared_ptr < option_impl > its_option(deserialize_option(_from));
- if (its_option) {
- options_.push_back(its_option);
- } else {
- option_is_successful = false;
- }
- }
-
- return is_successful;
-}
-
-entry_impl * message_impl::deserialize_entry(vsomeip::deserializer *_from) {
- entry_impl *deserialized_entry = 0;
- uint8_t tmp_entry_type;
-
- if (_from->look_ahead(0, tmp_entry_type)) {
- entry_type_e deserialized_entry_type =
- static_cast<entry_type_e>(tmp_entry_type);
-
- switch (deserialized_entry_type) {
- case entry_type_e::FIND_SERVICE:
- case entry_type_e::OFFER_SERVICE:
- //case entry_type_e::STOP_OFFER_SERVICE:
- case entry_type_e::REQUEST_SERVICE:
- deserialized_entry = new serviceentry_impl;
- break;
-
- case entry_type_e::FIND_EVENT_GROUP:
- case entry_type_e::PUBLISH_EVENTGROUP:
- //case entry_type_e::STOP_PUBLISH_EVENTGROUP:
- case entry_type_e::SUBSCRIBE_EVENTGROUP:
- //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP:
- case entry_type_e::SUBSCRIBE_EVENTGROUP_ACK:
- //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK:
- deserialized_entry = new eventgroupentry_impl;
- break;
-
- default:
- break;
- };
-
- // deserialize object
- if (0 != deserialized_entry) {
- deserialized_entry->set_owning_message(this);
- if (!deserialized_entry->deserialize(_from)) {
- delete deserialized_entry;
- deserialized_entry = 0;
- };
- }
- }
-
- return deserialized_entry;
-}
-
-option_impl * message_impl::deserialize_option(vsomeip::deserializer *_from) {
- option_impl *deserialized_option = 0;
- uint8_t tmp_option_type;
-
- if (_from->look_ahead(2, tmp_option_type)) {
-
- option_type_e deserialized_option_type =
- static_cast<option_type_e>(tmp_option_type);
-
- switch (deserialized_option_type) {
-
- case option_type_e::CONFIGURATION:
- deserialized_option = new configuration_option_impl;
- break;
- case option_type_e::LOAD_BALANCING:
- deserialized_option = new load_balancing_option_impl;
- break;
- case option_type_e::PROTECTION:
- deserialized_option = new protection_option_impl;
- break;
- case option_type_e::IP4_ENDPOINT:
- deserialized_option = new ipv4_option_impl(false);
- break;
- case option_type_e::IP4_MULTICAST:
- deserialized_option = new ipv4_option_impl(true);
- break;
- case option_type_e::IP6_ENDPOINT:
- deserialized_option = new ipv6_option_impl(false);
- break;
- case option_type_e::IP6_MULTICAST:
- deserialized_option = new ipv6_option_impl(true);
- break;
-
- default:
- deserialized_option = new option_impl();
- break;
- };
-
- // deserialize object
- if (0 != deserialized_option
- && !deserialized_option->deserialize(_from)) {
- delete deserialized_option;
- deserialized_option = 0;
- };
- }
-
- return deserialized_option;
-}
-
-length_t message_impl::get_someip_length() const {
- return header_.length_;
-}
-
-std::uint8_t message_impl::get_number_required_acks() const {
- return number_required_acks_;
-}
-
-std::uint8_t message_impl::get_number_contained_acks() const {
- return number_contained_acks_;
-}
-
-void message_impl::set_number_required_acks(std::uint8_t _required_acks) {
- number_required_acks_ = _required_acks;
-}
-
-void message_impl::increase_number_required_acks(std::uint8_t _amount) {
- number_required_acks_ += _amount;
-}
-
-void message_impl::decrease_number_required_acks(std::uint8_t _amount) {
- number_required_acks_ -= _amount;
-}
-
-void message_impl::increase_number_contained_acks() {
- number_contained_acks_++;
-}
-
-bool message_impl::all_required_acks_contained() const {
- return number_contained_acks_ >= number_required_acks_;
-}
-
-std::unique_lock<std::mutex> message_impl::get_message_lock() {
- return std::unique_lock<std::mutex>(message_mutex_);
-}
-
-void message_impl::forced_initial_events_add(forced_initial_events_t _entry) {
- std::lock_guard<std::mutex> its_lock(forced_initial_events_mutex_);
- forced_initial_events_info_.push_back(_entry);
-}
-
-const std::vector<message_impl::forced_initial_events_t>
-message_impl::forced_initial_events_get() {
- std::lock_guard<std::mutex> its_lock(forced_initial_events_mutex_);
- return forced_initial_events_info_;
-}
-
-void message_impl::set_initial_events_required(bool _initial_events_required) {
- initial_events_required_ = _initial_events_required;
-}
-
-bool message_impl::initial_events_required() const {
- return initial_events_required_;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <typeinfo>
+
+#include <vsomeip/constants.hpp>
+#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+// internal[_android.hpp] must be included before defines.hpp
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
+
+#include "../include/constants.hpp"
+#include "../include/defines.hpp"
+#include "../include/eventgroupentry_impl.hpp"
+#include "../include/serviceentry_impl.hpp"
+#include "../include/configuration_option_impl.hpp"
+#include "../include/ipv4_option_impl.hpp"
+#include "../include/ipv6_option_impl.hpp"
+#include "../include/load_balancing_option_impl.hpp"
+#include "../include/protection_option_impl.hpp"
+#include "../include/selective_option_impl.hpp"
+#include "../include/message_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/payload_impl.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+message_impl::message_impl() :
+ flags_(0x0),
+ options_length_(0x0),
+ current_message_size_(VSOMEIP_SOMEIP_SD_EMPTY_MESSAGE_SIZE) {
+ header_.service_ = VSOMEIP_SD_SERVICE;
+ header_.instance_ = VSOMEIP_SD_INSTANCE;
+ header_.method_ = VSOMEIP_SD_METHOD;
+ header_.client_ = VSOMEIP_SD_CLIENT;
+ // session must be set dynamically
+ header_.protocol_version_ = protocol_version;
+ header_.interface_version_ = interface_version;
+ header_.type_ = message_type;
+ header_.code_ = return_code;
+
+ set_unicast_flag(true);
+}
+
+message_impl::~message_impl() {
+}
+
+length_t message_impl::get_length() const {
+ length_t current_length = VSOMEIP_SOMEIP_SD_DATA_SIZE;
+ if( entries_.size()) {
+ current_length += VSOMEIP_SOMEIP_SD_ENTRY_LENGTH_SIZE;
+ current_length += uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
+ }
+
+ current_length += VSOMEIP_SOMEIP_SD_OPTION_LENGTH_SIZE;
+ if(options_.size()) {
+ for (size_t i = 0; i < options_.size(); ++i) {
+ current_length += static_cast<length_t>(options_[i]->get_length()
+ + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE);
+ }
+ }
+ return current_length;
+}
+
+length_t message_impl::get_size() const {
+ return current_message_size_;
+}
+
+#define VSOMEIP_REBOOT_FLAG 0x80
+
+bool message_impl::get_reboot_flag() const {
+ return ((flags_ & VSOMEIP_REBOOT_FLAG) != 0);
+}
+
+void message_impl::set_reboot_flag(bool _is_set) {
+ if (_is_set)
+ flags_ |= flags_t(VSOMEIP_REBOOT_FLAG);
+ else
+ flags_ &= flags_t(~VSOMEIP_REBOOT_FLAG);
+}
+
+#define VSOMEIP_UNICAST_FLAG 0x40
+
+bool message_impl::get_unicast_flag() const {
+ return ((flags_ & VSOMEIP_UNICAST_FLAG) != 0);
+}
+
+void message_impl::set_unicast_flag(bool _is_set) {
+ if (_is_set)
+ flags_ |= flags_t(VSOMEIP_UNICAST_FLAG);
+ else
+ flags_ &= flags_t(~VSOMEIP_UNICAST_FLAG);
+}
+
+bool
+message_impl::add_entry_data(const std::shared_ptr<entry_impl> &_entry,
+ const std::vector<std::shared_ptr<option_impl> > &_options,
+ const std::shared_ptr<entry_impl> &_other) {
+ std::uint32_t its_entry_size = VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+ std::map<const std::shared_ptr<option_impl>, bool> its_options;
+
+ if (_other) {
+ its_entry_size += VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+ }
+
+ // TODO: Check whether it is possible to express the options
+ // by the two runs. If there are more than two options, it
+ // might be necessary to copy an option, which then increases
+ // the size...
+
+ for (const std::shared_ptr<option_impl> &its_option : _options) {
+ const auto its_existing_option = find_option(its_option);
+ if (!its_existing_option) {
+ its_entry_size += its_option->get_size();
+ its_options[its_option] = true;
+ } else {
+ its_options[its_existing_option] = false;
+ }
+ }
+
+ if (current_message_size_ + its_entry_size > VSOMEIP_MAX_UDP_SD_PAYLOAD)
+ return false;
+
+ entries_.push_back(_entry);
+ _entry->set_owning_message(this);
+ for (const auto &its_option : its_options) {
+ if (its_option.second) {
+ options_.push_back(its_option.first);
+ its_option.first->set_owning_message(this);
+ }
+ _entry->assign_option(its_option.first);
+ }
+
+ if (_other) {
+ entries_.push_back(_other);
+ _other->set_owning_message(this);
+ for (const auto &its_option : its_options) {
+ _other->assign_option(its_option.first);
+ }
+ }
+
+ current_message_size_ += its_entry_size;
+
+ return true;
+}
+
+bool
+message_impl::has_entry() const {
+ return (0 < entries_.size());
+}
+
+bool
+message_impl::has_option() const {
+ return (0 < options_.size());
+}
+
+void message_impl::set_length(length_t _length) {
+ (void)_length;
+}
+
+const message_impl::entries_t & message_impl::get_entries() const {
+ return entries_;
+}
+
+const message_impl::options_t & message_impl::get_options() const {
+ return options_;
+}
+
+std::shared_ptr<option_impl>
+message_impl::find_option(const std::shared_ptr<option_impl> &_option) const {
+ for (auto its_option : options_) {
+ if (its_option->equals(_option))
+ return its_option;
+ }
+ return nullptr;
+}
+
+int16_t message_impl::get_option_index(
+ const std::shared_ptr<option_impl> &_option) const {
+ int16_t i = 0;
+
+ while (i < int16_t(options_.size())) {
+ if (options_[static_cast<options_t::size_type>(i)] == _option)
+ return i;
+ i++;
+ }
+ return -1;
+}
+
+std::shared_ptr<option_impl>
+message_impl::get_option(int16_t _index) const {
+ if (_index > -1) {
+ size_t its_index = static_cast<size_t>(_index);
+ if (its_index < options_.size())
+ return options_[its_index];
+ }
+ return nullptr;
+}
+
+uint32_t message_impl::get_options_length() {
+ return options_length_;
+}
+
+std::shared_ptr<payload> message_impl::get_payload() const {
+ return std::make_shared<payload_impl>();
+}
+
+void message_impl::set_payload(std::shared_ptr<payload> _payload) {
+ (void)_payload;
+}
+
+uint8_t message_impl::get_check_result() const {
+ return 1;
+}
+void message_impl::set_check_result(uint8_t _check_result) {
+ (void)_check_result;
+}
+
+bool message_impl::is_valid_crc() const {
+ return false;
+}
+
+bool message_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = header_.serialize(_to);
+ is_successful = is_successful && _to->serialize(flags_);
+ is_successful = is_successful
+ && _to->serialize(protocol::reserved_long, true);
+
+ uint32_t entries_length = uint32_t(entries_.size() * VSOMEIP_SOMEIP_SD_ENTRY_SIZE);
+ is_successful = is_successful && _to->serialize(entries_length);
+
+ for (const auto& its_entry : entries_)
+ is_successful = is_successful && its_entry && its_entry->serialize(_to);
+
+ uint32_t options_length = 0;
+ for (const auto& its_option : options_)
+ options_length += its_option ? static_cast<uint32_t>(its_option->get_length()
+ + VSOMEIP_SOMEIP_SD_OPTION_HEADER_SIZE) : 0;
+ is_successful = is_successful && _to->serialize(options_length);
+
+ for (const auto& its_option : options_)
+ is_successful = is_successful && its_option && its_option->serialize(_to);
+
+ return is_successful;
+}
+
+bool message_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful;
+ bool option_is_successful(true);
+
+ // header
+ is_successful = header_.deserialize(_from);
+
+ // flags
+ is_successful = is_successful && _from->deserialize(flags_);
+
+ // reserved
+ uint32_t reserved;
+ is_successful = is_successful && _from->deserialize(reserved, true);
+
+ // entries
+ uint32_t entries_length = 0;
+ is_successful = is_successful && _from->deserialize(entries_length);
+
+ // backup the current remaining length
+ uint32_t save_remaining = uint32_t(_from->get_remaining());
+ if (!is_successful) {
+ // couldn't deserialize entries length
+ return is_successful;
+ } else if (entries_length > save_remaining) {
+ // not enough data available to deserialize entries array
+ is_successful = false;
+ return is_successful;
+ }
+
+ // set remaining bytes to length of entries array
+ _from->set_remaining(entries_length);
+
+ // deserialize the entries
+ while (is_successful && _from->get_remaining()) {
+ std::shared_ptr < entry_impl > its_entry(deserialize_entry(_from));
+ if (its_entry) {
+ entries_.push_back(its_entry);
+ } else {
+ is_successful = false;
+ }
+ }
+
+ // set length to remaining bytes after entries array
+ _from->set_remaining(save_remaining - entries_length);
+
+ // Don't try to deserialize options if there aren't any
+ if(_from->get_remaining() == 0) {
+ return is_successful;
+ }
+
+ // deserialize the options
+ is_successful = is_successful && _from->deserialize(options_length_);
+
+ // check if there is unreferenced data behind the last option and discard it
+ if(_from->get_remaining() > options_length_) {
+ _from->set_remaining(options_length_);
+ }
+
+ while (option_is_successful && _from->get_remaining()) {
+ std::shared_ptr < option_impl > its_option(deserialize_option(_from));
+ if (its_option) {
+ options_.push_back(its_option);
+ } else {
+ option_is_successful = false;
+ }
+ }
+ current_message_size_ = 0;
+ return is_successful;
+}
+
+entry_impl * message_impl::deserialize_entry(vsomeip_v3::deserializer *_from) {
+ entry_impl *deserialized_entry = 0;
+ uint8_t tmp_entry_type;
+
+ if (_from->look_ahead(0, tmp_entry_type)) {
+ entry_type_e deserialized_entry_type =
+ static_cast<entry_type_e>(tmp_entry_type);
+
+ switch (deserialized_entry_type) {
+ case entry_type_e::FIND_SERVICE:
+ case entry_type_e::OFFER_SERVICE:
+ //case entry_type_e::STOP_OFFER_SERVICE:
+ case entry_type_e::REQUEST_SERVICE:
+ deserialized_entry = new serviceentry_impl;
+ break;
+
+ case entry_type_e::FIND_EVENT_GROUP:
+ case entry_type_e::PUBLISH_EVENTGROUP:
+ //case entry_type_e::STOP_PUBLISH_EVENTGROUP:
+ case entry_type_e::SUBSCRIBE_EVENTGROUP:
+ //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP:
+ case entry_type_e::SUBSCRIBE_EVENTGROUP_ACK:
+ //case entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK:
+ deserialized_entry = new eventgroupentry_impl;
+ break;
+
+ default:
+ break;
+ };
+
+ // deserialize object
+ if (0 != deserialized_entry) {
+ deserialized_entry->set_owning_message(this);
+ if (!deserialized_entry->deserialize(_from)) {
+ delete deserialized_entry;
+ deserialized_entry = 0;
+ };
+ }
+ }
+
+ return deserialized_entry;
+}
+
+option_impl * message_impl::deserialize_option(vsomeip_v3::deserializer *_from) {
+ option_impl *deserialized_option = 0;
+ uint8_t tmp_option_type;
+
+ if (_from->look_ahead(2, tmp_option_type)) {
+
+ option_type_e deserialized_option_type =
+ static_cast<option_type_e>(tmp_option_type);
+
+ switch (deserialized_option_type) {
+
+ case option_type_e::CONFIGURATION:
+ deserialized_option = new configuration_option_impl;
+ break;
+ case option_type_e::LOAD_BALANCING:
+ deserialized_option = new load_balancing_option_impl;
+ break;
+ case option_type_e::PROTECTION:
+ deserialized_option = new protection_option_impl;
+ break;
+ case option_type_e::IP4_ENDPOINT:
+ case option_type_e::IP4_MULTICAST:
+ deserialized_option = new ipv4_option_impl;
+ break;
+ case option_type_e::IP6_ENDPOINT:
+ case option_type_e::IP6_MULTICAST:
+ deserialized_option = new ipv6_option_impl;
+ break;
+ case option_type_e::SELECTIVE:
+ deserialized_option = new selective_option_impl;
+ break;
+
+ default:
+ deserialized_option = new option_impl();
+ break;
+ };
+
+ // deserialize object
+ if (0 != deserialized_option
+ && !deserialized_option->deserialize(_from)) {
+ delete deserialized_option;
+ deserialized_option = 0;
+ };
+ }
+
+ return deserialized_option;
+}
+
+length_t message_impl::get_someip_length() const {
+ return header_.length_;
+}
+
+uid_t message_impl::get_uid() const {
+ return ANY_UID;
+}
+
+gid_t message_impl::get_gid() const {
+ return ANY_GID;
+}
+
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/option_impl.cpp b/implementation/service_discovery/src/option_impl.cpp
index 8191912..eb92c1a 100755
--- a/implementation/service_discovery/src/option_impl.cpp
+++ b/implementation/service_discovery/src/option_impl.cpp
@@ -1,68 +1,73 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/constants.hpp"
-#include "../include/option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-option_impl::option_impl() :
- length_(0),
- type_(option_type_e::UNKNOWN) {
-}
-
-option_impl::~option_impl() {
-}
-
-bool option_impl::operator ==(const option_impl &_other) const {
- return (type_ == _other.type_ && length_ == _other.length_);
-}
-
-uint16_t option_impl::get_length() const {
- return length_;
-}
-
-option_type_e option_impl::get_type() const {
- return type_;
-}
-
-bool option_impl::serialize(vsomeip::serializer *_to) const {
- return (0 != _to && _to->serialize(length_)
- && _to->serialize(static_cast<uint8_t>(type_))
- && _to->serialize(protocol::reserved_byte));
-}
-
-bool option_impl::deserialize(vsomeip::deserializer *_from) {
- uint8_t its_type, reserved;
- bool l_result = (0 != _from && _from->deserialize(length_)
- && _from->deserialize(its_type) && _from->deserialize(reserved));
-
- if (l_result) {
- switch(static_cast<option_type_e>(its_type)) {
- case option_type_e::CONFIGURATION:
- case option_type_e::LOAD_BALANCING:
- case option_type_e::PROTECTION:
- case option_type_e::IP4_ENDPOINT:
- case option_type_e::IP6_ENDPOINT:
- case option_type_e::IP4_MULTICAST:
- case option_type_e::IP6_MULTICAST:
- type_ = static_cast<option_type_e>(its_type);
- break;
- default:
- type_ = option_type_e::UNKNOWN;
- // No valid option type --> ignore the remaining parts of the message!
- _from->set_remaining(0);
- }
- }
-
- return l_result;
-}
-
-} // namespace sd
-} // namespace vsomeip
-
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/constants.hpp"
+#include "../include/option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+option_impl::option_impl() :
+ length_(0),
+ type_(option_type_e::UNKNOWN) {
+}
+
+option_impl::~option_impl() {
+}
+
+bool option_impl::operator ==(const option_impl &_other) const {
+ return (type_ == _other.type_ && length_ == _other.length_);
+}
+
+bool
+option_impl::equals(const std::shared_ptr<option_impl> &_other) const {
+ return (this->operator ==(*(_other.get())));
+}
+
+uint16_t option_impl::get_length() const {
+ return length_;
+}
+
+option_type_e option_impl::get_type() const {
+ return type_;
+}
+
+bool option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ return (0 != _to && _to->serialize(length_)
+ && _to->serialize(static_cast<uint8_t>(type_))
+ && _to->serialize(protocol::reserved_byte));
+}
+
+bool option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ uint8_t its_type, reserved;
+ bool l_result = (0 != _from && _from->deserialize(length_)
+ && _from->deserialize(its_type) && _from->deserialize(reserved));
+
+ if (l_result) {
+ switch(static_cast<option_type_e>(its_type)) {
+ case option_type_e::CONFIGURATION:
+ case option_type_e::LOAD_BALANCING:
+ case option_type_e::PROTECTION:
+ case option_type_e::IP4_ENDPOINT:
+ case option_type_e::IP6_ENDPOINT:
+ case option_type_e::IP4_MULTICAST:
+ case option_type_e::IP6_MULTICAST:
+ case option_type_e::SELECTIVE:
+ type_ = static_cast<option_type_e>(its_type);
+ break;
+ default:
+ type_ = option_type_e::UNKNOWN;
+ // No valid option type --> ignore the remaining parts of the message!
+ _from->set_remaining(0);
+ }
+ }
+
+ return l_result;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/protection_option_impl.cpp b/implementation/service_discovery/src/protection_option_impl.cpp
index f847650..801ca88 100755
--- a/implementation/service_discovery/src/protection_option_impl.cpp
+++ b/implementation/service_discovery/src/protection_option_impl.cpp
@@ -1,70 +1,77 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/protection_option_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-protection_option_impl::protection_option_impl() {
- length_ = 1 + 4 + 4;
- type_ = option_type_e::PROTECTION;
- counter_ = 0;
- crc_ = 0;
-}
-
-protection_option_impl::~protection_option_impl() {
-}
-
-bool protection_option_impl::operator ==(
- const protection_option_impl &_other) const {
- return (option_impl::operator ==(_other)
- && counter_ == _other.counter_
- && crc_ == _other.crc_);
-}
-
-alive_counter_t protection_option_impl::get_alive_counter() const {
- return counter_;
-}
-
-void protection_option_impl::set_alive_counter(alive_counter_t _counter) {
- counter_ = _counter;
-}
-
-crc_t protection_option_impl::get_crc() const {
- return crc_;
-}
-
-void protection_option_impl::set_crc(crc_t _crc) {
- crc_ = _crc;
-}
-
-bool protection_option_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = option_impl::serialize(_to);
- is_successful = is_successful
- && _to->serialize(static_cast<uint32_t>(counter_));
- is_successful = is_successful
- && _to->serialize(static_cast<uint32_t>(crc_));
- return is_successful;
-}
-
-bool protection_option_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = option_impl::deserialize(_from);
-
- uint32_t its_alive_counter = 0;
- is_successful = is_successful && _from->deserialize(its_alive_counter);
- counter_ = static_cast<alive_counter_t>(its_alive_counter);
-
- uint32_t its_crc = 0;
- is_successful = is_successful && _from->deserialize(its_crc);
- crc_ = static_cast<crc_t>(its_crc);
-
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/protection_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+protection_option_impl::protection_option_impl() {
+ length_ = 1 + 4 + 4;
+ type_ = option_type_e::PROTECTION;
+ counter_ = 0;
+ crc_ = 0;
+}
+
+protection_option_impl::~protection_option_impl() {
+}
+
+bool
+protection_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(option_impl::operator ==(_other));
+
+ if (is_equal) {
+ const protection_option_impl &its_other
+ = dynamic_cast<const protection_option_impl &>(_other);
+ is_equal = (counter_ == its_other.counter_
+ && crc_ == its_other.crc_);
+ }
+
+ return is_equal;
+}
+
+alive_counter_t protection_option_impl::get_alive_counter() const {
+ return counter_;
+}
+
+void protection_option_impl::set_alive_counter(alive_counter_t _counter) {
+ counter_ = _counter;
+}
+
+crc_t protection_option_impl::get_crc() const {
+ return crc_;
+}
+
+void protection_option_impl::set_crc(crc_t _crc) {
+ crc_ = _crc;
+}
+
+bool protection_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = option_impl::serialize(_to);
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint32_t>(counter_));
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint32_t>(crc_));
+ return is_successful;
+}
+
+bool protection_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from);
+
+ uint32_t its_alive_counter = 0;
+ is_successful = is_successful && _from->deserialize(its_alive_counter);
+ counter_ = static_cast<alive_counter_t>(its_alive_counter);
+
+ uint32_t its_crc = 0;
+ is_successful = is_successful && _from->deserialize(its_crc);
+ crc_ = static_cast<crc_t>(its_crc);
+
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/remote_subscription_ack.cpp b/implementation/service_discovery/src/remote_subscription_ack.cpp
new file mode 100644
index 0000000..80be082
--- /dev/null
+++ b/implementation/service_discovery/src/remote_subscription_ack.cpp
@@ -0,0 +1,92 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/message_impl.hpp"
+#include "../include/remote_subscription_ack.hpp"
+#include "../../routing/include/remote_subscription.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+remote_subscription_ack::remote_subscription_ack(const boost::asio::ip::address &_address)
+ : is_complete_(false),
+ is_done_(false),
+ target_address_(_address) {
+ messages_.push_back(std::make_shared<message_impl>());
+}
+
+bool
+remote_subscription_ack::is_complete() const {
+ return is_complete_;
+}
+
+void
+remote_subscription_ack::complete() {
+ is_complete_ = true;
+}
+
+bool
+remote_subscription_ack::is_done() const {
+ return is_done_;
+}
+
+void
+remote_subscription_ack::done() {
+ is_done_ = true;
+}
+
+std::vector<std::shared_ptr<message_impl> >
+remote_subscription_ack::get_messages() const {
+ return messages_;
+}
+
+std::shared_ptr<message_impl> remote_subscription_ack::get_current_message() const {
+ return messages_.back();
+}
+
+std::shared_ptr<message_impl> remote_subscription_ack::add_message() {
+ messages_.emplace_back(std::make_shared<message_impl>());
+ return messages_.back();
+}
+
+boost::asio::ip::address
+remote_subscription_ack::get_target_address() const {
+ return target_address_;
+}
+
+bool
+remote_subscription_ack::is_pending() const {
+ for (const auto& its_subscription : subscriptions_) {
+ if (its_subscription->is_pending()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+std::set<std::shared_ptr<remote_subscription> >
+remote_subscription_ack::get_subscriptions() const {
+ return subscriptions_;
+}
+
+void
+remote_subscription_ack::add_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription) {
+ subscriptions_.insert(_subscription);
+}
+
+bool
+remote_subscription_ack::has_subscription() const {
+ return (0 < subscriptions_.size());
+}
+
+std::unique_lock<std::recursive_mutex> remote_subscription_ack::get_lock() {
+ return std::unique_lock<std::recursive_mutex>(mutex_);
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/request.cpp b/implementation/service_discovery/src/request.cpp
index c726c3e..819b1a5 100644
--- a/implementation/service_discovery/src/request.cpp
+++ b/implementation/service_discovery/src/request.cpp
@@ -5,7 +5,7 @@
#include "../include/request.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
request::request(major_version_t _major, minor_version_t _minor, ttl_t _ttl)
@@ -45,4 +45,4 @@ void request::set_sent_counter(uint8_t _sent_counter) {
}
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/runtime_impl.cpp b/implementation/service_discovery/src/runtime_impl.cpp
index d72d034..75ce986 100644
--- a/implementation/service_discovery/src/runtime_impl.cpp
+++ b/implementation/service_discovery/src/runtime_impl.cpp
@@ -12,9 +12,9 @@
#include "../include/runtime_impl.hpp"
#include "../include/service_discovery_impl.hpp"
-VSOMEIP_PLUGIN(vsomeip::sd::runtime_impl)
+VSOMEIP_PLUGIN(vsomeip_v3::sd::runtime_impl)
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
runtime_impl::runtime_impl()
@@ -24,28 +24,11 @@ runtime_impl::runtime_impl()
runtime_impl::~runtime_impl() {
}
-std::shared_ptr<service_discovery> runtime_impl::create_service_discovery(
- service_discovery_host *_host,
+std::shared_ptr<service_discovery>
+runtime_impl::create_service_discovery(service_discovery_host *_host,
std::shared_ptr<configuration> _configuration) const {
- return std::make_shared < service_discovery_impl > (_host, _configuration);
-}
-
-std::shared_ptr<message_impl> runtime_impl::create_message() const {
- std::shared_ptr < message_impl > its_message =
- std::make_shared<message_impl>();
- its_message->set_service(VSOMEIP_SD_SERVICE);
- its_message->set_instance(VSOMEIP_SD_INSTANCE);
- its_message->set_method(VSOMEIP_SD_METHOD);
- its_message->set_client(VSOMEIP_SD_CLIENT);
- // session must be set dynamically
- its_message->set_protocol_version(protocol_version);
- its_message->set_interface_version(interface_version);
- its_message->set_message_type(message_type);
- its_message->set_return_code(return_code);
- // reboot flag must be set dynamically
- its_message->set_unicast_flag(true);
- return its_message;
+ return std::make_shared<service_discovery_impl>(_host, _configuration);
}
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/selective_option_impl.cpp b/implementation/service_discovery/src/selective_option_impl.cpp
new file mode 100755
index 0000000..c61be22
--- /dev/null
+++ b/implementation/service_discovery/src/selective_option_impl.cpp
@@ -0,0 +1,86 @@
+// Copyright (C) 2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstring>
+
+#include "../include/selective_option_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+selective_option_impl::selective_option_impl() {
+ length_ = 1; // always contains "Reserved"
+ type_ = option_type_e::SELECTIVE;
+}
+
+selective_option_impl::~selective_option_impl() {
+}
+
+bool
+selective_option_impl::operator ==(const option_impl &_other) const {
+ bool is_equal(option_impl::operator ==(_other));
+ if (is_equal) {
+ const selective_option_impl &its_other
+ = dynamic_cast<const selective_option_impl &>(_other);
+ is_equal = (clients_ == its_other.clients_);
+ }
+ return is_equal;
+}
+
+std::set<client_t> selective_option_impl::get_clients() const {
+ std::set<client_t> its_clients(clients_);
+ return (its_clients);
+}
+
+bool selective_option_impl::add_client(client_t _client) {
+ auto its_result = clients_.insert(_client);
+ length_ = uint16_t(1 + clients_.size() * sizeof(client_t));
+ return (its_result.second);
+}
+
+bool selective_option_impl::remove_client(client_t _client) {
+ auto its_size = clients_.size();
+ clients_.erase(_client);
+ length_ = uint16_t(1 + clients_.size() * sizeof(client_t));
+ return (clients_.size() < its_size);
+}
+
+bool selective_option_impl::has_clients() const {
+ return (!clients_.empty());
+}
+
+bool selective_option_impl::has_client(client_t _client) {
+ auto find_client = clients_.find(_client);
+ return (find_client != clients_.end());
+}
+
+bool selective_option_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = option_impl::serialize(_to);
+ if (is_successful) {
+ for (auto &its_client : clients_)
+ _to->serialize(its_client);
+ }
+ return is_successful;
+}
+
+bool selective_option_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = option_impl::deserialize(_from);
+ if (is_successful) {
+ uint16_t i = 1;
+ while (i < length_) {
+ client_t its_client;
+ is_successful = _from->deserialize(its_client);
+
+ clients_.insert(its_client);
+ i = uint16_t(i + sizeof(client_t));
+ }
+ }
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/service_discovery_impl.cpp b/implementation/service_discovery/src/service_discovery_impl.cpp
index de5f190..e5c4a32 100644
--- a/implementation/service_discovery/src/service_discovery_impl.cpp
+++ b/implementation/service_discovery/src/service_discovery_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -7,6 +7,9 @@
#include <random>
#include <forward_list>
+#include <thread>
+
+#include <vsomeip/internal/logger.hpp>
#include "../include/constants.hpp"
#include "../include/defines.hpp"
@@ -15,7 +18,9 @@
#include "../include/eventgroupentry_impl.hpp"
#include "../include/ipv4_option_impl.hpp"
#include "../include/ipv6_option_impl.hpp"
+#include "../include/selective_option_impl.hpp"
#include "../include/message_impl.hpp"
+#include "../include/remote_subscription_ack.hpp"
#include "../include/request.hpp"
#include "../include/runtime.hpp"
#include "../include/service_discovery_host.hpp"
@@ -23,51 +28,50 @@
#include "../include/serviceentry_impl.hpp"
#include "../include/subscription.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
#include "../../endpoints/include/endpoint.hpp"
#include "../../endpoints/include/client_endpoint.hpp"
#include "../../endpoints/include/endpoint_definition.hpp"
#include "../../endpoints/include/tcp_server_endpoint_impl.hpp"
#include "../../endpoints/include/udp_server_endpoint_impl.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../message/include/serializer.hpp"
+#include "../../plugin/include/plugin_manager_impl.hpp"
#include "../../routing/include/eventgroupinfo.hpp"
#include "../../routing/include/serviceinfo.hpp"
-#include "../../plugin/include/plugin_manager.hpp"
#include "../../utility/include/byteorder.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace sd {
-service_discovery_impl::service_discovery_impl(service_discovery_host *_host,
- std::shared_ptr<configuration> _configuration)
- : io_(_host->get_io()),
- host_(_host),
- configuration_(_configuration),
- port_(VSOMEIP_SD_DEFAULT_PORT),
- reliable_(false),
- serializer_(std::make_shared<serializer>(
- configuration_->get_buffer_shrink_threshold())),
- deserializer_(std::make_shared<deserializer>(
- configuration_->get_buffer_shrink_threshold())),
- ttl_timer_(_host->get_io()),
- ttl_timer_runtime_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY / 2),
- ttl_(VSOMEIP_SD_DEFAULT_TTL),
- subscription_expiration_timer_(_host->get_io()),
- max_message_size_(VSOMEIP_MAX_UDP_SD_PAYLOAD),
- initial_delay_(0),
- offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME),
- repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
- repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
- cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
- offer_debounce_timer_(_host->get_io()),
- find_debounce_time_(VSOMEIP_SD_DEFAULT_FIND_DEBOUNCE_TIME),
- find_debounce_timer_(_host->get_io()),
- main_phase_timer_(_host->get_io()),
- is_suspended_(false),
- is_diagnosis_(false),
- last_msg_received_timer_(_host->get_io()),
- last_msg_received_timer_timeout_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY +
+service_discovery_impl::service_discovery_impl(
+ service_discovery_host *_host,
+ const std::shared_ptr<configuration>& _configuration)
+ : io_(_host->get_io()),
+ host_(_host),
+ configuration_(_configuration),
+ port_(VSOMEIP_SD_DEFAULT_PORT),
+ reliable_(false),
+ serializer_(std::make_shared<serializer>(
+ configuration_->get_buffer_shrink_threshold())),
+ deserializer_(std::make_shared<deserializer>(
+ configuration_->get_buffer_shrink_threshold())),
+ ttl_timer_(_host->get_io()),
+ ttl_timer_runtime_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY / 2),
+ ttl_(VSOMEIP_SD_DEFAULT_TTL),
+ subscription_expiration_timer_(_host->get_io()),
+ max_message_size_(VSOMEIP_MAX_UDP_SD_PAYLOAD),
+ initial_delay_(0),
+ offer_debounce_time_(VSOMEIP_SD_DEFAULT_OFFER_DEBOUNCE_TIME),
+ repetitions_base_delay_(VSOMEIP_SD_DEFAULT_REPETITIONS_BASE_DELAY),
+ repetitions_max_(VSOMEIP_SD_DEFAULT_REPETITIONS_MAX),
+ cyclic_offer_delay_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY),
+ offer_debounce_timer_(_host->get_io()),
+ find_debounce_time_(VSOMEIP_SD_DEFAULT_FIND_DEBOUNCE_TIME),
+ find_debounce_timer_(_host->get_io()),
+ main_phase_timer_(_host->get_io()),
+ is_suspended_(false),
+ is_diagnosis_(false),
+ last_msg_received_timer_(_host->get_io()),
+ last_msg_received_timer_timeout_(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY +
(VSOMEIP_SD_DEFAULT_CYCLIC_OFFER_DELAY / 10)) {
// TODO: cleanup start condition!
next_subscription_expiration_ = std::chrono::steady_clock::now() + std::chrono::hours(24);
@@ -76,12 +80,16 @@ service_discovery_impl::service_discovery_impl(service_discovery_host *_host,
service_discovery_impl::~service_discovery_impl() {
}
-boost::asio::io_service & service_discovery_impl::get_io() {
+boost::asio::io_service &
+service_discovery_impl::get_io() {
return io_;
}
-void service_discovery_impl::init() {
- runtime_ = std::dynamic_pointer_cast<sd::runtime>(plugin_manager::get()->get_plugin(plugin_type_e::SD_RUNTIME_PLUGIN, VSOMEIP_SD_LIBRARY));
+void
+service_discovery_impl::init() {
+ runtime_ = std::dynamic_pointer_cast<sd::runtime>(
+ plugin_manager::get()->get_plugin(
+ plugin_type_e::SD_RUNTIME_PLUGIN, VSOMEIP_SD_LIBRARY));
unicast_ = configuration_->get_unicast_address();
sd_multicast_ = configuration_->get_sd_multicast();
@@ -96,16 +104,10 @@ void service_discovery_impl::init() {
ttl_ = configuration_->get_sd_ttl();
// generate random initial delay based on initial delay min and max
- std::int32_t initial_delay_min =
+ std::uint32_t initial_delay_min =
configuration_->get_sd_initial_delay_min();
- if (initial_delay_min < 0) {
- initial_delay_min = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MIN;
- }
- std::int32_t initial_delay_max =
+ std::uint32_t initial_delay_max =
configuration_->get_sd_initial_delay_max();
- if (initial_delay_max < 0) {
- initial_delay_max = VSOMEIP_SD_DEFAULT_INITIAL_DELAY_MAX;
- }
if (initial_delay_min > initial_delay_max) {
const std::uint32_t tmp(initial_delay_min);
initial_delay_min = initial_delay_max;
@@ -134,7 +136,8 @@ void service_discovery_impl::init() {
+ (cyclic_offer_delay_ / 10);
}
-void service_discovery_impl::start() {
+void
+service_discovery_impl::start() {
if (!endpoint_) {
endpoint_ = host_->create_service_discovery_endpoint(
sd_multicast_, port_, reliable_);
@@ -160,9 +163,15 @@ void service_discovery_impl::start() {
i.second->set_sent_counter(0);
}
}
- if (endpoint_) {
+ if (endpoint_ && !reliable_) {
// rejoin multicast group
- endpoint_->join(sd_multicast_);
+#ifndef ANDROID
+ reinterpret_cast<udp_server_endpoint_impl*>(
+ endpoint_.get())->join(sd_multicast_);
+#else
+ dynamic_cast<udp_server_endpoint_impl*>(
+ endpoint_.get())->join(sd_multicast_);
+#endif
}
}
is_suspended_ = false;
@@ -172,31 +181,35 @@ void service_discovery_impl::start() {
start_ttl_timer();
}
-void service_discovery_impl::stop() {
+void
+service_discovery_impl::stop() {
is_suspended_ = true;
stop_ttl_timer();
stop_last_msg_received_timer();
}
-void service_discovery_impl::request_service(service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor,
+void
+service_discovery_impl::request_service(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
ttl_t _ttl) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
auto find_service = requested_.find(_service);
if (find_service != requested_.end()) {
auto find_instance = find_service->second.find(_instance);
if (find_instance == find_service->second.end()) {
- find_service->second[_instance] = std::make_shared < request
- > (_major, _minor, _ttl);
+ find_service->second[_instance]
+ = std::make_shared<request>(_major, _minor, _ttl);
}
} else {
- requested_[_service][_instance] = std::make_shared < request
- > (_major, _minor, _ttl);
+ requested_[_service][_instance]
+ = std::make_shared<request>(_major, _minor, _ttl);
}
}
-void service_discovery_impl::release_service(service_t _service,
- instance_t _instance) {
+void
+service_discovery_impl::release_service(
+ service_t _service, instance_t _instance) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
auto find_service = requested_.find(_service);
if (find_service != requested_.end()) {
@@ -217,10 +230,11 @@ service_discovery_impl::find_request(service_t _service, instance_t _instance) {
return nullptr;
}
-void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
- eventgroup_t _eventgroup, major_version_t _major, ttl_t _ttl, client_t _client,
- subscription_type_e _subscription_type) {
- uint8_t subscribe_count(0);
+void
+service_discovery_impl::subscribe(
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
+ ttl_t _ttl, client_t _client) {
{
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
@@ -229,285 +243,268 @@ void service_discovery_impl::subscribe(service_t _service, instance_t _instance,
if (found_instance != found_service->second.end()) {
auto found_eventgroup = found_instance->second.find(_eventgroup);
if (found_eventgroup != found_instance->second.end()) {
- auto found_client = found_eventgroup->second.find(_client);
- if (found_client != found_eventgroup->second.end()) {
- if (found_client->second->get_major() != _major) {
- VSOMEIP_ERROR
- << "Subscriptions to different versions of the same "
- "service instance are not supported!";
+ auto its_subscription = found_eventgroup->second;
+ if (its_subscription->get_major() != _major) {
+ VSOMEIP_ERROR
+ << "Subscriptions to different versions of the same "
+ "service instance are not supported!";
+ } else if (its_subscription->is_selective()) {
+ if (its_subscription->add_client(_client)) {
+ its_subscription->set_state(_client,
+ subscription_state_e::ST_NOT_ACKNOWLEDGED);
+ send_subscription(its_subscription,
+ _service, _instance, _eventgroup,
+ _client);
}
- return;
}
+ return;
}
}
}
+ }
+
+ std::shared_ptr<endpoint> its_reliable, its_unreliable;
+ get_subscription_endpoints(_service, _instance,
+ its_reliable, its_unreliable);
- const uint8_t max_parallel_subscriptions = 16; // 4Bit Counter field
- subscribe_count = static_cast<uint8_t>(subscribed_[_service][_instance][_eventgroup].size());
- if (subscribe_count >= max_parallel_subscriptions) {
- VSOMEIP_WARNING << "Too many parallel subscriptions (max.16) on same event group: "
- << std::hex << _eventgroup << std::dec;
+ {
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+
+ // New subscription
+ std::shared_ptr<subscription> its_subscription
+ = create_subscription(
+ _service, _instance, _eventgroup, _major,
+ _ttl, its_reliable, its_unreliable);
+
+ if (!its_subscription) {
+ VSOMEIP_ERROR << __func__
+ << ": creating subscription failed!";
return;
}
- }
- std::shared_ptr < endpoint > its_unreliable;
- std::shared_ptr < endpoint > its_reliable;
- bool has_address(false);
- boost::asio::ip::address its_address;
+ subscribed_[_service][_instance][_eventgroup] = its_subscription;
- get_subscription_endpoints(its_unreliable, its_reliable,
- &its_address, &has_address, _service, _instance, _client);
+ its_subscription->add_client(_client);
+ its_subscription->set_state(_client,
+ subscription_state_e::ST_NOT_ACKNOWLEDGED);
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (!its_runtime) {
- return;
+ send_subscription(its_subscription,
+ _service, _instance, _eventgroup,
+ _client);
}
- std::shared_ptr<message_impl> its_message = its_runtime->create_message();
- {
- std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- // New subscription
- std::shared_ptr < subscription > its_subscription = std::make_shared
- < subscription > (_major, _ttl, its_reliable, its_unreliable,
- _subscription_type, subscribe_count);
- subscribed_[_service][_instance][_eventgroup][_client] = its_subscription;
- if (has_address) {
-
- if (_client != VSOMEIP_ROUTING_CLIENT) {
- if (its_subscription->get_endpoint(true) &&
- !host_->has_identified(_client, _service, _instance, true)) {
- return;
- }
- if (its_subscription->get_endpoint(false) &&
- !host_->has_identified(_client, _service, _instance, false)) {
- return;
- }
- }
+}
- const remote_offer_type_e its_offer_type = get_remote_offer_type(
- _service, _instance);
+void
+service_discovery_impl::send_subscription(
+ const std::shared_ptr<subscription> &_subscription,
+ const service_t _service, const instance_t _instance,
+ const eventgroup_t _eventgroup,
+ const client_t _client) {
+ auto its_reliable = _subscription->get_endpoint(true);
+ auto its_unreliable = _subscription->get_endpoint(false);
- if (its_offer_type == remote_offer_type_e::UNRELIABLE &&
- !its_subscription->get_endpoint(true) &&
- its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(false)->is_established()) {
- insert_subscription(its_message,
- _service, _instance,
- _eventgroup,
- its_subscription, its_offer_type);
- } else {
- its_subscription->set_udp_connection_established(false);
+ boost::asio::ip::address its_address;
+ get_subscription_address(its_reliable, its_unreliable, its_address);
+
+ if (!its_address.is_unspecified()) {
+ entry_data_t its_data;
+
+ const remote_offer_type_e its_offer_type
+ = get_remote_offer_type(_service, _instance);
+ if (its_offer_type == remote_offer_type_e::UNRELIABLE &&
+ !its_reliable && its_unreliable) {
+ if (its_unreliable->is_established()) {
+ its_data = create_eventgroup_entry(_service, _instance,
+ _eventgroup, _subscription, its_offer_type);
+ } else {
+ _subscription->set_udp_connection_established(false);
+ }
+ } else if (its_offer_type == remote_offer_type_e::RELIABLE &&
+ its_reliable && !its_unreliable) {
+ if (its_reliable->is_established()) {
+ its_data = create_eventgroup_entry(_service, _instance,
+ _eventgroup, _subscription, its_offer_type);
+ } else {
+ _subscription->set_tcp_connection_established(false);
+ }
+ } else if (its_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE &&
+ its_reliable && its_unreliable) {
+ if (its_reliable->is_established() && its_unreliable->is_established()) {
+ its_data = create_eventgroup_entry(_service, _instance,
+ _eventgroup, _subscription, its_offer_type);
+ } else {
+ if (!its_reliable->is_established()) {
+ _subscription->set_tcp_connection_established(false);
}
- } else if (its_offer_type == remote_offer_type_e::RELIABLE &&
- its_subscription->get_endpoint(true) &&
- !its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(true)->is_established()) {
- insert_subscription(its_message,
- _service, _instance,
- _eventgroup,
- its_subscription, its_offer_type);
- } else {
- its_subscription->set_tcp_connection_established(false);
- }
- } else if (its_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE &&
- its_subscription->get_endpoint(true) &&
- its_subscription->get_endpoint(false)) {
- if (its_subscription->get_endpoint(true)->is_established() &&
- its_subscription->get_endpoint(false)->is_established()) {
- insert_subscription(its_message,
- _service, _instance,
- _eventgroup,
- its_subscription, its_offer_type);
- } else {
- if (!its_subscription->get_endpoint(true)->is_established()) {
- its_subscription->set_tcp_connection_established(false);
- }
- if (!its_subscription->get_endpoint(false)->is_established()) {
- its_subscription->set_udp_connection_established(false);
- }
+ if (!its_unreliable->is_established()) {
+ _subscription->set_udp_connection_established(false);
}
}
+ }
- if(0 < its_message->get_entries().size()) {
- its_subscription->set_acknowledged(false);
+ if (its_data.entry_) {
+ if (_subscription->is_selective()) {
+ auto its_selective_option = std::make_shared<selective_option_impl>();
+ (void)its_selective_option->add_client(_client);
+
+ its_data.options_.push_back(its_selective_option);
}
+
+ // TODO: Implement a simple path, that sends a single message
+ auto its_current_message = std::make_shared<message_impl>();
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(its_current_message);
+
+ add_entry_data(its_messages, its_data);
+
+ serialize_and_send(its_messages, its_address);
}
}
- if (has_address && its_message->get_entries().size()
- && its_message->get_options().size()) {
- serialize_and_send(its_message, its_address);
- }
}
-void service_discovery_impl::get_subscription_endpoints(
- std::shared_ptr<endpoint>& _unreliable,
- std::shared_ptr<endpoint>& _reliable, boost::asio::ip::address* _address,
- bool* _has_address,
- service_t _service, instance_t _instance, client_t _client) const {
- _reliable = host_->find_or_create_remote_client(_service, _instance,
- true, _client);
- _unreliable = host_->find_or_create_remote_client(_service,
- _instance, false, _client);
- if (_unreliable) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<client_endpoint>(_unreliable);
+void
+service_discovery_impl::get_subscription_endpoints(
+ service_t _service, instance_t _instance,
+ std::shared_ptr<endpoint> &_reliable,
+ std::shared_ptr<endpoint> &_unreliable) const {
+ _unreliable = host_->find_or_create_remote_client(
+ _service, _instance, false, VSOMEIP_ROUTING_CLIENT);
+ _reliable = host_->find_or_create_remote_client(
+ _service, _instance, true, VSOMEIP_ROUTING_CLIENT);
+}
+
+void
+service_discovery_impl::get_subscription_address(
+ const std::shared_ptr<endpoint> &_reliable,
+ const std::shared_ptr<endpoint> &_unreliable,
+ boost::asio::ip::address &_address) const {
+ if (_reliable) {
+ auto its_client_endpoint
+ = std::dynamic_pointer_cast<client_endpoint>(_reliable);
if (its_client_endpoint) {
- *_has_address = its_client_endpoint->get_remote_address(
- *_address);
+ its_client_endpoint->get_remote_address(_address);
+ return;
}
}
- if (_reliable) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<client_endpoint>(_reliable);
+ if (_unreliable) {
+ auto its_client_endpoint
+ = std::dynamic_pointer_cast<client_endpoint>(_unreliable);
if (its_client_endpoint) {
- *_has_address = *_has_address
- || its_client_endpoint->get_remote_address(
- *_address);
+ its_client_endpoint->get_remote_address(_address);
}
}
}
-void service_discovery_impl::unsubscribe(service_t _service,
+void
+service_discovery_impl::unsubscribe(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, client_t _client) {
std::shared_ptr < runtime > its_runtime = runtime_.lock();
- if(!its_runtime) {
+ if (!its_runtime) {
return;
}
- std::shared_ptr < message_impl > its_message = its_runtime->create_message();
+
+ auto its_current_message = std::make_shared<message_impl>();
+
boost::asio::ip::address its_address;
- bool has_address(false);
{
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- std::shared_ptr < subscription > its_subscription;
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
- const remote_offer_type_e its_offer_type = get_remote_offer_type(
- _service, _instance);
auto found_eventgroup = found_instance->second.find(_eventgroup);
if (found_eventgroup != found_instance->second.end()) {
- auto found_client = found_eventgroup->second.find(_client);
- if (found_client != found_eventgroup->second.end()) {
- its_subscription = found_client->second;
- its_subscription->set_ttl(0);
- found_eventgroup->second.erase(_client);
- auto endpoint = its_subscription->get_endpoint(false);
- if (endpoint) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<client_endpoint>(
- endpoint);
- if (its_client_endpoint) {
- has_address =
- its_client_endpoint->get_remote_address(
- its_address);
- }
- } else {
- endpoint = its_subscription->get_endpoint(true);
- if (endpoint) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<
- client_endpoint>(endpoint);
- if (its_client_endpoint) {
- has_address =
- its_client_endpoint->get_remote_address(
- its_address);
- }
- } else {
- return;
- }
+ auto its_subscription = found_eventgroup->second;
+ if (its_subscription->remove_client(_client)) {
+ auto its_reliable = its_subscription->get_endpoint(true);
+ auto its_unreliable = its_subscription->get_endpoint(false);
+ get_subscription_address(
+ its_reliable, its_unreliable, its_address);
+ if (!its_subscription->has_client()) {
+ its_subscription->set_ttl(0);
+ } else if (its_subscription->is_selective()) {
+ auto its_major = its_subscription->get_major();
+
+ // create a dummy subscription object to unsubscribe
+ // the single client.
+ its_subscription = std::make_shared<subscription>();
+ its_subscription->set_major(its_major);
+ its_subscription->set_ttl(0);
+ its_subscription->set_selective(true);
+ its_subscription->add_client(_client);
+ its_subscription->set_endpoint(its_reliable, true);
+ its_subscription->set_endpoint(its_unreliable, false);
+ }
+ }
+
+ const remote_offer_type_e its_offer_type
+ = get_remote_offer_type(its_subscription);
+
+ auto its_data = create_eventgroup_entry(_service, _instance,
+ _eventgroup, its_subscription, its_offer_type);
+ if (its_data.entry_) {
+ its_current_message->add_entry_data(its_data.entry_, its_data.options_);
+ }
+
+ // Finally update the subscriptions
+ if (!its_subscription->has_client()) {
+ found_instance->second.erase(found_eventgroup);
+ if (found_instance->second.size() == 0) {
+ found_service->second.erase(found_instance);
}
- insert_subscription(its_message, _service, _instance,
- _eventgroup, its_subscription, its_offer_type);
}
}
}
}
}
- if (has_address && its_message->get_entries().size()
- && its_message->get_options().size()) {
- serialize_and_send(its_message, its_address);
- }
-}
-void service_discovery_impl::unsubscribe_all(service_t _service, instance_t _instance) {
- std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- auto found_service = subscribed_.find(_service);
- if (found_service != subscribed_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- found_instance->second.clear();
- }
- }
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(its_current_message);
+
+ serialize_and_send(its_messages, its_address);
}
-void service_discovery_impl::unsubscribe_client(service_t _service,
- instance_t _instance,
- client_t _client) {
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (!its_runtime) {
- return;
- }
- std::shared_ptr < message_impl > its_message = its_runtime->create_message();
+void
+service_discovery_impl::unsubscribe_all(
+ service_t _service, instance_t _instance) {
+
+ auto its_current_message = std::make_shared<message_impl>();;
boost::asio::ip::address its_address;
- bool has_address(false);
+ const remote_offer_type_e its_offer_type
+ = get_remote_offer_type(_service, _instance);
+
{
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- std::shared_ptr < subscription > its_subscription;
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
- const remote_offer_type_e its_offer_type = get_remote_offer_type(
- _service, _instance);
- for (auto &found_eventgroup : found_instance->second) {
- auto found_client = found_eventgroup.second.find(_client);
- if (found_client != found_eventgroup.second.end()) {
- its_subscription = found_client->second;
- its_subscription->set_ttl(0);
- found_eventgroup.second.erase(_client);
- if (!has_address) {
- auto endpoint = its_subscription->get_endpoint(
- false);
- if (endpoint) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<
- client_endpoint>(endpoint);
- if (its_client_endpoint) {
- has_address =
- its_client_endpoint->get_remote_address(
- its_address);
- }
- } else {
- endpoint = its_subscription->get_endpoint(true);
- if (endpoint) {
- std::shared_ptr<client_endpoint> its_client_endpoint =
- std::dynamic_pointer_cast<
- client_endpoint>(endpoint);
- if (its_client_endpoint) {
- has_address =
- its_client_endpoint->get_remote_address(
- its_address);
- }
- } else {
- return;
- }
- }
- }
- insert_subscription(its_message, _service, _instance,
- found_eventgroup.first, its_subscription, its_offer_type);
+ for (auto &its_eventgroup : found_instance->second) {
+ auto its_subscription = its_eventgroup.second;
+ its_subscription->set_ttl(0);
+ auto its_data = create_eventgroup_entry(_service, _instance,
+ its_eventgroup.first, its_subscription, its_offer_type);
+ auto its_reliable = its_subscription->get_endpoint(true);
+ auto its_unreliable = its_subscription->get_endpoint(false);
+ get_subscription_address(
+ its_reliable, its_unreliable, its_address);
+ if (its_data.entry_) {
+ its_current_message->add_entry_data(its_data.entry_, its_data.options_);
}
}
+ found_instance->second.clear();
}
}
}
- if (has_address && its_message->get_entries().size()
- && its_message->get_options().size()) {
- serialize_and_send(its_message, its_address);
- }
+
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(its_current_message);
+
+ serialize_and_send(its_messages, its_address);
}
-std::pair<session_t, bool> service_discovery_impl::get_session(
+std::pair<session_t, bool>
+service_discovery_impl::get_session(
const boost::asio::ip::address &_address) {
std::pair<session_t, bool> its_session;
auto found_session = sessions_sent_.find(_address);
@@ -519,7 +516,8 @@ std::pair<session_t, bool> service_discovery_impl::get_session(
return its_session;
}
-void service_discovery_impl::increment_session(
+void
+service_discovery_impl::increment_session(
const boost::asio::ip::address &_address) {
auto found_session = sessions_sent_.find(_address);
if (found_session != sessions_sent_.end()) {
@@ -530,7 +528,8 @@ void service_discovery_impl::increment_session(
}
}
-bool service_discovery_impl::is_reboot(
+bool
+service_discovery_impl::is_reboot(
const boost::asio::ip::address &_sender,
const boost::asio::ip::address &_destination,
bool _reboot_flag, session_t _session) {
@@ -603,149 +602,17 @@ bool service_discovery_impl::is_reboot(
return result;
}
-template<class Option, typename AddressType>
-std::shared_ptr<option_impl> service_discovery_impl::find_existing_option(
- std::shared_ptr<message_impl> &_message,
- AddressType _address,
- uint16_t _port, layer_four_protocol_e _protocol,
- option_type_e _option_type) {
- if (_message->get_options().size() > 0) {
- std::uint16_t option_length(0x0);
- if(_option_type == option_type_e::IP4_ENDPOINT ||
- _option_type == option_type_e::IP4_MULTICAST) {
- option_length = 0x9;
- } else if(_option_type == option_type_e::IP6_ENDPOINT ||
- _option_type == option_type_e::IP6_MULTICAST) {
- option_length = 0x15;
- } else { // unsupported option type
- return nullptr;
- }
-
- bool is_multicast(false);
- if(_option_type == option_type_e::IP4_MULTICAST ||
- _option_type == option_type_e::IP6_MULTICAST) {
- is_multicast = true;
- }
-
- std::vector<std::shared_ptr<option_impl>> its_options =
- _message->get_options();
- for (const std::shared_ptr<option_impl>& opt : its_options) {
- if (opt->get_length() == option_length &&
- opt->get_type() == _option_type &&
- std::static_pointer_cast<ip_option_impl>(opt)->get_layer_four_protocol() == _protocol &&
- std::static_pointer_cast<ip_option_impl>(opt)->get_port() == _port &&
- std::static_pointer_cast<Option>(opt)->is_multicast() == is_multicast &&
- std::static_pointer_cast<Option>(opt)->get_address() == _address) {
- return opt;
- }
- }
- }
- return nullptr;
-}
-template<class Option, typename AddressType>
-bool service_discovery_impl::check_message_for_ip_option_and_assign_existing(
- std::shared_ptr<message_impl> &_message,
- std::shared_ptr<entry_impl> _entry, AddressType _address,
- uint16_t _port, layer_four_protocol_e _protocol,
- option_type_e _option_type) {
-
- std::shared_ptr<option_impl> its_option
- = find_existing_option<Option, AddressType>(_message, _address, _port, _protocol, _option_type);
- if (its_option) {
- _entry->assign_option(its_option);
- return true;
- }
- return false;
-}
-
-template<class Option, typename AddressType>
-void service_discovery_impl::assign_ip_option_to_entry(
- std::shared_ptr<Option> _option, AddressType _address,
- uint16_t _port, layer_four_protocol_e _protocol,
- std::shared_ptr<entry_impl> _entry) {
- if (_option) {
- _option->set_address(_address);
- _option->set_port(_port);
- _option->set_layer_four_protocol(_protocol);
- _entry->assign_option(_option);
- }
-}
-
-void service_discovery_impl::insert_option(
- std::shared_ptr<message_impl> &_message,
- std::shared_ptr<entry_impl> _entry,
- const boost::asio::ip::address &_address, uint16_t _port,
- bool _is_reliable) {
- layer_four_protocol_e its_protocol =
- _is_reliable ? layer_four_protocol_e::TCP :
- layer_four_protocol_e::UDP;
- bool entry_assigned(false);
-
- if (unicast_ == _address) {
- if (unicast_.is_v4()) {
- ipv4_address_t its_address = unicast_.to_v4().to_bytes();
- entry_assigned = check_message_for_ip_option_and_assign_existing<
- ipv4_option_impl, ipv4_address_t>(_message, _entry,
- its_address, _port, its_protocol,
- option_type_e::IP4_ENDPOINT);
- if(!entry_assigned) {
- std::shared_ptr < ipv4_option_impl > its_option =
- _message->create_ipv4_option(false);
- assign_ip_option_to_entry<ipv4_option_impl, ipv4_address_t>(
- its_option, its_address, _port, its_protocol, _entry);
- }
- } else {
- ipv6_address_t its_address = unicast_.to_v6().to_bytes();
- entry_assigned = check_message_for_ip_option_and_assign_existing<
- ipv6_option_impl, ipv6_address_t>(_message, _entry,
- its_address, _port, its_protocol,
- option_type_e::IP6_ENDPOINT);
- if(!entry_assigned) {
- std::shared_ptr < ipv6_option_impl > its_option =
- _message->create_ipv6_option(false);
- assign_ip_option_to_entry<ipv6_option_impl, ipv6_address_t>(
- its_option, its_address, _port, its_protocol, _entry);
- }
- }
- } else {
- if (_address.is_v4()) {
- ipv4_address_t its_address = _address.to_v4().to_bytes();
- entry_assigned = check_message_for_ip_option_and_assign_existing<
- ipv4_option_impl, ipv4_address_t>(_message, _entry,
- its_address, _port, its_protocol,
- option_type_e::IP4_MULTICAST);
- if(!entry_assigned) {
- std::shared_ptr < ipv4_option_impl > its_option =
- _message->create_ipv4_option(true);
- assign_ip_option_to_entry<ipv4_option_impl, ipv4_address_t>(
- its_option, its_address, _port, its_protocol, _entry);
- }
- } else {
- ipv6_address_t its_address = _address.to_v6().to_bytes();
- entry_assigned = check_message_for_ip_option_and_assign_existing<
- ipv6_option_impl, ipv6_address_t>(_message, _entry,
- its_address, _port, its_protocol,
- option_type_e::IP6_MULTICAST);
- if(!entry_assigned) {
- std::shared_ptr < ipv6_option_impl > its_option =
- _message->create_ipv6_option(true);
- assign_ip_option_to_entry<ipv6_option_impl, ipv6_address_t>(
- its_option, its_address, _port, its_protocol, _entry);
- }
- }
- }
-}
-
-void service_discovery_impl::insert_find_entries(
- std::shared_ptr<message_impl> &_message, const requests_t &_requests,
- uint32_t _start, uint32_t &_size, bool &_done) {
+void
+service_discovery_impl::insert_find_entries(
+ std::vector<std::shared_ptr<message_impl> > &_messages,
+ const requests_t &_requests) {
std::lock_guard<std::mutex> its_lock(requested_mutex_);
- uint32_t its_size(0);
- uint32_t i = 0;
- _done = true;
- for (auto its_service : _requests) {
- for (auto its_instance : its_service.second) {
+ entry_data_t its_data;
+ its_data.entry_ = its_data.other_ = nullptr;
+
+ for (const auto& its_service : _requests) {
+ for (const auto& its_instance : its_service.second) {
auto its_request = its_instance.second;
// check if release_service was called
@@ -755,47 +622,36 @@ void service_discovery_impl::insert_find_entries(
if(the_instance != the_service->second.end() ) {
uint8_t its_sent_counter = its_request->get_sent_counter();
if (its_sent_counter != repetitions_max_ + 1) {
- if (i >= _start) {
- if (its_size + VSOMEIP_SOMEIP_SD_ENTRY_SIZE <= max_message_size_) {
- std::shared_ptr < serviceentry_impl > its_entry =
- _message->create_service_entry();
- if (its_entry) {
- its_entry->set_type(entry_type_e::FIND_SERVICE);
- its_entry->set_service(its_service.first);
- its_entry->set_instance(its_instance.first);
- its_entry->set_major_version(its_request->get_major());
- its_entry->set_minor_version(its_request->get_minor());
- its_entry->set_ttl(its_request->get_ttl());
- its_size += VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
- its_sent_counter++;
-
- its_request->set_sent_counter(its_sent_counter);
- } else {
- VSOMEIP_ERROR << "Failed to create service entry!";
- }
- } else {
- _done = false;
- _size = its_size;
- return;
- }
+ auto its_entry = std::make_shared<serviceentry_impl>();
+ if (its_entry) {
+ its_entry->set_type(entry_type_e::FIND_SERVICE);
+ its_entry->set_service(its_service.first);
+ its_entry->set_instance(its_instance.first);
+ its_entry->set_major_version(its_request->get_major());
+ its_entry->set_minor_version(its_request->get_minor());
+ its_entry->set_ttl(its_request->get_ttl());
+ its_sent_counter++;
+
+ its_request->set_sent_counter(its_sent_counter);
+
+ its_data.entry_ = its_entry;
+ add_entry_data(_messages, its_data);
+ } else {
+ VSOMEIP_ERROR << "Failed to create service entry!";
}
}
- i++;
}
}
-
}
}
- _size = its_size;
}
-void service_discovery_impl::insert_offer_entries(
- std::shared_ptr<message_impl> &_message, const services_t &_services,
- uint32_t &_start, uint32_t _size, bool &_done, bool _ignore_phase) {
- uint32_t i = 0;
- uint32_t its_size(_size);
- for (const auto its_service : _services) {
- for (const auto its_instance : its_service.second) {
+void
+service_discovery_impl::insert_offer_entries(
+ std::vector<std::shared_ptr<message_impl> > &_messages,
+ const services_t &_services, bool _ignore_phase) {
+ for (const auto& its_service : _services) {
+ for (const auto& its_instance : its_service.second) {
if ((!is_suspended_)
&& ((!is_diagnosis_)
|| (is_diagnosis_
@@ -804,31 +660,24 @@ void service_discovery_impl::insert_offer_entries(
// Only insert services with configured endpoint(s)
if ((_ignore_phase || its_instance.second->is_in_mainphase())
&& (its_instance.second->get_endpoint(false)
- || its_instance.second->get_endpoint(true))
- && its_instance.second->get_ttl() > 0) {
- if (i >= _start) {
- if (!insert_offer_service(_message, its_service.first,
- its_instance.first, its_instance.second, its_size)) {
- _start = i;
- _done = false;
- return;
- }
- }
+ || its_instance.second->get_endpoint(true))) {
+ insert_offer_service(_messages, its_instance.second);
}
- i++;
}
}
}
- _start = i;
- _done = true;
}
-bool service_discovery_impl::insert_subscription(
- std::shared_ptr<message_impl> &_message, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<subscription> &_subscription,
+entry_data_t
+service_discovery_impl::create_eventgroup_entry(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ const std::shared_ptr<subscription> &_subscription,
remote_offer_type_e _offer_type) {
- bool ret(false);
+
+ entry_data_t its_data;
+ its_data.entry_ = nullptr;
+ its_data.other_ = nullptr;
+
std::shared_ptr<endpoint> its_reliable_endpoint(_subscription->get_endpoint(true));
std::shared_ptr<endpoint> its_unreliable_endpoint(_subscription->get_endpoint(false));
@@ -855,279 +704,253 @@ bool service_discovery_impl::insert_subscription(
break;
}
- if (!insert_reliable && !insert_unreliable) {
+ if (!insert_reliable && !insert_unreliable
+ && _offer_type != remote_offer_type_e::UNKNOWN) {
VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
"subscription doesn't match offer type: ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] "
<< _offer_type;
- return false;
+ return its_data;
}
- std::shared_ptr<eventgroupentry_impl> its_entry;
+ std::shared_ptr<eventgroupentry_impl> its_entry, its_other;
if (insert_reliable && its_reliable_endpoint) {
const std::uint16_t its_port = its_reliable_endpoint->get_local_port();
if (its_port) {
- its_entry = _message->create_eventgroup_entry();
+ its_entry = std::make_shared<eventgroupentry_impl>();
+ if (!its_entry) {
+ VSOMEIP_ERROR << __func__
+ << ": Could not create eventgroup entry.";
+ return its_data;
+ }
+
its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
its_entry->set_service(_service);
its_entry->set_instance(_instance);
its_entry->set_eventgroup(_eventgroup);
- its_entry->set_counter(_subscription->get_counter());
+ its_entry->set_counter(0);
its_entry->set_major_version(_subscription->get_major());
its_entry->set_ttl(_subscription->get_ttl());
- insert_option(_message, its_entry, unicast_, its_port, true);
- ret = true;
+ its_data.entry_ = its_entry;
+
+ for (const auto its_client : _subscription->get_clients()) {
+ if (_subscription->get_state(its_client)
+ == subscription_state_e::ST_RESUBSCRIBING_NOT_ACKNOWLEDGED) {
+ its_other = std::make_shared<eventgroupentry_impl>();
+ its_other->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
+ its_other->set_service(_service);
+ its_other->set_instance(_instance);
+ its_other->set_eventgroup(_eventgroup);
+ its_other->set_counter(0);
+ its_other->set_major_version(_subscription->get_major());
+ its_other->set_ttl(0);
+ its_data.other_ = its_other;
+ break;
+ }
+ }
+
+ auto its_option = create_ip_option(unicast_, its_port, true);
+ its_data.options_.push_back(its_option);
} else {
VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
"local reliable port is zero: ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- ret = false;
+ return its_data;
}
}
+
if (insert_unreliable && its_unreliable_endpoint) {
const std::uint16_t its_port = its_unreliable_endpoint->get_local_port();
if (its_port) {
if (!its_entry) {
- its_entry = _message->create_eventgroup_entry();
+ its_entry = std::make_shared<eventgroupentry_impl>();
+ if (!its_entry) {
+ VSOMEIP_ERROR << __func__
+ << ": Could not create eventgroup entry.";
+ return its_data;
+ }
+
its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
its_entry->set_service(_service);
its_entry->set_instance(_instance);
its_entry->set_eventgroup(_eventgroup);
- its_entry->set_counter(_subscription->get_counter());
+ its_entry->set_counter(0);
its_entry->set_major_version(_subscription->get_major());
its_entry->set_ttl(_subscription->get_ttl());
+
+ its_data.entry_ = its_entry;
+ }
+
+ for (const auto its_client : _subscription->get_clients()) {
+ if (_subscription->get_state(its_client)
+ == subscription_state_e::ST_RESUBSCRIBING_NOT_ACKNOWLEDGED) {
+ if (!its_other) {
+ its_other = std::make_shared<eventgroupentry_impl>();
+ its_other->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
+ its_other->set_service(_service);
+ its_other->set_instance(_instance);
+ its_other->set_eventgroup(_eventgroup);
+ its_other->set_counter(0);
+ its_other->set_major_version(_subscription->get_major());
+ its_other->set_ttl(0);
+ its_data.other_ = its_other;
+ break;
+ }
+ }
}
- insert_option(_message, its_entry, unicast_, its_port, false);
- ret = true;
+
+ auto its_option = create_ip_option(unicast_, its_port, false);
+ its_data.options_.push_back(its_option);
} else {
VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
" local unreliable port is zero: ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "."
<< std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- ret = false;
+ return its_data;
}
}
- return ret;
-}
-bool service_discovery_impl::insert_nack_subscription_on_resubscribe(std::shared_ptr<message_impl> &_message,
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- std::shared_ptr<subscription> &_subscription, remote_offer_type_e _offer_type) {
- bool ret(false);
- // SIP_SD_844:
- // This method is used for not acknowledged subscriptions on renew subscription
- // Two entries: Stop subscribe & subscribe within one SD-Message
- // One option: Both entries reference it
-
- auto insert_entry = [&](ttl_t _ttl) {
- std::shared_ptr<eventgroupentry_impl> its_entry =
- _message->create_eventgroup_entry();
- // SUBSCRIBE_EVENTGROUP and STOP_SUBSCRIBE_EVENTGROUP are identical
- its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP);
- its_entry->set_service(_service);
- its_entry->set_instance(_instance);
- its_entry->set_eventgroup(_eventgroup);
- its_entry->set_counter(_subscription->get_counter());
- its_entry->set_major_version(_subscription->get_major());
- its_entry->set_ttl(_ttl);
- return its_entry;
- };
+ if (its_entry
+ &&_subscription->is_selective()) {
+ auto its_selective_option = std::make_shared<selective_option_impl>();
+ for (const auto &its_client : _subscription->get_clients())
+ (void)its_selective_option->add_client(its_client);
- std::shared_ptr<endpoint> its_reliable_endpoint(_subscription->get_endpoint(true));
- std::shared_ptr<endpoint> its_unreliable_endpoint(_subscription->get_endpoint(false));
+ its_data.options_.push_back(its_selective_option);
+ }
- if (_offer_type == remote_offer_type_e::UNRELIABLE &&
- !its_reliable_endpoint && its_unreliable_endpoint) {
- if (its_unreliable_endpoint->is_established()) {
- const std::uint16_t its_port = its_unreliable_endpoint->get_local_port();
- if (its_port) {
- std::shared_ptr<eventgroupentry_impl> its_stop_entry = insert_entry(0);
- std::shared_ptr<eventgroupentry_impl> its_entry = insert_entry(_subscription->get_ttl());
- insert_option(_message, its_stop_entry, unicast_, its_port, false);
- insert_option(_message, its_entry, unicast_, its_port, false);
- ret = true;
- } else {
- VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
- "local unreliable port is zero: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- }
- } else {
- _subscription->set_udp_connection_established(false);
- }
- } else if (_offer_type == remote_offer_type_e::RELIABLE &&
- its_reliable_endpoint && !its_unreliable_endpoint) {
- if (its_reliable_endpoint->is_established()) {
- const std::uint16_t its_port = its_reliable_endpoint->get_local_port();
- if (its_port) {
- std::shared_ptr<eventgroupentry_impl> its_stop_entry = insert_entry(0);
- std::shared_ptr<eventgroupentry_impl> its_entry = insert_entry(_subscription->get_ttl());
- insert_option(_message, its_stop_entry, unicast_, its_port, true);
- insert_option(_message, its_entry, unicast_, its_port, true);
- ret = true;
- } else {
- VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
- "local reliable port is zero: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- }
- } else {
- _subscription->set_tcp_connection_established(false);
- }
- } else if (_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE &&
- its_reliable_endpoint && its_unreliable_endpoint) {
- if (its_reliable_endpoint->is_established() &&
- its_unreliable_endpoint->is_established()) {
- const std::uint16_t its_reliable_port = its_reliable_endpoint->get_local_port();
- const std::uint16_t its_unreliable_port = its_unreliable_endpoint->get_local_port();
- if (its_reliable_port && its_unreliable_port) {
- std::shared_ptr<eventgroupentry_impl> its_stop_entry = insert_entry(0);
- std::shared_ptr<eventgroupentry_impl> its_entry = insert_entry(_subscription->get_ttl());
- insert_option(_message, its_stop_entry, unicast_, its_reliable_port, true);
- insert_option(_message, its_entry, unicast_, its_reliable_port, true);
- insert_option(_message, its_stop_entry, unicast_, its_unreliable_port, false);
- insert_option(_message, its_entry, unicast_, its_unreliable_port, false);
- ret = true;
- } else if (!its_reliable_port) {
- VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
- "local reliable port is zero: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- } else if (!its_unreliable_port) {
- VSOMEIP_WARNING << __func__ << ": Didn't insert subscription as "
- "local unreliable port is zero: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]";
- }
- } else {
- if (!its_reliable_endpoint->is_established()) {
- _subscription->set_tcp_connection_established(false);
- }
- if (!its_unreliable_endpoint->is_established()) {
- _subscription->set_udp_connection_established(false);
- }
- }
- } else {
- VSOMEIP_WARNING << __func__ << ": Couldn't insert StopSubscribe/Subscribe ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] "
- << _offer_type;
+ if (its_entry && its_other) {
+ its_data.entry_ = its_other;
+ its_data.other_ = its_entry;
}
- return ret;
+
+ return its_data;
}
-void service_discovery_impl::insert_subscription_ack(
- std::shared_ptr<message_impl> &_message, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
+void
+service_discovery_impl::insert_subscription_ack(
+ const std::shared_ptr<remote_subscription_ack>& _acknowledgement,
const std::shared_ptr<eventgroupinfo> &_info, ttl_t _ttl,
- uint8_t _counter, major_version_t _major, uint16_t _reserved,
- const std::shared_ptr<endpoint_definition> &_target) {
- std::unique_lock<std::mutex> its_lock(_message->get_message_lock());
- _message->increase_number_contained_acks();
- for (auto its_entry : _message->get_entries()) {
+ const std::shared_ptr<endpoint_definition> &_target,
+ const client_t _client) {
+ std::unique_lock<std::recursive_mutex> its_lock(_acknowledgement->get_lock());
+ auto its_message = _acknowledgement->get_current_message();
+
+ auto its_service = _info->get_service();
+ auto its_instance = _info->get_instance();
+ auto its_eventgroup = _info->get_eventgroup();
+ auto its_major = _info->get_major();
+
+ for (const auto& its_entry : its_message->get_entries()) {
if (its_entry->is_eventgroup_entry()) {
- std::shared_ptr < eventgroupentry_impl > its_eventgroup_entry =
- std::dynamic_pointer_cast < eventgroupentry_impl
- > (its_entry);
- if(its_eventgroup_entry->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
- && its_eventgroup_entry->get_service() == _service
- && its_eventgroup_entry->get_instance() == _instance
- && its_eventgroup_entry->get_eventgroup() == _eventgroup
- && its_eventgroup_entry->get_major_version() == _major
- && its_eventgroup_entry->get_reserved() == _reserved
- && its_eventgroup_entry->get_counter() == _counter
+ std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry
+ = std::dynamic_pointer_cast<eventgroupentry_impl>(its_entry);
+ if (its_eventgroup_entry->get_type()
+ == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
+ && its_eventgroup_entry->get_service() == its_service
+ && its_eventgroup_entry->get_instance() == its_instance
+ && its_eventgroup_entry->get_eventgroup() == its_eventgroup
+ && its_eventgroup_entry->get_major_version() == its_major
&& its_eventgroup_entry->get_ttl() == _ttl) {
- if (_target) {
- if (_target->is_reliable()) {
- if (!its_eventgroup_entry->get_target(true)) {
- its_eventgroup_entry->add_target(_target);
- }
- } else {
- if (!its_eventgroup_entry->get_target(false)) {
- its_eventgroup_entry->add_target(_target);
+
+ if (_ttl > 0) {
+ if (_target) {
+ if (_target->is_reliable()) {
+ if (!its_eventgroup_entry->get_target(true)) {
+ its_eventgroup_entry->add_target(_target);
+ }
+ } else {
+ if (!its_eventgroup_entry->get_target(false)) {
+ its_eventgroup_entry->add_target(_target);
+ }
}
}
}
+
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ auto its_selective_option = its_eventgroup_entry->get_selective_option();
+ if (its_selective_option) {
+ its_selective_option->add_client(_client);
+ }
+ }
+
return;
}
}
}
- std::shared_ptr < eventgroupentry_impl > its_entry =
- _message->create_eventgroup_entry();
+ entry_data_t its_data;
+
+ std::shared_ptr<eventgroupentry_impl> its_entry
+ = std::make_shared<eventgroupentry_impl>();
its_entry->set_type(entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
- its_entry->set_service(_service);
- its_entry->set_instance(_instance);
- its_entry->set_eventgroup(_eventgroup);
- its_entry->set_major_version(_major);
- its_entry->set_reserved(_reserved);
- its_entry->set_counter(_counter);
+ its_entry->set_service(its_service);
+ its_entry->set_instance(its_instance);
+ its_entry->set_eventgroup(its_eventgroup);
+ its_entry->set_major_version(its_major);
+ its_entry->set_reserved(0);
+ its_entry->set_counter(0);
// SWS_SD_00315
its_entry->set_ttl(_ttl);
- if (_target) {
- its_entry->add_target(_target);
+ if (_ttl > 0) {
+ if (_target) {
+ its_entry->add_target(_target);
+ }
+
+ boost::asio::ip::address its_address;
+ uint16_t its_port;
+ if (_info->get_multicast(its_address, its_port)
+ && _info->get_threshold() > 0) {
+ // SIP_SD_855
+ // Only insert a multicast option for eventgroups with multicast threshold > 0
+ auto its_option = create_ip_option(its_address, its_port, false);
+ its_data.options_.push_back(its_option);
+ }
}
+ // Selective
+ if (_client != VSOMEIP_ROUTING_CLIENT) {
+ auto its_selective_option = std::make_shared<selective_option_impl>();
+ (void)its_selective_option->add_client(_client);
- boost::asio::ip::address its_address;
- uint16_t its_port;
- if (_info->get_multicast(its_address, its_port)) {
- insert_option(_message, its_entry, its_address, its_port, false);
- }
-}
-
-void service_discovery_impl::insert_subscription_nack(
- std::shared_ptr<message_impl> &_message, service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- uint8_t _counter, major_version_t _major, uint16_t _reserved) {
- std::unique_lock<std::mutex> its_lock(_message->get_message_lock());
- std::shared_ptr < eventgroupentry_impl > its_entry =
- _message->create_eventgroup_entry();
- // SWS_SD_00316 and SWS_SD_00385
- its_entry->set_type(entry_type_e::STOP_SUBSCRIBE_EVENTGROUP_ACK);
- its_entry->set_service(_service);
- its_entry->set_instance(_instance);
- its_entry->set_eventgroup(_eventgroup);
- its_entry->set_major_version(_major);
- its_entry->set_reserved(_reserved);
- its_entry->set_counter(_counter);
- // SWS_SD_00432
- its_entry->set_ttl(0x0);
- _message->increase_number_contained_acks();
-}
-
-bool service_discovery_impl::send(bool _is_announcing) {
+ its_data.options_.push_back(its_selective_option);
+ }
+
+ its_data.entry_ = its_entry;
+ its_data.other_ = nullptr;
+
+ add_entry_data_to_remote_subscription_ack_msg(_acknowledgement, its_data);
+}
+
+bool
+service_discovery_impl::send(bool _is_announcing) {
std::shared_ptr < runtime > its_runtime = runtime_.lock();
if (its_runtime) {
- std::vector< std::shared_ptr< message_impl > > its_messages;
- std::shared_ptr < message_impl > its_message;
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ std::shared_ptr<message_impl> its_message;
- if(_is_announcing) {
- its_message = its_runtime->create_message();
+ if (_is_announcing) {
+ its_message = std::make_shared<message_impl>();
its_messages.push_back(its_message);
std::lock_guard<std::mutex> its_lock(offer_mutex_);
services_t its_offers = host_->get_offered_services();
- fill_message_with_offer_entries(its_runtime, its_message,
- its_messages, its_offers, false);
+ insert_offer_entries(its_messages, its_offers, false);
// Serialize and send
- return serialize_and_send_messages(its_messages);
+ return send(its_messages);
}
}
return false;
}
// Interface endpoint_host
-void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
+void
+service_discovery_impl::on_message(
+ const byte_t *_data, length_t _length,
const boost::asio::ip::address &_sender,
const boost::asio::ip::address &_destination) {
#if 0
@@ -1147,21 +970,22 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
if (!check_source_address(_sender)) {
return;
}
- if (_destination == sd_multicast_address_) {
+ const bool received_via_mcast = (_destination == sd_multicast_address_);
+ if (received_via_mcast) {
std::lock_guard<std::mutex> its_lock(last_msg_received_timer_mutex_);
boost::system::error_code ec;
last_msg_received_timer_.cancel(ec);
- last_msg_received_timer_.expires_from_now(last_msg_received_timer_timeout_, ec);
+ last_msg_received_timer_.expires_from_now(
+ last_msg_received_timer_timeout_, ec);
last_msg_received_timer_.async_wait(
- std::bind(
- &service_discovery_impl::on_last_msg_received_timer_expired,
- shared_from_this(), std::placeholders::_1));
+ std::bind(&service_discovery_impl::on_last_msg_received_timer_expired,
+ shared_from_this(), std::placeholders::_1));
}
current_remote_address_ = _sender;
deserializer_->set_data(_data, _length);
- std::shared_ptr < message_impl
- > its_message(deserializer_->deserialize_sd_message());
+ std::shared_ptr<message_impl> its_message(
+ deserializer_->deserialize_sd_message());
deserializer_->reset();
if (its_message) {
// ignore all messages which are sent with invalid header fields
@@ -1187,55 +1011,51 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
reboot_notification_handler_(ip);
}
}
- std::vector < std::shared_ptr<option_impl> > its_options =
- its_message->get_options();
+
+ std::vector<std::shared_ptr<option_impl> > its_options
+ = its_message->get_options();
std::shared_ptr<runtime> its_runtime = runtime_.lock();
if (!its_runtime) {
return;
}
- std::shared_ptr < message_impl > its_message_response
- = its_runtime->create_message();
-
- std::uint8_t its_required_acks =
- its_message->get_number_required_acks();
- its_message_response->set_number_required_acks(its_required_acks);
- std::shared_ptr<sd_message_identifier_t> its_message_id =
- std::make_shared<sd_message_identifier_t>(
- its_message->get_session(), _sender, _destination,
- its_message_response);
+ auto its_acknowledgement = std::make_shared<remote_subscription_ack>(_sender);
- std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>> its_resubscribes;
- // 28 Bytes for SD-Header + Length Entries and Options Array
- its_resubscribes.push_back(std::make_pair(28, its_runtime->create_message()));
+ std::vector<std::shared_ptr<message_impl> > its_resubscribes;
+ its_resubscribes.push_back(std::make_shared<message_impl>());
const message_impl::entries_t& its_entries = its_message->get_entries();
const message_impl::entries_t::const_iterator its_end = its_entries.end();
bool is_stop_subscribe_subscribe(false);
+ bool force_initial_events(false);
- bool offer_acceptance_queried(false);
+ bool sd_acceptance_queried(false);
bool accept_offers(false);
bool expired_services(false);
for (auto iter = its_entries.begin(); iter != its_end; iter++) {
- if (!offer_acceptance_queried) {
- if (offer_acceptance_handler_) {
- ip_address_t ip;
- if (configuration_->offer_acceptance_required(_sender)) {
+ if (!sd_acceptance_queried) {
+ if (sd_acceptance_handler_) {
+ remote_info_t remote;
+ remote.port_ = ANY_PORT;
+ remote.first_ = ANY_PORT;
+ remote.last_ = ANY_PORT;
+ remote.is_range_ = false;
+ if (configuration_->sd_acceptance_required(_sender, ANY_PORT)) {
if (_sender.is_v4()) {
- ip.address_.v4_ = _sender.to_v4().to_bytes();
- ip.is_v4_ = true;
+ remote.ip_.address_.v4_ = _sender.to_v4().to_bytes();
+ remote.ip_.is_v4_ = true;
} else {
- ip.address_.v6_ = _sender.to_v6().to_bytes();
- ip.is_v4_ = false;
+ remote.ip_.address_.v6_ = _sender.to_v6().to_bytes();
+ remote.ip_.is_v4_ = false;
}
- accept_offers = offer_acceptance_handler_(ip);
+ accept_offers = sd_acceptance_handler_(remote);
if (!accept_offers && !expired_services) {
-
- VSOMEIP_INFO << "service_discovery_impl::on_message: Do not accept offer / subscribe from: "
- << std::hex << std::setw(4) << std::setfill('0') << _sender.to_string();
-
+ VSOMEIP_WARNING << "service_discovery_impl::" << __func__
+ << ": Do not accept offer / subscribe from "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << _sender.to_string();
remove_remote_offer_type_by_ip(_sender);
host_->expire_subscriptions(_sender);
host_->expire_services(_sender);
@@ -1244,85 +1064,82 @@ void service_discovery_impl::on_message(const byte_t *_data, length_t _length,
} else {
accept_offers = true;
}
- offer_acceptance_queried = true;
} else {
- offer_acceptance_queried = true;
accept_offers = true;
}
+ sd_acceptance_queried = true;
}
if ((*iter)->is_service_entry()) {
- std::shared_ptr < serviceentry_impl > its_service_entry =
- std::dynamic_pointer_cast < serviceentry_impl
- > (*iter);
+ std::shared_ptr<serviceentry_impl> its_service_entry
+ = std::dynamic_pointer_cast<serviceentry_impl>(*iter);
bool its_unicast_flag = its_message->get_unicast_flag();
process_serviceentry(its_service_entry, its_options,
- its_unicast_flag, &its_resubscribes, accept_offers);
- } else {
- if (accept_offers) {
- std::shared_ptr < eventgroupentry_impl > its_eventgroup_entry =
- std::dynamic_pointer_cast < eventgroupentry_impl
- > (*iter);
- bool force_initial_events(false);
+ its_unicast_flag, its_resubscribes,
+ received_via_mcast, accept_offers);
+ } else if (accept_offers) {
+ std::shared_ptr<eventgroupentry_impl> its_eventgroup_entry
+ = std::dynamic_pointer_cast<eventgroupentry_impl>(*iter);
+
+ bool must_process(true);
+ // Do we need to process it?
+ if (its_eventgroup_entry->get_type()
+ == entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ must_process = !has_same(iter, its_end, its_options);
+ }
+
+ if (must_process) {
if (is_stop_subscribe_subscribe) {
force_initial_events = true;
}
- is_stop_subscribe_subscribe = check_stop_subscribe_subscribe(
- iter, its_end, its_message->get_options());
+ is_stop_subscribe_subscribe =
+ check_stop_subscribe_subscribe(iter, its_end, its_options);
process_eventgroupentry(its_eventgroup_entry, its_options,
- its_message_response, _destination,
- its_message_id, is_stop_subscribe_subscribe, force_initial_events);
- } else {
- its_required_acks = 0;
+ its_acknowledgement, _destination,
+ is_stop_subscribe_subscribe, force_initial_events);
}
+
}
}
- // send answer directly if SubscribeEventgroup entries were (n)acked
- if (its_required_acks || its_message_response->get_number_required_acks() > 0) {
- bool sent(false);
- {
- std::lock_guard<std::mutex> its_lock(response_mutex_);
- if (its_message_response->all_required_acks_contained()) {
- update_subscription_expiration_timer(its_message_response);
- serialize_and_send(its_message_response, _sender);
- // set required acks to 0xFF to mark message as sent
- its_message_response->set_number_required_acks((std::numeric_limits<uint8_t>::max)());
- sent = true;
- }
- }
- if (sent) {
- for (const auto &fie : its_message_response->forced_initial_events_get()) {
- host_->send_initial_events(fie.service_, fie.instance_,
- fie.eventgroup_, fie.target_);
- }
- if (its_message_response->initial_events_required()) {
- for (const auto& ack_tuple :
- get_eventgroups_requiring_initial_events(its_message_response)) {
- host_->send_initial_events(std::get<0>(ack_tuple),
- std::get<1>(ack_tuple), std::get<2>(ack_tuple),
- std::get<3>(ack_tuple));
- }
+ {
+ std::unique_lock<std::recursive_mutex> its_lock(its_acknowledgement->get_lock());
+ its_acknowledgement->complete();
+ // TODO: Check the following logic...
+ if (its_acknowledgement->has_subscription()) {
+ update_acknowledgement(its_acknowledgement);
+ } else {
+ if (!its_acknowledgement->is_pending()
+ && !its_acknowledgement->is_done()) {
+ send_subscription_ack(its_acknowledgement);
}
}
}
- for (const auto& response : its_resubscribes) {
- if (response.second->get_entries().size() && response.second->get_options().size()) {
- serialize_and_send(response.second, _sender);
+
+ // check resubscriptions for validity
+ for (auto iter = its_resubscribes.begin(); iter != its_resubscribes.end();) {
+ if ((*iter)->get_entries().empty() || (*iter)->get_options().empty()) {
+ iter = its_resubscribes.erase(iter);
+ } else {
+ iter++;
}
}
+ if (!its_resubscribes.empty()) {
+ serialize_and_send(its_resubscribes, _sender);
+ }
} else {
- VSOMEIP_ERROR << "service_discovery_impl::on_message: deserialization error.";
+ VSOMEIP_ERROR << "service_discovery_impl::" << __func__ << ": Deserialization error.";
return;
}
}
// Entry processing
-void service_discovery_impl::process_serviceentry(
+void
+service_discovery_impl::process_serviceentry(
std::shared_ptr<serviceentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
bool _unicast_flag,
- std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes,
- bool _accept_offers) {
+ std::vector<std::shared_ptr<message_impl> > &_resubscribes,
+ bool _received_via_mcast, bool _accept_offers) {
// Read service info from entry
entry_type_e its_type = _entry->get_type();
@@ -1390,7 +1207,7 @@ void service_discovery_impl::process_serviceentry(
break;
case option_type_e::UNKNOWN:
default:
- VSOMEIP_ERROR << "Unsupported service option";
+ VSOMEIP_ERROR << __func__ << ": Unsupported service option";
break;
}
}
@@ -1405,15 +1222,16 @@ void service_discovery_impl::process_serviceentry(
break;
case entry_type_e::OFFER_SERVICE:
if (_accept_offers) {
- process_offerservice_serviceentry(its_service, its_instance,
- its_major, its_minor, its_ttl,
- its_reliable_address, its_reliable_port,
- its_unreliable_address, its_unreliable_port, _resubscribes);
+ process_offerservice_serviceentry(its_service, its_instance,
+ its_major, its_minor, its_ttl,
+ its_reliable_address, its_reliable_port,
+ its_unreliable_address, its_unreliable_port, _resubscribes,
+ _received_via_mcast);
}
break;
case entry_type_e::UNKNOWN:
default:
- VSOMEIP_ERROR << "Unsupported serviceentry type";
+ VSOMEIP_ERROR << __func__ << ": Unsupported service entry type";
}
} else if (_accept_offers) {
@@ -1435,14 +1253,16 @@ void service_discovery_impl::process_serviceentry(
}
}
-void service_discovery_impl::process_offerservice_serviceentry(
+void
+service_discovery_impl::process_offerservice_serviceentry(
service_t _service, instance_t _instance, major_version_t _major,
minor_version_t _minor, ttl_t _ttl,
const boost::asio::ip::address &_reliable_address,
uint16_t _reliable_port,
const boost::asio::ip::address &_unreliable_address,
uint16_t _unreliable_port,
- std::vector<std::pair<std::uint16_t, std::shared_ptr<message_impl>>>* _resubscribes) {
+ std::vector<std::shared_ptr<message_impl> > &_resubscribes,
+ bool _received_via_mcast) {
std::shared_ptr < runtime > its_runtime = runtime_.lock();
if (!its_runtime)
return;
@@ -1465,7 +1285,7 @@ void service_discovery_impl::process_offerservice_serviceentry(
&& !_reliable_address.is_unspecified()) {
offer_type = remote_offer_type_e::RELIABLE;
} else {
- VSOMEIP_WARNING << __func__ << ": unknown remote offer type ["
+ VSOMEIP_WARNING << __func__ << ": Unknown remote offer type ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "]";
}
@@ -1477,171 +1297,51 @@ void service_discovery_impl::process_offerservice_serviceentry(
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "]";
}
-
host_->add_routing_info(_service, _instance,
_major, _minor,
_ttl * get_ttl_factor(_service, _instance, ttl_factor_offers_),
_reliable_address, _reliable_port,
_unreliable_address, _unreliable_port);
- const std::function<void(std::uint16_t)> check_space =
- [&_resubscribes, &its_runtime](std::uint16_t _number) {
- if (_resubscribes->back().first + _number > VSOMEIP_MAX_UDP_MESSAGE_SIZE) {
- // 28 Bytes for SD-Header + Length Entries and Options Array
- _resubscribes->push_back(std::make_pair(28 + _number,
- its_runtime->create_message()));
- } else {
- _resubscribes->back().first =
- static_cast<std::uint16_t>(_resubscribes->back().first + _number);
- }
- };
+ // No need to resubscribe for unicast offers
+ if (_received_via_mcast) {
+ std::int32_t its_remaining = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
+ its_remaining -= _resubscribes.back()->get_size();
- std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- auto found_service = subscribed_.find(_service);
- if (found_service != subscribed_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- if (0 < found_instance->second.size()) {
- const remote_offer_type_e its_offer_type =
- get_remote_offer_type(_service, _instance);
- for (auto its_eventgroup : found_instance->second) {
- for (auto its_client : its_eventgroup.second) {
- std::shared_ptr<subscription> its_subscription(its_client.second);
- std::shared_ptr<endpoint> its_unreliable;
- std::shared_ptr<endpoint> its_reliable;
- bool has_address(false);
- boost::asio::ip::address its_address;
- get_subscription_endpoints(
- its_unreliable, its_reliable, &its_address,
- &has_address, _service, _instance,
- its_client.first);
+ std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
+ auto found_service = subscribed_.find(_service);
+ if (found_service != subscribed_.end()) {
+ auto found_instance = found_service->second.find(_instance);
+ if (found_instance != found_service->second.end()) {
+ if (0 < found_instance->second.size()) {
+ const remote_offer_type_e its_offer_type =
+ get_remote_offer_type(_service, _instance);
+ for (const auto& its_eventgroup : found_instance->second) {
+ auto its_subscription = its_eventgroup.second;
+ std::shared_ptr<endpoint> its_reliable, its_unreliable;
+ get_subscription_endpoints(_service, _instance,
+ its_reliable, its_unreliable);
its_subscription->set_endpoint(its_reliable, true);
its_subscription->set_endpoint(its_unreliable, false);
- if (its_client.first != VSOMEIP_ROUTING_CLIENT) {
- if (its_client.second->get_endpoint(true) &&
- !host_->has_identified(its_client.first, _service,
- _instance, true)) {
- continue;
- }
- if (its_client.second->get_endpoint(false) &&
- !host_->has_identified(its_client.first, _service,
- _instance, false)) {
- continue;
- }
- }
-
- if (its_subscription->is_acknowledged()) {
- if (its_offer_type == remote_offer_type_e::UNRELIABLE) {
- if (its_unreliable && its_unreliable->is_established()) {
- // 28 = 16 (subscription) + 12 (option)
- check_space(28);
- const std::size_t options_size_before =
- _resubscribes->back().second->get_options().size();
- if (insert_subscription(_resubscribes->back().second,
- _service, _instance,
- its_eventgroup.first,
- its_subscription, its_offer_type)) {
- its_subscription->set_acknowledged(false);
- const std::size_t options_size_after =
- _resubscribes->back().second->get_options().size();
- const std::size_t diff = options_size_after - options_size_before;
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first + (12u * diff - 12u));
- } else {
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first - 28);
- }
- }
- } else if (its_offer_type == remote_offer_type_e::RELIABLE) {
- if (its_reliable && its_reliable->is_established()) {
- // 28 = 16 (subscription) + 12 (option)
- check_space(28);
- const std::size_t options_size_before =
- _resubscribes->back().second->get_options().size();
- if (insert_subscription(_resubscribes->back().second,
- _service, _instance,
- its_eventgroup.first,
- its_subscription, its_offer_type)) {
- its_subscription->set_acknowledged(false);
- const std::size_t options_size_after =
- _resubscribes->back().second->get_options().size();
- const std::size_t diff = options_size_after - options_size_before;
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first + (12u * diff - 12u));
- } else {
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first - 28);
- }
- } else {
- its_client.second->set_tcp_connection_established(false);
- // restart TCP endpoint if not connected
- if (its_reliable) {
- its_reliable->restart();
- }
- }
- } else if (its_offer_type == remote_offer_type_e::RELIABLE_UNRELIABLE) {
- if (its_reliable && its_unreliable &&
- its_reliable->is_established() &&
- its_unreliable->is_established()) {
- // 40 = 16 (subscription) + 2x12 (option)
- check_space(40);
- const std::size_t options_size_before =
- _resubscribes->back().second->get_options().size();
- if (insert_subscription(_resubscribes->back().second,
- _service, _instance,
- its_eventgroup.first,
- its_subscription, its_offer_type)) {
- its_subscription->set_acknowledged(false);
- const std::size_t options_size_after =
- _resubscribes->back().second->get_options().size();
- const std::size_t diff = options_size_after - options_size_before;
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first + (12u * diff - 24u));
- } else {
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first - 40);
- }
- } else if (its_reliable && !its_reliable->is_established()) {
- its_client.second->set_tcp_connection_established(false);
- // restart TCP endpoint if not connected
- its_reliable->restart();
- }
- } else {
- VSOMEIP_WARNING << __func__ << ": unknown remote offer type ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "]";
- }
- } else {
- // 56 = 2x16 (subscription) + 2x12 (option)
- check_space(56);
- const std::size_t options_size_before =
- _resubscribes->back().second->get_options().size();
- if (insert_nack_subscription_on_resubscribe(_resubscribes->back().second,
- _service, _instance, its_eventgroup.first,
- its_subscription, its_offer_type) ) {
- const std::size_t options_size_after =
- _resubscribes->back().second->get_options().size();
- const std::size_t diff = options_size_after - options_size_before;
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first + (12u * diff - 24u));
+ for (const auto& its_client : its_subscription->get_clients()) {
+ if (its_subscription->get_state(its_client)
+ == subscription_state_e::ST_ACKNOWLEDGED) {
+ its_subscription->set_state(its_client,
+ subscription_state_e::ST_RESUBSCRIBING);
} else {
- _resubscribes->back().first =
- static_cast<std::uint16_t>(
- _resubscribes->back().first - 56u);
- }
-
- // restart TCP endpoint if not connected
- if (its_reliable && !its_reliable->is_established()) {
- its_reliable->restart();
+ its_subscription->set_state(its_client,
+ subscription_state_e::ST_RESUBSCRIBING_NOT_ACKNOWLEDGED);
}
}
+ auto its_data = create_eventgroup_entry(_service, _instance,
+ its_eventgroup.first, its_subscription, its_offer_type);
+ if (its_data.entry_) {
+ add_entry_data(_resubscribes, its_data);
+ }
+ for (const auto its_client : its_subscription->get_clients()) {
+ its_subscription->set_state(its_client,
+ subscription_state_e::ST_NOT_ACKNOWLEDGED);
+ }
}
}
}
@@ -1649,164 +1349,149 @@ void service_discovery_impl::process_offerservice_serviceentry(
}
}
-void service_discovery_impl::process_findservice_serviceentry(
- service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor, bool _unicast_flag) {
+void
+service_discovery_impl::process_findservice_serviceentry(
+ service_t _service, instance_t _instance,
+ major_version_t _major, minor_version_t _minor,
+ bool _unicast_flag) {
if (_instance != ANY_INSTANCE) {
std::shared_ptr<serviceinfo> its_info = host_->get_offered_service(
_service, _instance);
if (its_info) {
- send_uni_or_multicast_offerservice(_service, _instance, _major,
- _minor, its_info, _unicast_flag);
+ if (_major == ANY_MAJOR || _major == its_info->get_major()) {
+ if (_minor == 0xFFFFFFFF || _minor <= its_info->get_minor()) {
+ if (its_info->get_endpoint(false) || its_info->get_endpoint(true)) {
+ send_uni_or_multicast_offerservice(its_info, _unicast_flag);
+ }
+ }
+ }
}
} else {
std::map<instance_t, std::shared_ptr<serviceinfo>> offered_instances =
host_->get_offered_service_instances(_service);
// send back all available instances
for (const auto &found_instance : offered_instances) {
- send_uni_or_multicast_offerservice(_service, found_instance.first, _major,
- _minor, found_instance.second, _unicast_flag);
- }
- }
-}
-
-void service_discovery_impl::send_unicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
- if (_major == ANY_MAJOR || _major == _info->get_major()) {
- if (_minor == 0xFFFFFFFF || _minor <= _info->get_minor()) {
- if (_info->get_endpoint(false) || _info->get_endpoint(true)) {
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (!its_runtime) {
- return;
- }
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
- uint32_t its_size(max_message_size_);
- insert_offer_service(its_message, _service, _instance, _info,
- its_size);
- if (current_remote_address_.is_unspecified()) {
- VSOMEIP_ERROR << "service_discovery_impl::"
- "send_unicast_offer_service current remote address "
- "is unspecified, won't send offer.";
- } else {
- serialize_and_send(its_message, current_remote_address_);
+ auto its_info = found_instance.second;
+ if (_major == ANY_MAJOR || _major == its_info->get_major()) {
+ if (_minor == 0xFFFFFFFF || _minor <= its_info->get_minor()) {
+ if (its_info->get_endpoint(false) || its_info->get_endpoint(true)) {
+ send_uni_or_multicast_offerservice(its_info, _unicast_flag);
+ }
}
}
}
}
}
-void service_discovery_impl::send_multicast_offer_service(
- const std::shared_ptr<const serviceinfo> &_info, service_t _service,
- instance_t _instance, major_version_t _major, minor_version_t _minor) {
- if (_major == ANY_MAJOR || _major == _info->get_major()) {
- if (_minor == 0xFFFFFFFF || _minor <= _info->get_minor()) {
- if (_info->get_endpoint(false) || _info->get_endpoint(true)) {
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (!its_runtime) {
- return;
- }
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
-
- uint32_t its_size(max_message_size_);
- insert_offer_service(its_message, _service, _instance, _info,
- its_size);
-
- if (its_message->get_entries().size() > 0) {
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- std::pair<session_t, bool> its_session = get_session(
- unicast_);
- its_message->set_session(its_session.first);
- its_message->set_reboot_flag(its_session.second);
- if (host_->send(VSOMEIP_SD_CLIENT, its_message, true)) {
- increment_session(unicast_);
- }
- }
- }
- }
+void
+service_discovery_impl::send_unicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info) {
+ std::shared_ptr<runtime> its_runtime = runtime_.lock();
+ if (!its_runtime) {
+ return;
}
+
+ auto its_offer_message(std::make_shared<message_impl>());
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(its_offer_message);
+
+ insert_offer_service(its_messages, _info);
+
+ serialize_and_send(its_messages, current_remote_address_);
+}
+
+void
+service_discovery_impl::send_multicast_offer_service(
+ const std::shared_ptr<const serviceinfo> &_info) {
+ auto its_offer_message(std::make_shared<message_impl>());
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(its_offer_message);
+
+ insert_offer_service(its_messages, _info);
+
+ serialize_and_send(its_messages, current_remote_address_);
}
-void service_discovery_impl::on_endpoint_connected(
+void
+service_discovery_impl::on_endpoint_connected(
service_t _service, instance_t _instance,
- const std::shared_ptr<const vsomeip::endpoint> &_endpoint) {
+ const std::shared_ptr<endpoint> &_endpoint) {
std::shared_ptr<runtime> its_runtime = runtime_.lock();
if (!its_runtime) {
return;
}
- // send out subscriptions for services where the tcp connection
- // wasn't established at time of subscription
+ // TODO: Simplify this method! It is not clear, why we need to check
+ // both endpoints here although the method is always called for a
+ // single one.
- std::shared_ptr<message_impl> its_message(its_runtime->create_message());
- bool has_address(false);
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ its_messages.push_back(std::make_shared<message_impl>());
boost::asio::ip::address its_address;
+ std::shared_ptr<endpoint> its_dummy;
+ if (_endpoint->is_reliable())
+ get_subscription_address(_endpoint, its_dummy, its_address);
+ else
+ get_subscription_address(its_dummy, _endpoint, its_address);
+
{
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
auto found_instance = found_service->second.find(_instance);
if (found_instance != found_service->second.end()) {
- if(0 < found_instance->second.size()) {
+ if (0 < found_instance->second.size()) {
const remote_offer_type_e its_offer_type =
get_remote_offer_type(_service, _instance);
- for(const auto &its_eventgroup : found_instance->second) {
- for(const auto &its_client : its_eventgroup.second) {
- if (its_client.first != VSOMEIP_ROUTING_CLIENT) {
- if (its_client.second->get_endpoint(true) &&
- !host_->has_identified(its_client.first, _service,
- _instance, true)) {
- continue;
- }
- if (its_client.second->get_endpoint(false) &&
- !host_->has_identified(its_client.first, _service,
- _instance, false)) {
- continue;
- }
- }
- std::shared_ptr<subscription> its_subscription(its_client.second);
- if (its_subscription) {
- if (!its_subscription->is_tcp_connection_established() ||
- !its_subscription->is_udp_connection_established()) {
- const std::shared_ptr<const endpoint> its_reliable_endpoint(
- its_subscription->get_endpoint(true));
- const std::shared_ptr<const endpoint> its_unreliable_endpoint(
- its_subscription->get_endpoint(false));
- if(its_reliable_endpoint && its_reliable_endpoint->is_established()) {
- if(its_reliable_endpoint.get() == _endpoint.get()) {
- // mark tcp as established
- its_subscription->set_tcp_connection_established(true);
- }
+ for (const auto &its_eventgroup : found_instance->second) {
+ std::shared_ptr<subscription> its_subscription(its_eventgroup.second);
+ if (its_subscription) {
+ if (!its_subscription->is_tcp_connection_established() ||
+ !its_subscription->is_udp_connection_established()) {
+ const std::shared_ptr<const endpoint> its_reliable_endpoint(
+ its_subscription->get_endpoint(true));
+ const std::shared_ptr<const endpoint> its_unreliable_endpoint(
+ its_subscription->get_endpoint(false));
+ if (its_reliable_endpoint && its_reliable_endpoint->is_established()) {
+ if (its_reliable_endpoint.get() == _endpoint.get()) {
+ // mark tcp as established
+ its_subscription->set_tcp_connection_established(true);
}
- if(its_unreliable_endpoint && its_unreliable_endpoint->is_established()) {
- if(its_unreliable_endpoint.get() == _endpoint.get()) {
- // mark udp as established
- its_subscription->set_udp_connection_established(true);
- }
+ }
+ if (its_unreliable_endpoint && its_unreliable_endpoint->is_established()) {
+ if (its_unreliable_endpoint.get() == _endpoint.get()) {
+ // mark udp as established
+ its_subscription->set_udp_connection_established(true);
}
- if ((its_reliable_endpoint && its_unreliable_endpoint &&
- its_subscription->is_tcp_connection_established() &&
- its_subscription->is_udp_connection_established()) ||
- (its_reliable_endpoint && !its_unreliable_endpoint &&
- its_subscription->is_tcp_connection_established()) ||
- (its_unreliable_endpoint && !its_reliable_endpoint &&
- its_subscription->is_udp_connection_established())) {
- std::shared_ptr<endpoint> its_unreliable;
- std::shared_ptr<endpoint> its_reliable;
- get_subscription_endpoints(
- its_unreliable, its_reliable, &its_address,
- &has_address, _service, _instance,
- its_client.first);
- its_subscription->set_endpoint(its_reliable, true);
- its_subscription->set_endpoint(its_unreliable, false);
- insert_subscription(its_message, _service,
- _instance, its_eventgroup.first,
- its_subscription, its_offer_type);
- its_subscription->set_acknowledged(false);
+ }
+
+ if ((its_reliable_endpoint && its_unreliable_endpoint &&
+ its_subscription->is_tcp_connection_established() &&
+ its_subscription->is_udp_connection_established()) ||
+ (its_reliable_endpoint && !its_unreliable_endpoint &&
+ its_subscription->is_tcp_connection_established()) ||
+ (its_unreliable_endpoint && !its_reliable_endpoint &&
+ its_subscription->is_udp_connection_established())) {
+
+ std::shared_ptr<endpoint> its_unreliable;
+ std::shared_ptr<endpoint> its_reliable;
+ get_subscription_endpoints(_service, _instance,
+ its_reliable, its_unreliable);
+ get_subscription_address(its_reliable, its_unreliable, its_address);
+
+ its_subscription->set_endpoint(its_reliable, true);
+ its_subscription->set_endpoint(its_unreliable, false);
+ for (const auto its_client : its_subscription->get_clients())
+ its_subscription->set_state(its_client,
+ subscription_state_e::ST_NOT_ACKNOWLEDGED);
+
+ auto its_data = create_eventgroup_entry(_service, _instance,
+ its_eventgroup.first, its_subscription, its_offer_type);
+
+ if (its_data.entry_) {
+ add_entry_data(its_messages, its_data);
}
}
}
@@ -1816,168 +1501,161 @@ void service_discovery_impl::on_endpoint_connected(
}
}
}
- if (has_address && its_message->get_entries().size()
- && its_message->get_options().size()) {
- serialize_and_send(its_message, its_address);
- }
+
+ serialize_and_send(its_messages, its_address);
}
-bool service_discovery_impl::insert_offer_service(
- std::shared_ptr < message_impl > _message, service_t _service,
- instance_t _instance, const std::shared_ptr<const serviceinfo> &_info,
- uint32_t &_size) {
+std::shared_ptr<option_impl>
+service_discovery_impl::create_ip_option(
+ const boost::asio::ip::address &_address, uint16_t _port,
+ bool _is_reliable) const {
+ std::shared_ptr<option_impl> its_option;
+ if (_address.is_v4()) {
+ its_option = std::make_shared<ipv4_option_impl>(
+ _address, _port, _is_reliable);
+ } else {
+ its_option = std::make_shared<ipv6_option_impl>(
+ _address, _port, _is_reliable);
+ }
+ return its_option;
+}
- std::shared_ptr < endpoint > its_reliable = _info->get_endpoint(true);
- std::shared_ptr < endpoint > its_unreliable = _info->get_endpoint(false);
+void
+service_discovery_impl::insert_offer_service(
+ std::vector<std::shared_ptr<message_impl> > &_messages,
+ const std::shared_ptr<const serviceinfo> &_info) {
+ entry_data_t its_data;
+ its_data.entry_ = its_data.other_ = nullptr;
- uint32_t its_size = VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
+ std::shared_ptr<endpoint> its_reliable = _info->get_endpoint(true);
if (its_reliable) {
- uint32_t its_endpoint_size(0);
- if (unicast_.is_v4()) {
- if (!find_existing_option<ipv4_option_impl, ipv4_address_t>(_message,
- unicast_.to_v4().to_bytes(), its_reliable->get_local_port(),
- layer_four_protocol_e::TCP, option_type_e::IP4_ENDPOINT)) {
- its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE;
- }
- } else {
- if (!find_existing_option<ipv6_option_impl, ipv6_address_t>(_message,
- unicast_.to_v6().to_bytes(), its_reliable->get_local_port(),
- layer_four_protocol_e::TCP, option_type_e::IP6_ENDPOINT)) {
- its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE;
- }
- }
- its_size += its_endpoint_size;
+ auto its_new_option = create_ip_option(unicast_,
+ its_reliable->get_local_port(), true);
+ its_data.options_.push_back(its_new_option);
}
+
+ std::shared_ptr<endpoint> its_unreliable = _info->get_endpoint(false);
if (its_unreliable) {
- uint32_t its_endpoint_size(0);
- if (unicast_.is_v4()) {
- if (!find_existing_option<ipv4_option_impl, ipv4_address_t>(_message,
- unicast_.to_v4().to_bytes(), its_unreliable->get_local_port(),
- layer_four_protocol_e::UDP, option_type_e::IP4_ENDPOINT)) {
- its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV4_OPTION_SIZE;
- }
- } else {
- if (!find_existing_option<ipv6_option_impl, ipv6_address_t>(_message,
- unicast_.to_v6().to_bytes(), its_unreliable->get_local_port(),
- layer_four_protocol_e::UDP, option_type_e::IP6_ENDPOINT)) {
- its_endpoint_size = VSOMEIP_SOMEIP_SD_IPV6_OPTION_SIZE;
- }
- }
- its_size += its_endpoint_size;
+ auto its_new_option = create_ip_option(unicast_,
+ its_unreliable->get_local_port(), false);
+ its_data.options_.push_back(its_new_option);
}
- if (its_size <= _size) {
- _size -= its_size;
+ auto its_entry = std::make_shared<serviceentry_impl>();
+ if (its_entry) {
+ its_data.entry_ = its_entry;
- std::shared_ptr < serviceentry_impl > its_entry =
- _message->create_service_entry();
- if (its_entry) {
- its_entry->set_type(entry_type_e::OFFER_SERVICE);
- its_entry->set_service(_service);
- its_entry->set_instance(_instance);
- its_entry->set_major_version(_info->get_major());
- its_entry->set_minor_version(_info->get_minor());
+ its_entry->set_type(entry_type_e::OFFER_SERVICE);
+ its_entry->set_service(_info->get_service());
+ its_entry->set_instance(_info->get_instance());
+ its_entry->set_major_version(_info->get_major());
+ its_entry->set_minor_version(_info->get_minor());
- ttl_t its_ttl = _info->get_ttl();
- if (its_ttl > 0)
- its_ttl = ttl_;
- its_entry->set_ttl(its_ttl);
+ ttl_t its_ttl = _info->get_ttl();
+ if (its_ttl > 0)
+ its_ttl = ttl_;
+ its_entry->set_ttl(its_ttl);
- if (its_reliable) {
- insert_option(_message, its_entry, unicast_,
- its_reliable->get_local_port(), true);
- }
+ // This would be a clean solution but does _not_ work with the ANDi tool
+ // unsubscribe_all(_service, _instance);
- if (its_unreliable) {
- insert_option(_message, its_entry, unicast_,
- its_unreliable->get_local_port(), false);
- }
- // This would be a clean solution but does _not_ work with the ANDi tool
- //unsubscribe_all(_service, _instance);
- } else {
- VSOMEIP_ERROR << "Failed to create service entry.";
- }
- return true;
+ add_entry_data(_messages, its_data);
+ } else {
+ VSOMEIP_ERROR << __func__ << ": Failed to create service entry.";
}
-
- return false;
}
-void service_discovery_impl::process_eventgroupentry(
+void
+service_discovery_impl::process_eventgroupentry(
std::shared_ptr<eventgroupentry_impl> &_entry,
const std::vector<std::shared_ptr<option_impl> > &_options,
- std::shared_ptr < message_impl > &its_message_response,
+ std::shared_ptr<remote_subscription_ack> &_acknowledgement,
const boost::asio::ip::address &_destination,
- const std::shared_ptr<sd_message_identifier_t> &_message_id,
- bool _is_stop_subscribe_subscribe,
- bool _force_initial_events) {
+ bool _is_stop_subscribe_subscribe, bool _force_initial_events) {
+
+ auto its_sender = _acknowledgement->get_target_address();
+ auto its_session = _entry->get_owning_message()->get_session();
+
service_t its_service = _entry->get_service();
instance_t its_instance = _entry->get_instance();
eventgroup_t its_eventgroup = _entry->get_eventgroup();
entry_type_e its_type = _entry->get_type();
major_version_t its_major = _entry->get_major_version();
ttl_t its_ttl = _entry->get_ttl();
- uint16_t its_reserved = _entry->get_reserved();
- uint8_t its_counter = _entry->get_counter();
- bool has_two_options_ = (_entry->get_num_options(1) + _entry->get_num_options(2) >= 2) ? true : false;
+ auto its_info = host_->find_eventgroup(
+ its_service, its_instance, its_eventgroup);
+ if (!its_info) {
+ if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
+ // We received a subscription for a non-existing eventgroup.
+ // --> Create dummy eventgroupinfo to send Nack.
+ its_info = std::make_shared<eventgroupinfo>(its_service, its_instance,
+ its_eventgroup, its_major, its_ttl);
+ boost::system::error_code ec;
+ VSOMEIP_ERROR << __func__
+ << ": Received a SubscribeEventGroup entry for unknown eventgroup "
+ << " from: " << its_sender.to_string(ec) << " for: ["
+ << std::hex << std::setw(4) << std::setfill('0') << its_service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << its_eventgroup
+ << "] session: " << std::hex << std::setw(4) << std::setfill('0')
+ << its_session << ", ttl: " << its_ttl;
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
+ }
+ } else {
+ // We received a subscription [n]ack for an eventgroup that does not exist.
+ // --> Remove subscription.
+ unsubscribe(its_service, its_instance, its_eventgroup, VSOMEIP_ROUTING_CLIENT);
+ }
+ return;
+ }
if (_entry->get_owning_message()->get_return_code() != return_code) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Invalid return code in SD header "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_ERROR << __func__ << ": Invalid return code in SOMEIP/SD header "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
if(its_type == entry_type_e::SUBSCRIBE_EVENTGROUP) {
- if( _destination.is_multicast() ) {
+ if (_destination.is_multicast() ) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Received a SubscribeEventGroup entry on multicast address "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_ERROR << __func__
+ << ": Received a SubscribeEventGroup entry on multicast address "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
if (_entry->get_num_options(1) == 0
&& _entry->get_num_options(2) == 0) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Invalid number of options in SubscribeEventGroup entry "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
+ VSOMEIP_ERROR << __func__
+ << ": Invalid number of options in SubscribeEventGroup entry "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
// increase number of required acks by one as number required acks
// is calculated based on the number of referenced options
- its_message_response->increase_number_required_acks();
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
- if(_entry->get_owning_message()->get_options_length() < 12) {
+ if (_entry->get_owning_message()->get_options_length() < 12) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Invalid options length in SD message "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_ERROR << __func__
+ << ": Invalid options length in SOMEIP/SD message "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
@@ -1987,27 +1665,28 @@ void service_discovery_impl::process_eventgroupentry(
< static_cast<std::vector<std::shared_ptr<option_impl>>::size_type>(
(_entry->get_num_options(1)) + (_entry->get_num_options(2)))) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Fewer options in SD message than "
- "referenced in EventGroup entry or malformed option received "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
+ VSOMEIP_ERROR << __func__
+ << "Fewer options in SOMEIP/SD message than "
+ "referenced in EventGroup entry or malformed option received "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
// set to 0 to ensure an answer containing at least this subscribe_nack is sent out
- its_message_response->set_number_required_acks(0);
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
- if(_entry->get_owning_message()->get_someip_length() < _entry->get_owning_message()->get_length()
+ if (_entry->get_owning_message()->get_someip_length()
+ < _entry->get_owning_message()->get_length()
&& its_ttl > 0) {
boost::system::error_code ec;
- VSOMEIP_ERROR << std::dec << "SomeIP length field in SubscribeEventGroup message header: ["
- << _entry->get_owning_message()->get_someip_length()
- << "] bytes, is shorter than length of deserialized message: ["
- << (uint32_t) _entry->get_owning_message()->get_length() << "] bytes. "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": SOME/IP length field in SubscribeEventGroup message header: ["
+ << std::dec << _entry->get_owning_message()->get_someip_length()
+ << "] bytes, is shorter than length of deserialized message: ["
+ << (uint32_t) _entry->get_owning_message()->get_length() << "] bytes. "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
}
@@ -2018,6 +1697,7 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address its_second_address;
uint16_t its_second_port(ILLEGAL_PORT);
bool is_second_reliable(false);
+ std::set<client_t> its_clients({0}); // maybe overridden for selectives
for (auto i : { 1, 2 }) {
for (auto its_index : _entry->get_options(uint8_t(i))) {
@@ -2026,21 +1706,19 @@ void service_discovery_impl::process_eventgroupentry(
its_option = _options.at(its_index);
} catch(const std::out_of_range& e) {
#ifdef _WIN32
- e; // silence MSVC warining C4101
+ e; // silence MSVC warning C4101
#endif
boost::system::error_code ec;
- VSOMEIP_ERROR << "Fewer options in SD message than "
- "referenced in EventGroup entry for "
- "option run number: " << i << " "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0')
- << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Fewer options in SD message than "
+ "referenced in EventGroup entry for "
+ "option run number: "
+ << i << " "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0')
+ << its_session;
if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type && its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
@@ -2054,12 +1732,8 @@ void service_discovery_impl::process_eventgroupentry(
boost::asio::ip::address_v4 its_ipv4_address(
its_ipv4_option->get_address());
if (!check_layer_four_protocol(its_ipv4_option)) {
- if( its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
return;
}
@@ -2075,33 +1749,27 @@ void service_discovery_impl::process_eventgroupentry(
if (is_first_reliable == is_second_reliable
&& its_second_port != ILLEGAL_PORT) {
if (its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv4 endpoint options of same kind referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_
+ VSOMEIP_ERROR << __func__
+ << ": Multiple IPv4 endpoint options of same kind referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session
<< " is_first_reliable: " << is_first_reliable;
return;
}
- if(!check_ipv4_address(its_first_address)
+ if (!check_ipv4_address(its_first_address)
|| 0 == its_first_port) {
- if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Invalid port or IP address in first IPv4 endpoint option specified! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid port or IP address in first IPv4 endpoint option specified! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
} else
@@ -2116,33 +1784,27 @@ void service_discovery_impl::process_eventgroupentry(
if (is_second_reliable == is_first_reliable
&& its_first_port != ILLEGAL_PORT) {
if (its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv4 endpoint options of same kind referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_
+ VSOMEIP_ERROR << __func__
+ << ": Multiple IPv4 endpoint options of same kind referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session
<< " is_second_reliable: " << is_second_reliable;
return;
}
- if(!check_ipv4_address(its_second_address)
+ if (!check_ipv4_address(its_second_address)
|| 0 == its_second_port) {
- if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Invalid port or IP address in second IPv4 endpoint option specified! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid port or IP address in second IPv4 endpoint option specified! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
} else {
@@ -2150,10 +1812,10 @@ void service_discovery_impl::process_eventgroupentry(
}
} else {
boost::system::error_code ec;
- VSOMEIP_ERROR
- << "Invalid eventgroup option (IPv4 Endpoint)"
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid eventgroup option (IPv4 Endpoint)"
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
}
break;
}
@@ -2167,16 +1829,12 @@ void service_discovery_impl::process_eventgroupentry(
its_ipv6_option->get_address());
if (!check_layer_four_protocol(its_ipv6_option)) {
if(its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
VSOMEIP_ERROR << "Invalid layer 4 protocol type in IPv6 endpoint option specified! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
@@ -2189,16 +1847,13 @@ void service_discovery_impl::process_eventgroupentry(
if (is_first_reliable == is_second_reliable
&& its_second_port != ILLEGAL_PORT) {
if (its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv6 endpoint options of same kind referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_
+ VSOMEIP_ERROR << __func__
+ << ": Multiple IPv6 endpoint options of same kind referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session
<< " is_first_reliable: " << is_first_reliable;
return;
}
@@ -2212,16 +1867,13 @@ void service_discovery_impl::process_eventgroupentry(
if (is_second_reliable == is_first_reliable
&& its_first_port != ILLEGAL_PORT) {
if (its_ttl > 0) {
- if (has_two_options_) {
- its_message_response->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ insert_subscription_ack(_acknowledgement, its_info, 0);
}
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv6 endpoint options of same kind referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_
+ VSOMEIP_ERROR << __func__
+ << ": Multiple IPv6 endpoint options of same kind referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session
<< " is_second_reliable: " << is_second_reliable;
return;
}
@@ -2230,10 +1882,10 @@ void service_discovery_impl::process_eventgroupentry(
}
} else {
boost::system::error_code ec;
- VSOMEIP_ERROR
- << "Invalid eventgroup option (IPv6 Endpoint) "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid eventgroup option (IPv6 Endpoint) "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
}
break;
}
@@ -2260,17 +1912,18 @@ void service_discovery_impl::process_eventgroupentry(
if (its_first_port != ILLEGAL_PORT
&& its_second_port != ILLEGAL_PORT) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv4 multicast options referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Multiple IPv4 multicast options referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
} else {
boost::system::error_code ec;
- VSOMEIP_ERROR
- << "Invalid eventgroup option (IPv4 Multicast) "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid eventgroup option (IPv4 Multicast) "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
}
break;
case option_type_e::IP6_MULTICAST:
@@ -2296,33 +1949,41 @@ void service_discovery_impl::process_eventgroupentry(
if (its_first_port != ILLEGAL_PORT
&& its_second_port != ILLEGAL_PORT) {
boost::system::error_code ec;
- VSOMEIP_ERROR << "Multiple IPv6 multicast options referenced! "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << "Multiple IPv6 multicast options referenced! "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
return;
}
} else {
boost::system::error_code ec;
- VSOMEIP_ERROR
- << "Invalid eventgroup option (IPv6 Multicast) "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
+ VSOMEIP_ERROR << __func__
+ << ": Invalid eventgroup option (IPv6 Multicast) "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
}
break;
case option_type_e::CONFIGURATION: {
- its_message_response->decrease_number_required_acks();
+ break;
+ }
+ case option_type_e::SELECTIVE: {
+ auto its_selective_option
+ = std::dynamic_pointer_cast<selective_option_impl>(its_option);
+ if (its_selective_option) {
+ its_clients = its_selective_option->get_clients();
+ }
break;
}
case option_type_e::UNKNOWN:
default:
boost::system::error_code ec;
- VSOMEIP_WARNING << "Unsupported eventgroup option "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if(its_ttl > 0) {
- its_message_response->decrease_number_required_acks();
- insert_subscription_nack(its_message_response, its_service, its_instance,
- its_eventgroup, its_counter, its_major, its_reserved);
+ VSOMEIP_WARNING << __func__
+ << ": Unsupported eventgroup option ["
+ << std::hex << (int)its_option->get_type() << "] "
+ << its_sender.to_string(ec) << " session: "
+ << std::hex << std::setw(4) << std::setfill('0') << its_session;
+ if (its_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
return;
}
break;
@@ -2332,256 +1993,225 @@ void service_discovery_impl::process_eventgroupentry(
if (entry_type_e::SUBSCRIBE_EVENTGROUP == its_type) {
handle_eventgroup_subscription(its_service, its_instance,
- its_eventgroup, its_major, its_ttl, its_counter, its_reserved,
+ its_eventgroup, its_major, its_ttl, 0, 0,
its_first_address, its_first_port, is_first_reliable,
- its_second_address, its_second_port, is_second_reliable, its_message_response,
- _message_id, _is_stop_subscribe_subscribe, _force_initial_events);
+ its_second_address, its_second_port, is_second_reliable,
+ _acknowledgement, _is_stop_subscribe_subscribe,
+ _force_initial_events, its_clients, its_info);
} else {
- if( entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { //this type is used for ACK and NACK messages
- if(its_ttl > 0) {
+ if (entry_type_e::SUBSCRIBE_EVENTGROUP_ACK == its_type) { //this type is used for ACK and NACK messages
+ if (its_ttl > 0) {
handle_eventgroup_subscription_ack(its_service, its_instance,
- its_eventgroup, its_major, its_ttl, its_counter,
+ its_eventgroup, its_major, its_ttl, 0,
+ its_clients,
its_first_address, its_first_port);
} else {
- handle_eventgroup_subscription_nack(its_service, its_instance, its_eventgroup, its_counter);
+ handle_eventgroup_subscription_nack(its_service, its_instance, its_eventgroup,
+ 0, its_clients);
}
}
}
}
-void service_discovery_impl::handle_eventgroup_subscription(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, major_version_t _major,
+void
+service_discovery_impl::handle_eventgroup_subscription(
+ service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major,
ttl_t _ttl, uint8_t _counter, uint16_t _reserved,
- const boost::asio::ip::address &_first_address, uint16_t _first_port, bool _is_first_reliable,
- const boost::asio::ip::address &_second_address, uint16_t _second_port, bool _is_second_reliable,
- std::shared_ptr < message_impl > &its_message,
- const std::shared_ptr<sd_message_identifier_t> &_message_id,
- bool _is_stop_subscribe_subscribe, bool _force_initial_events) {
-
- if (its_message) {
- bool has_reliable_events(false);
- bool has_unreliable_events(false);
- bool has_two_options_ = (_first_port != ILLEGAL_PORT && _second_port != ILLEGAL_PORT) ? true : false;
- auto its_eventgroup = host_->find_eventgroup(_service, _instance, _eventgroup);
- if (its_eventgroup) {
- its_eventgroup->get_reliability(has_reliable_events, has_unreliable_events);
+ const boost::asio::ip::address &_first_address, uint16_t _first_port,
+ bool _is_first_reliable,
+ const boost::asio::ip::address &_second_address, uint16_t _second_port,
+ bool _is_second_reliable,
+ std::shared_ptr<remote_subscription_ack> &_acknowledgement,
+ bool _is_stop_subscribe_subscribe, bool _force_initial_events,
+ const std::set<client_t> &_clients,
+ const std::shared_ptr<eventgroupinfo>& _info) {
+ (void)_counter;
+ (void)_reserved;
+
+ auto its_messages = _acknowledgement->get_messages();
+
+#ifndef VSOMEIP_ENABLE_COMPAT
+ bool reliablility_nack(false);
+ if (_info) {
+ const bool first_port_set(_first_port != ILLEGAL_PORT);
+ const bool second_port_set(_second_port != ILLEGAL_PORT);
+ switch (_info->get_reliability()) {
+ case reliability_type_e::RT_UNRELIABLE:
+ if (!(first_port_set && !_is_first_reliable)
+ && !(second_port_set && !_is_second_reliable)) {
+ reliablility_nack = true;
+ }
+ break;
+ case reliability_type_e::RT_RELIABLE:
+ if (!(first_port_set && _is_first_reliable)
+ && !(second_port_set && _is_second_reliable)) {
+ reliablility_nack = true;
+ }
+ break;
+ case reliability_type_e::RT_BOTH:
+ if (_first_port == ILLEGAL_PORT || _second_port == ILLEGAL_PORT) {
+ reliablility_nack = true;
+ }
+ if (_is_first_reliable == _is_second_reliable) {
+ reliablility_nack = true;
+ }
+ break;
+ default:
+ break;
}
+ }
+ if (reliablility_nack && _ttl > 0) {
+ insert_subscription_ack(_acknowledgement, _info, 0);
+ boost::system::error_code ec;
+ // TODO: Add sender and session id
+ VSOMEIP_WARNING << __func__
+ << ": Subscription for ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
+ << " not valid: Event configuration ("
+ << (std::uint32_t)_info->get_reliability()
+ << ") does not match the provided endpoint options: "
+ << _first_address.to_string(ec) << ":" << std::dec << _first_port << " "
+ << _second_address.to_string(ec) << ":" << std::dec << _second_port;
- bool reliablility_nack(false);
- if (has_reliable_events && !has_unreliable_events) {
- if (!(_first_port != ILLEGAL_PORT && _is_first_reliable) &&
- !(_second_port != ILLEGAL_PORT && _is_second_reliable)) {
- reliablility_nack = true;
- }
- } else if (!has_reliable_events && has_unreliable_events) {
- if (!(_first_port != ILLEGAL_PORT && !_is_first_reliable) &&
- !(_second_port != ILLEGAL_PORT && !_is_second_reliable)) {
- reliablility_nack = true;
- }
- } else if (has_reliable_events && has_unreliable_events) {
- if (_first_port == ILLEGAL_PORT || _second_port == ILLEGAL_PORT) {
- reliablility_nack = true;
- }
- if (_is_first_reliable == _is_second_reliable) {
- reliablility_nack = true;
- }
- }
- if (reliablility_nack && _ttl > 0) {
- if (has_two_options_) {
- its_message->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message, _service, _instance,
- _eventgroup, _counter, _major, _reserved);
- boost::system::error_code ec;
- VSOMEIP_WARNING << "Subscription for ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " not valid: Event configuration does not match the provided "
- << "endpoint options: "
- << _first_address.to_string(ec) << ":" << std::dec << _first_port << " "
- << _second_address.to_string(ec) << ":" << std::dec << _second_port
- << " " << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- return;
- }
+ return;
+ }
- std::shared_ptr < eventgroupinfo > its_info = host_->find_eventgroup(
- _service, _instance, _eventgroup);
+#endif
- struct subscriber_target_t {
- std::shared_ptr<endpoint_definition> subscriber_;
- std::shared_ptr<endpoint_definition> target_;
- };
- std::array<subscriber_target_t, 2> its_targets =
- { subscriber_target_t(), subscriber_target_t() };
- // Could not find eventgroup or wrong version
- if (!its_info || _major != its_info->get_major()) {
- // Create a temporary info object with TTL=0 --> send NACK
- if( its_info && (_major != its_info->get_major())) {
- boost::system::error_code ec;
- VSOMEIP_ERROR << "Requested major version:[" << (uint32_t) _major
- << "] in subscription to service: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
- << " does not match with services major version:[" << (uint32_t) its_info->get_major()
- << "] " << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- } else {
- VSOMEIP_ERROR << "Requested eventgroup:[" << _eventgroup
- << "] not found for subscription to service:["
- << _service << "] instance:[" << _instance << "]";
- }
- its_info = std::make_shared < eventgroupinfo > (_major, 0);
- if(_ttl > 0) {
- if (has_two_options_) {
- its_message->decrease_number_required_acks();
- }
- insert_subscription_nack(its_message, _service, _instance,
- _eventgroup, _counter, _major, _reserved);
- }
- return;
- } else {
- boost::asio::ip::address its_first_address, its_second_address;
- uint16_t its_first_port, its_second_port;
- if (ILLEGAL_PORT != _first_port) {
- its_targets[0].subscriber_ = endpoint_definition::get(
- _first_address, _first_port, _is_first_reliable, _service, _instance);
- if (!_is_first_reliable &&
- its_info->get_multicast(its_first_address, its_first_port)) { // udp multicast
- its_targets[0].target_ = endpoint_definition::get(
- its_first_address, its_first_port, false, _service, _instance);
- } else if(_is_first_reliable) { // tcp unicast
- its_targets[0].target_ = its_targets[0].subscriber_;
- // check if TCP connection is established by client
- if(_ttl > 0 && !is_tcp_connected(_service, _instance, its_targets[0].target_)) {
- insert_subscription_nack(its_message, _service, _instance,
- _eventgroup, _counter, _major, _reserved);
- boost::system::error_code ec;
- VSOMEIP_ERROR << "TCP connection to target1: ["
- << its_targets[0].target_->get_address().to_string()
- << ":" << its_targets[0].target_->get_port()
- << "] not established for subscription to: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if (has_two_options_) {
- its_message->decrease_number_required_acks();
- }
- return;
- }
- } else { // udp unicast
- its_targets[0].target_ = its_targets[0].subscriber_;
+ std::shared_ptr<endpoint_definition> its_subscriber;
+ std::shared_ptr<endpoint_definition> its_reliable;
+ std::shared_ptr<endpoint_definition> its_unreliable;
+
+ // wrong major version
+ if (_major != _info->get_major()) {
+ // Create a temporary info object with TTL=0 --> send NACK
+ auto its_info = std::make_shared<eventgroupinfo>(_service, _instance,
+ _eventgroup, _major, 0);
+ boost::system::error_code ec;
+ // TODO: Add session id
+ VSOMEIP_ERROR << __func__
+ << ": Requested major version:[" << (uint32_t) _major
+ << "] in subscription to service: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "]"
+ << " does not match with services major version:["
+ << (uint32_t) _info->get_major() << "] subscriber: "
+ << _first_address.to_string(ec) << ":" << std::dec << _first_port;
+ if (_ttl > 0) {
+ insert_subscription_ack(_acknowledgement, its_info, 0);
+ }
+ return;
+ } else {
+ boost::asio::ip::address its_first_address, its_second_address;
+ uint16_t its_first_port, its_second_port;
+ if (ILLEGAL_PORT != _first_port) {
+ its_subscriber = endpoint_definition::get(
+ _first_address, _first_port, _is_first_reliable, _service, _instance);
+ if (!_is_first_reliable &&
+ _info->get_multicast(its_first_address, its_first_port) &&
+ _info->is_sending_multicast()) { // udp multicast
+ its_unreliable = endpoint_definition::get(
+ its_first_address, its_first_port, false, _service, _instance);
+ } else if (_is_first_reliable) { // tcp unicast
+ its_reliable = its_subscriber;
+ // check if TCP connection is established by client
+ if (_ttl > 0 && !is_tcp_connected(_service, _instance, its_reliable)) {
+ insert_subscription_ack(_acknowledgement, _info, 0);
+ boost::system::error_code ec;
+ // TODO: Add sender and session id
+ VSOMEIP_ERROR << "TCP connection to target1: ["
+ << its_reliable->get_address().to_string()
+ << ":" << its_reliable->get_port()
+ << "] not established for subscription to: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] ";
+ return;
}
- }
- if (ILLEGAL_PORT != _second_port) {
- its_targets[1].subscriber_ = endpoint_definition::get(
- _second_address, _second_port, _is_second_reliable, _service, _instance);
- if (!_is_second_reliable &&
- its_info->get_multicast(its_second_address, its_second_port)) { // udp multicast
- its_targets[1].target_ = endpoint_definition::get(
- its_second_address, its_second_port, false, _service, _instance);
- } else if (_is_second_reliable) { // tcp unicast
- its_targets[1].target_ = its_targets[1].subscriber_;
- // check if TCP connection is established by client
- if(_ttl > 0 && !is_tcp_connected(_service, _instance, its_targets[1].target_)) {
- insert_subscription_nack(its_message, _service, _instance,
- _eventgroup, _counter, _major, _reserved);
- boost::system::error_code ec;
- VSOMEIP_ERROR << "TCP connection to target2 : ["
- << its_targets[1].target_->get_address().to_string()
- << ":" << its_targets[1].target_->get_port()
- << "] not established for subscription to: ["
- << std::hex << std::setw(4) << std::setfill('0') << _service << "."
- << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
- << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] "
- << _message_id->sender_.to_string(ec) << " session: "
- << std::hex << std::setw(4) << std::setfill('0') << _message_id->session_;
- if (has_two_options_) {
- its_message->decrease_number_required_acks();
- }
- return;
- }
- } else { // udp unicast
- its_targets[1].target_ = its_targets[1].subscriber_;
+ } else { // udp unicast
+ its_unreliable = its_subscriber;
+ }
+ }
+
+ if (ILLEGAL_PORT != _second_port) {
+ its_subscriber = endpoint_definition::get(
+ _second_address, _second_port, _is_second_reliable, _service, _instance);
+ if (!_is_second_reliable &&
+ _info->get_multicast(its_second_address, its_second_port) &&
+ _info->is_sending_multicast()) { // udp multicast
+ its_unreliable = endpoint_definition::get(
+ its_second_address, its_second_port, false, _service, _instance);
+ } else if (_is_second_reliable) { // tcp unicast
+ its_reliable = its_subscriber;
+ // check if TCP connection is established by client
+ if (_ttl > 0 && !is_tcp_connected(_service, _instance, its_reliable)) {
+ insert_subscription_ack(_acknowledgement, _info, 0);
+ boost::system::error_code ec;
+ // TODO: Add sender and session id
+ VSOMEIP_ERROR << "TCP connection to target2 : ["
+ << its_reliable->get_address().to_string()
+ << ":" << its_reliable->get_port()
+ << "] not established for subscription to: ["
+ << std::hex << std::setw(4) << std::setfill('0') << _service << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _instance << "."
+ << std::hex << std::setw(4) << std::setfill('0') << _eventgroup << "] ";
+ return;
}
+ } else { // udp unicast
+ its_unreliable = its_subscriber;
}
}
+ }
- if (_ttl == 0) { // --> unsubscribe
- for (const auto &target : its_targets) {
- if (target.subscriber_) {
- if (!_is_stop_subscribe_subscribe) {
- host_->on_unsubscribe(_service, _instance, _eventgroup, target.subscriber_);
- }
- }
+ // Create subscription object
+ auto its_subscription = std::make_shared<remote_subscription>();
+ its_subscription->set_eventgroupinfo(_info);
+ its_subscription->reset(_clients);
+
+ if (_ttl == 0) { // --> unsubscribe
+ its_subscription->set_ttl(0);
+ if (!_is_stop_subscribe_subscribe) {
+ {
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ pending_remote_subscriptions_[its_subscription] = _acknowledgement;
+ _acknowledgement->add_subscription(its_subscription);
}
- return;
+ host_->on_remote_unsubscribe(its_subscription);
}
+ return;
+ }
- for (const auto &target : its_targets) {
- if (!target.target_) {
- continue;
- }
- host_->on_remote_subscription(_service, _instance,
- _eventgroup, target.subscriber_, target.target_,
- _ttl * get_ttl_factor(_service, _instance, ttl_factor_subscriptions_),
- _message_id,
- [&](remote_subscription_state_e _rss, client_t _subscribing_remote_client) {
- switch (_rss) {
- case remote_subscription_state_e::SUBSCRIPTION_ACKED:
- insert_subscription_ack(its_message, _service,
- _instance, _eventgroup, its_info, _ttl,
- _counter, _major, _reserved);
- if (_force_initial_events) {
- // processing subscription of StopSubscribe/Subscribe
- // sequence
- its_message->forced_initial_events_add(
- message_impl::forced_initial_events_t(
- { target.subscriber_, _service, _instance,
- _eventgroup }));
- }
- break;
- case remote_subscription_state_e::SUBSCRIPTION_NACKED:
- case remote_subscription_state_e::SUBSCRIPTION_ERROR:
- insert_subscription_nack(its_message, _service,
- _instance, _eventgroup, _counter, _major,
- _reserved);
- break;
- case remote_subscription_state_e::SUBSCRIPTION_PENDING:
- if (target.target_ && target.subscriber_) {
- std::shared_ptr<subscriber_t> subscriber_ =
- std::make_shared<subscriber_t>();
- subscriber_->subscriber = target.subscriber_;
- subscriber_->target = target.target_;
- subscriber_->response_message_id_ = _message_id;
- subscriber_->eventgroupinfo_ = its_info;
- subscriber_->ttl_ = _ttl;
- subscriber_->major_ = _major;
- subscriber_->reserved_ = _reserved;
- subscriber_->counter_ = _counter;
-
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- pending_remote_subscriptions_[_service]
- [_instance]
- [_eventgroup]
- [_subscribing_remote_client].push_back(subscriber_);
- }
- default:
- break;
- }
- });
- }
+ if (_force_initial_events) {
+ its_subscription->set_force_initial_events(true);
+ }
+ its_subscription->set_subscriber(its_subscriber);
+ its_subscription->set_reliable(its_reliable);
+ its_subscription->set_unreliable(its_unreliable);
+ its_subscription->set_ttl(_ttl
+ * get_ttl_factor(_service, _instance, ttl_factor_subscriptions_));
+
+ {
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ pending_remote_subscriptions_[its_subscription] = _acknowledgement;
+ _acknowledgement->add_subscription(its_subscription);
}
+
+ host_->on_remote_subscribe(its_subscription,
+ std::bind(&service_discovery_impl::update_remote_subscription,
+ shared_from_this(), std::placeholders::_1));
}
-void service_discovery_impl::handle_eventgroup_subscription_nack(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, uint8_t _counter) {
- client_t nackedClient = 0;
+void
+service_discovery_impl::handle_eventgroup_subscription_nack(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ uint8_t _counter, const std::set<client_t> &_clients) {
+ (void)_counter;
+
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
@@ -2589,42 +2219,34 @@ void service_discovery_impl::handle_eventgroup_subscription_nack(service_t _serv
if (found_instance != found_service->second.end()) {
auto found_eventgroup = found_instance->second.find(_eventgroup);
if (found_eventgroup != found_instance->second.end()) {
- for (auto client : found_eventgroup->second) {
- if (client.second->get_counter() == _counter) {
- // Deliver nack
- nackedClient = client.first;
- host_->on_subscribe_nack(client.first, _service,
- _instance, _eventgroup, ANY_EVENT, DEFAULT_SUBSCRIPTION);
- break;
- }
+ auto its_subscription = found_eventgroup->second;
+ for (const auto its_client : _clients) {
+ host_->on_subscribe_nack(its_client,
+ _service, _instance, _eventgroup, ANY_EVENT,
+ PENDING_SUBSCRIPTION_ID); // TODO: This is a dummy call...
}
- // Restart TCP connection only for non selective subscriptions
- for (auto client : found_eventgroup->second) {
- if( !client.second->is_acknowledged()
- && client.first == VSOMEIP_ROUTING_CLIENT ) {
- auto endpoint = client.second->get_endpoint(true);
- if(endpoint) {
- endpoint->restart();
- }
- }
- }
- // Remove nacked subscription only for selective events
- if(nackedClient != VSOMEIP_ROUTING_CLIENT) {
- found_eventgroup->second.erase(nackedClient);
+ if (!its_subscription->is_selective()) {
+ auto its_reliable = its_subscription->get_endpoint(true);
+ if (its_reliable)
+ its_reliable->restart();
}
}
}
}
}
-void service_discovery_impl::handle_eventgroup_subscription_ack(
+void
+service_discovery_impl::handle_eventgroup_subscription_ack(
service_t _service, instance_t _instance, eventgroup_t _eventgroup,
major_version_t _major, ttl_t _ttl, uint8_t _counter,
+ const std::set<client_t> &_clients,
const boost::asio::ip::address &_address, uint16_t _port) {
(void)_major;
(void)_ttl;
+ (void)_counter;
+
std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
auto found_service = subscribed_.find(_service);
if (found_service != subscribed_.end()) {
@@ -2632,17 +2254,20 @@ void service_discovery_impl::handle_eventgroup_subscription_ack(
if (found_instance != found_service->second.end()) {
auto found_eventgroup = found_instance->second.find(_eventgroup);
if (found_eventgroup != found_instance->second.end()) {
- for (auto its_client : found_eventgroup->second) {
- if (its_client.second->get_counter() == _counter) {
- its_client.second->set_acknowledged(true);
- host_->on_subscribe_ack(its_client.first, _service,
- _instance, _eventgroup, ANY_EVENT, DEFAULT_SUBSCRIPTION);
- }
- if (_address.is_multicast()) {
- host_->on_subscribe_ack(_service, _instance, _address,
- _port);
+ for (const auto its_client : _clients) {
+ if (found_eventgroup->second->get_state(its_client)
+ == subscription_state_e::ST_NOT_ACKNOWLEDGED) {
+ found_eventgroup->second->set_state(its_client,
+ subscription_state_e::ST_ACKNOWLEDGED);
+ host_->on_subscribe_ack(its_client,
+ _service, _instance, _eventgroup,
+ ANY_EVENT, PENDING_SUBSCRIPTION_ID);
}
}
+ if (_address.is_multicast()) {
+ host_->on_subscribe_ack_with_multicast(
+ _service, _instance, _address, _port);
+ }
}
}
}
@@ -2650,7 +2275,7 @@ void service_discovery_impl::handle_eventgroup_subscription_ack(
bool service_discovery_impl::is_tcp_connected(service_t _service,
instance_t _instance,
- std::shared_ptr<vsomeip::endpoint_definition> its_endpoint) {
+ const std::shared_ptr<endpoint_definition>& its_endpoint) {
bool is_connected = false;
std::shared_ptr<serviceinfo> its_info = host_->get_offered_service(_service,
_instance);
@@ -2666,28 +2291,62 @@ bool service_discovery_impl::is_tcp_connected(service_t _service,
return is_connected;
}
-void service_discovery_impl::serialize_and_send(
- std::shared_ptr<message_impl> _message,
- const boost::asio::ip::address &_address) {
+bool
+service_discovery_impl::send(
+ const std::vector<std::shared_ptr<message_impl> > &_messages) {
+ bool its_result(true);
std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- std::pair<session_t, bool> its_session = get_session(_address);
- _message->set_session(its_session.first);
- _message->set_reboot_flag(its_session.second);
- if(!serializer_->serialize(_message.get())) {
- boost::system::error_code ec;
- VSOMEIP_ERROR << "service_discovery_impl::serialize_and_send: serialization error."
- << " Remote: " << _address.to_string(ec) << " session: 0x"
- << std::hex << its_session.first;
- return;
+ for (const auto &m : _messages) {
+ if (m->has_entry()) {
+ std::pair<session_t, bool> its_session = get_session(unicast_);
+ m->set_session(its_session.first);
+ m->set_reboot_flag(its_session.second);
+ if (host_->send(VSOMEIP_SD_CLIENT, m)) {
+ increment_session(unicast_);
+ }
+ } else {
+ its_result = false;
+ }
}
- if (host_->send_to(endpoint_definition::get(_address, port_, reliable_, _message->get_service(), _message->get_instance()),
- serializer_->get_data(), serializer_->get_size(), port_)) {
- increment_session(_address);
+ return its_result;
+}
+
+bool
+service_discovery_impl::serialize_and_send(
+ const std::vector<std::shared_ptr<message_impl> > &_messages,
+ const boost::asio::ip::address &_address) {
+ bool its_result(true);
+ if (!_address.is_unspecified()) {
+ std::lock_guard<std::mutex> its_lock(serialize_mutex_);
+ for (const auto &m : _messages) {
+ if (m->has_entry()) {
+ std::pair<session_t, bool> its_session = get_session(_address);
+ m->set_session(its_session.first);
+ m->set_reboot_flag(its_session.second);
+
+ if (serializer_->serialize(m.get())) {
+ if (host_->send_via_sd(endpoint_definition::get(_address, port_,
+ reliable_, m->get_service(), m->get_instance()),
+ serializer_->get_data(), serializer_->get_size(),
+ port_)) {
+ increment_session(_address);
+ }
+ } else {
+ VSOMEIP_ERROR << "service_discovery_impl::" << __func__
+ << ": Serialization failed!";
+ its_result = false;
+ }
+ serializer_->reset();
+ } else {
+ its_result = false;
+ }
+ }
}
- serializer_->reset();
+ return its_result;
}
-void service_discovery_impl::start_ttl_timer() {
+void
+service_discovery_impl::start_ttl_timer() {
std::lock_guard<std::mutex> its_lock(ttl_timer_mutex_);
boost::system::error_code ec;
ttl_timer_.expires_from_now(std::chrono::milliseconds(ttl_timer_runtime_), ec);
@@ -2696,13 +2355,15 @@ void service_discovery_impl::start_ttl_timer() {
std::placeholders::_1));
}
-void service_discovery_impl::stop_ttl_timer() {
+void
+service_discovery_impl::stop_ttl_timer() {
std::lock_guard<std::mutex> its_lock(ttl_timer_mutex_);
boost::system::error_code ec;
ttl_timer_.cancel(ec);
}
-void service_discovery_impl::check_ttl(const boost::system::error_code &_error) {
+void
+service_discovery_impl::check_ttl(const boost::system::error_code &_error) {
if (!_error) {
{
std::lock_guard<std::mutex> its_lock(check_ttl_mutex_);
@@ -2712,7 +2373,8 @@ void service_discovery_impl::check_ttl(const boost::system::error_code &_error)
}
}
-bool service_discovery_impl::check_static_header_fields(
+bool
+service_discovery_impl::check_static_header_fields(
const std::shared_ptr<const message> &_message) const {
if(_message->get_protocol_version() != protocol_version) {
VSOMEIP_ERROR << "Invalid protocol version in SD header";
@@ -2734,8 +2396,9 @@ bool service_discovery_impl::check_static_header_fields(
return true;
}
-bool service_discovery_impl::check_layer_four_protocol(
- const std::shared_ptr<const ip_option_impl> _ip_option) const {
+bool
+service_discovery_impl::check_layer_four_protocol(
+ const std::shared_ptr<const ip_option_impl>& _ip_option) const {
if (_ip_option->get_layer_four_protocol() == layer_four_protocol_e::UNKNOWN) {
VSOMEIP_ERROR << "Invalid layer 4 protocol in IP endpoint option";
return false;
@@ -2743,119 +2406,14 @@ bool service_discovery_impl::check_layer_four_protocol(
return true;
}
-void service_discovery_impl::send_subscriptions(service_t _service, instance_t _instance,
- client_t _client, bool _reliable) {
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (!its_runtime) {
- return;
- }
- std::forward_list<std::pair<std::shared_ptr<message_impl>,
- const boost::asio::ip::address>> subscription_messages;
- {
- std::lock_guard<std::mutex> its_lock(subscribed_mutex_);
- auto found_service = subscribed_.find(_service);
- if (found_service != subscribed_.end()) {
- auto found_instance = found_service->second.find(_instance);
- if (found_instance != found_service->second.end()) {
- const remote_offer_type_e its_offer_type =
- get_remote_offer_type(_service, _instance);
- for (auto found_eventgroup : found_instance->second) {
- auto found_client = found_eventgroup.second.find(_client);
- if (found_client != found_eventgroup.second.end()) {
- std::shared_ptr<endpoint> its_unreliable;
- std::shared_ptr<endpoint> its_reliable;
- bool has_address(false);
- boost::asio::ip::address its_address;
- get_subscription_endpoints(
- its_unreliable, its_reliable, &its_address,
- &has_address, _service, _instance,
- found_client->first);
- std::shared_ptr<endpoint> endpoint;
- if (_reliable) {
- endpoint = its_reliable;
- found_client->second->set_endpoint(its_reliable, true);
- if (its_unreliable &&
- !host_->has_identified(found_client->first, _service, _instance, false)) {
- return;
- }
- } else {
- endpoint = its_unreliable;
- found_client->second->set_endpoint(its_unreliable, false);
- if (its_reliable &&
- !host_->has_identified(found_client->first, _service, _instance, true)) {
- return;
- }
- }
- if (endpoint) {
- if (!has_address) {
- VSOMEIP_WARNING << "service_discovery_impl::"
- "send_subscriptions couldn't determine "
- "address for service.instance: "
- << std::hex << std::setw(4) << std::setfill('0')
- << _service << "." << _instance;
- continue;
- }
- std::shared_ptr<message_impl> its_message
- = its_runtime->create_message();
-
- if (its_reliable && its_unreliable) {
- if (its_reliable->is_established() && its_unreliable->is_established()) {
- insert_subscription(its_message, _service,
- _instance, found_eventgroup.first,
- found_client->second, its_offer_type);
- found_client->second->set_tcp_connection_established(true);
- found_client->second->set_udp_connection_established(true);
- } else {
- found_client->second->set_tcp_connection_established(false);
- found_client->second->set_udp_connection_established(false);
- }
- } else {
- if(_reliable) {
- if(endpoint->is_established()) {
- insert_subscription(its_message, _service,
- _instance, found_eventgroup.first,
- found_client->second, its_offer_type);
- found_client->second->set_tcp_connection_established(true);
- } else {
- // don't insert reliable endpoint option if the
- // TCP client endpoint is not yet connected
- found_client->second->set_tcp_connection_established(false);
- }
- } else {
- if (endpoint->is_established()) {
- insert_subscription(its_message, _service,
- _instance, found_eventgroup.first,
- found_client->second, its_offer_type);
- found_client->second->set_udp_connection_established(true);
- } else {
- // don't insert unreliable endpoint option if the
- // UDP client endpoint is not yet connected
- found_client->second->set_udp_connection_established(false);
- }
- }
- }
- if (its_message->get_entries().size()
- && its_message->get_options().size()) {
- subscription_messages.push_front({its_message, its_address});
- found_client->second->set_acknowledged(false);
- }
- }
- }
- }
- }
- }
- }
- for (const auto s : subscription_messages) {
- serialize_and_send(s.first, s.second);
- }
-}
-
-void service_discovery_impl::start_subscription_expiration_timer() {
+void
+service_discovery_impl::start_subscription_expiration_timer() {
std::lock_guard<std::mutex> its_lock(subscription_expiration_timer_mutex_);
start_subscription_expiration_timer_unlocked();
}
-void service_discovery_impl::start_subscription_expiration_timer_unlocked() {
+void
+service_discovery_impl::start_subscription_expiration_timer_unlocked() {
subscription_expiration_timer_.expires_at(next_subscription_expiration_);
subscription_expiration_timer_.async_wait(
std::bind(&service_discovery_impl::expire_subscriptions,
@@ -2863,23 +2421,28 @@ void service_discovery_impl::start_subscription_expiration_timer_unlocked() {
std::placeholders::_1));
}
-void service_discovery_impl::stop_subscription_expiration_timer() {
+void
+service_discovery_impl::stop_subscription_expiration_timer() {
std::lock_guard<std::mutex> its_lock(subscription_expiration_timer_mutex_);
stop_subscription_expiration_timer_unlocked();
}
-void service_discovery_impl::stop_subscription_expiration_timer_unlocked() {
+void
+service_discovery_impl::stop_subscription_expiration_timer_unlocked() {
subscription_expiration_timer_.cancel();
}
-void service_discovery_impl::expire_subscriptions(const boost::system::error_code &_error) {
+void
+service_discovery_impl::expire_subscriptions(
+ const boost::system::error_code &_error) {
if (!_error) {
next_subscription_expiration_ = host_->expire_subscriptions(false);
start_subscription_expiration_timer();
}
}
-bool service_discovery_impl::check_ipv4_address(
+bool
+service_discovery_impl::check_ipv4_address(
const boost::asio::ip::address& its_address) const {
//Check unallowed ipv4 address
bool is_valid = true;
@@ -2912,25 +2475,28 @@ bool service_discovery_impl::check_ipv4_address(
return is_valid;
}
-void service_discovery_impl::offer_service(service_t _service,
- instance_t _instance,
- std::shared_ptr<serviceinfo> _info) {
+void
+service_discovery_impl::offer_service(const std::shared_ptr<serviceinfo> &_info) {
+ service_t its_service = _info->get_service();
+ service_t its_instance = _info->get_instance();
+
std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
// check if offer is in map
bool found(false);
- const auto its_service = collected_offers_.find(_service);
- if (its_service != collected_offers_.end()) {
- const auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
+ const auto its_service_it = collected_offers_.find(its_service);
+ if (its_service_it != collected_offers_.end()) {
+ const auto its_instance_it = its_service_it->second.find(its_instance);
+ if (its_instance_it != its_service_it->second.end()) {
found = true;
}
}
if (!found) {
- collected_offers_[_service][_instance] = _info;
+ collected_offers_[its_service][its_instance] = _info;
}
}
-void service_discovery_impl::start_offer_debounce_timer(bool _first_start) {
+void
+service_discovery_impl::start_offer_debounce_timer(bool _first_start) {
std::lock_guard<std::mutex> its_lock(offer_debounce_timer_mutex_);
boost::system::error_code ec;
if (_first_start) {
@@ -2943,14 +2509,14 @@ void service_discovery_impl::start_offer_debounce_timer(bool _first_start) {
"setting expiry time of timer failed: " << ec.message();
}
offer_debounce_timer_.async_wait(
- std::bind(
- &service_discovery_impl::on_offer_debounce_timer_expired,
- this, std::placeholders::_1));
+ std::bind(&service_discovery_impl::on_offer_debounce_timer_expired,
+ this, std::placeholders::_1));
}
-void service_discovery_impl::start_find_debounce_timer(bool _first_start) {
+void
+service_discovery_impl::start_find_debounce_timer(bool _first_start) {
std::lock_guard<std::mutex> its_lock(find_debounce_timer_mutex_);
boost::system::error_code ec;
if (_first_start) {
@@ -2968,20 +2534,21 @@ void service_discovery_impl::start_find_debounce_timer(bool _first_start) {
this, std::placeholders::_1));
}
-//initial delay
-void service_discovery_impl::on_find_debounce_timer_expired(
+// initial delay
+void
+service_discovery_impl::on_find_debounce_timer_expired(
const boost::system::error_code &_error) {
if(_error) { // timer was canceled
return;
}
- // only copy the accumulated requests of the initial wait phase
+ // Only copy the accumulated requests of the initial wait phase
// if the sent counter for the request is zero.
requests_t repetition_phase_finds;
bool new_finds(false);
{
std::lock_guard<std::mutex> its_lock(requested_mutex_);
- for (const auto its_service : requested_) {
- for (const auto its_instance : its_service.second) {
+ for (const auto& its_service : requested_) {
+ for (const auto& its_instance : its_service.second) {
if( its_instance.second->get_sent_counter() == 0) {
repetition_phase_finds[its_service.first][its_instance.first] = its_instance.second;
}
@@ -2998,17 +2565,13 @@ void service_discovery_impl::on_find_debounce_timer_expired(
}
// Sent out finds for the first time as initial wait phase ended
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (its_runtime) {
- std::vector<std::shared_ptr<message_impl>> its_messages;
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
- its_messages.push_back(its_message);
- // Serialize and send FindService (increments sent counter in requested_ map)
- fill_message_with_find_entries(its_runtime, its_message, its_messages,
- repetition_phase_finds);
- serialize_and_send_messages(its_messages);
- }
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message(
+ std::make_shared<message_impl>());
+ its_messages.push_back(its_message);
+ // Serialize and send FindService (increments sent counter in requested_ map)
+ insert_find_entries(its_messages, repetition_phase_finds);
+ send(its_messages);
std::chrono::milliseconds its_delay(repetitions_base_delay_);
std::uint8_t its_repetitions(1);
@@ -3034,13 +2597,14 @@ void service_discovery_impl::on_find_debounce_timer_expired(
start_find_debounce_timer(false);
}
-void service_discovery_impl::on_offer_debounce_timer_expired(
+void
+service_discovery_impl::on_offer_debounce_timer_expired(
const boost::system::error_code &_error) {
if(_error) { // timer was canceled
return;
}
- // copy the accumulated offers of the initial wait phase
+ // Copy the accumulated offers of the initial wait phase
services_t repetition_phase_offers;
bool new_offers(false);
{
@@ -3050,7 +2614,7 @@ void service_discovery_impl::on_offer_debounce_timer_expired(
if (is_diagnosis_) {
for (services_t::iterator its_service = collected_offers_.begin();
its_service != collected_offers_.end(); its_service++) {
- for (auto its_instance : its_service->second) {
+ for (const auto& its_instance : its_service->second) {
if (!configuration_->is_someip(
its_service->first, its_instance.first)) {
non_someip_services.push_back(its_service);
@@ -3076,28 +2640,23 @@ void service_discovery_impl::on_offer_debounce_timer_expired(
}
// Sent out offers for the first time as initial wait phase ended
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (its_runtime) {
- std::vector<std::shared_ptr<message_impl>> its_messages;
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
- its_messages.push_back(its_message);
- fill_message_with_offer_entries(its_runtime, its_message, its_messages,
- repetition_phase_offers, true);
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message(std::make_shared<message_impl>());
+ its_messages.push_back(its_message);
+ insert_offer_entries(its_messages, repetition_phase_offers, true);
- // Serialize and send
- serialize_and_send_messages(its_messages);
- }
+ // Serialize and send
+ send(its_messages);
std::chrono::milliseconds its_delay(0);
std::uint8_t its_repetitions(0);
if (repetitions_max_) {
- // start timer for repetition phase the first time
+ // Start timer for repetition phase the first time
// with 2^0 * repetitions_base_delay
its_delay = repetitions_base_delay_;
its_repetitions = 1;
} else {
- // if repetitions_max is set to zero repetition phase is skipped,
+ // If repetitions_max is set to zero repetition phase is skipped,
// therefore wait one cyclic offer delay before entering main phase
its_delay = cyclic_offer_delay_;
its_repetitions = 0;
@@ -3125,16 +2684,17 @@ void service_discovery_impl::on_offer_debounce_timer_expired(
start_offer_debounce_timer(false);
}
-void service_discovery_impl::on_repetition_phase_timer_expired(
+void
+service_discovery_impl::on_repetition_phase_timer_expired(
const boost::system::error_code &_error,
- std::shared_ptr<boost::asio::steady_timer> _timer,
+ const std::shared_ptr<boost::asio::steady_timer>& _timer,
std::uint8_t _repetition, std::uint32_t _last_delay) {
if (_error) {
return;
}
if (_repetition == 0) {
std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
- // we waited one cyclic offer delay, the offers can now be sent in the
+ // We waited one cyclic offer delay, the offers can now be sent in the
// main phase and the timer can be deleted
move_offers_into_main_phase(_timer);
} else {
@@ -3145,12 +2705,12 @@ void service_discovery_impl::on_repetition_phase_timer_expired(
std::uint8_t repetition(0);
bool move_to_main(false);
if (_repetition <= repetitions_max_) {
- // sent offers, double time to wait and start timer again.
+ // Sent offers, double time to wait and start timer again.
new_delay = std::chrono::milliseconds(_last_delay * 2);
repetition = ++_repetition;
} else {
- // repetition phase is now over we have to sleep one cyclic
+ // Repetition phase is now over we have to sleep one cyclic
// offer delay before it's allowed to sent the offer again.
// If the last offer was sent shorter than half the
// configured cyclic_offer_delay_ago the offers are directly
@@ -3164,18 +2724,14 @@ void service_discovery_impl::on_repetition_phase_timer_expired(
repetition = 0;
}
}
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (its_runtime) {
- std::vector<std::shared_ptr<message_impl>> its_messages;
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
- its_messages.push_back(its_message);
- fill_message_with_offer_entries(its_runtime, its_message,
- its_messages, its_timer_pair->second, true);
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message(
+ std::make_shared<message_impl>());
+ its_messages.push_back(its_message);
+ insert_offer_entries(its_messages, its_timer_pair->second, true);
- // Serialize and send
- serialize_and_send_messages(its_messages);
- }
+ // Serialize and send
+ send(its_messages);
if (move_to_main) {
move_offers_into_main_phase(_timer);
return;
@@ -3197,9 +2753,10 @@ void service_discovery_impl::on_repetition_phase_timer_expired(
}
-void service_discovery_impl::on_find_repetition_phase_timer_expired(
+void
+service_discovery_impl::on_find_repetition_phase_timer_expired(
const boost::system::error_code &_error,
- std::shared_ptr<boost::asio::steady_timer> _timer,
+ const std::shared_ptr<boost::asio::steady_timer>& _timer,
std::uint8_t _repetition, std::uint32_t _last_delay) {
if (_error) {
return;
@@ -3211,30 +2768,25 @@ void service_discovery_impl::on_find_repetition_phase_timer_expired(
std::chrono::milliseconds new_delay(0);
std::uint8_t repetition(0);
if (_repetition <= repetitions_max_) {
- // sent findService entries in one message, double time to wait and start timer again.
- std::shared_ptr<runtime> its_runtime = runtime_.lock();
- if (its_runtime) {
- std::vector<std::shared_ptr<message_impl>> its_messages;
- std::shared_ptr<message_impl> its_message =
- its_runtime->create_message();
- its_messages.push_back(its_message);
- fill_message_with_find_entries(its_runtime, its_message,
- its_messages, its_timer_pair->second);
- serialize_and_send_messages(its_messages);
- }
+ // Sent findService entries in one message, double time to wait and start timer again.
+ std::vector<std::shared_ptr<message_impl>> its_messages;
+ std::shared_ptr<message_impl> its_message(
+ std::make_shared<message_impl>());
+ its_messages.push_back(its_message);
+ insert_find_entries(its_messages, its_timer_pair->second);
+ send(its_messages);
new_delay = std::chrono::milliseconds(_last_delay * 2);
repetition = ++_repetition;
} else {
- // repetition phase is now over, erase the timer on next expiry time
+ // Repetition phase is now over, erase the timer on next expiry time
find_repetition_phase_timers_.erase(its_timer_pair);
return;
}
boost::system::error_code ec;
its_timer_pair->first->expires_from_now(new_delay, ec);
if (ec) {
- VSOMEIP_ERROR <<
- "service_discovery_impl::on_find_repetition_phase_timer_expired "
- "setting expiry time of timer failed: " << ec.message();
+ VSOMEIP_ERROR << __func__
+ << "setting expiry time of timer failed: " << ec.message();
}
its_timer_pair->first->async_wait(
std::bind(
@@ -3245,16 +2797,16 @@ void service_discovery_impl::on_find_repetition_phase_timer_expired(
}
-void service_discovery_impl::move_offers_into_main_phase(
+void
+service_discovery_impl::move_offers_into_main_phase(
const std::shared_ptr<boost::asio::steady_timer> &_timer) {
// HINT: make sure to lock the repetition_phase_timers_mutex_ before calling
- // this function
- // set flag on all serviceinfos bound to this timer
- // that they will be included in the cyclic offers from now on
+ // this function set flag on all serviceinfos bound to this timer that they
+ // will be included in the cyclic offers from now on
const auto its_timer = repetition_phase_timers_.find(_timer);
if (its_timer != repetition_phase_timers_.end()) {
- for (const auto its_service : its_timer->second) {
- for (const auto instance : its_service.second) {
+ for (const auto& its_service : its_timer->second) {
+ for (const auto& instance : its_service.second) {
instance.second->set_is_in_mainphase(true);
}
}
@@ -3262,108 +2814,50 @@ void service_discovery_impl::move_offers_into_main_phase(
}
}
-void service_discovery_impl::fill_message_with_offer_entries(
- std::shared_ptr<runtime> _runtime,
- std::shared_ptr<message_impl> _message,
- std::vector<std::shared_ptr<message_impl>> &_messages,
- const services_t &_offers, bool _ignore_phase) {
- uint32_t its_remaining(max_message_size_);
- uint32_t its_start(0);
- bool is_done(false);
- while (!is_done) {
- insert_offer_entries(_message, _offers, its_start, its_remaining,
- is_done, _ignore_phase);
- if (!is_done) {
- its_remaining = max_message_size_;
- _message = _runtime->create_message();
- _messages.push_back(_message);
- }
- }
-}
-
-void service_discovery_impl::fill_message_with_find_entries(
- std::shared_ptr<runtime> _runtime,
- std::shared_ptr<message_impl> _message,
- std::vector<std::shared_ptr<message_impl>> &_messages,
- const requests_t &_requests) {
- uint32_t its_start(0);
- uint32_t its_size(0);
- bool is_done(false);
- while (!is_done) {
- insert_find_entries(_message, _requests, its_start, its_size,
- is_done);
- its_start += its_size / VSOMEIP_SOMEIP_SD_ENTRY_SIZE;
- if (!is_done) {
- its_start = 0;
- _message = _runtime->create_message();
- _messages.push_back(_message);
- }
- };
-}
-
-
-bool service_discovery_impl::serialize_and_send_messages(
- const std::vector<std::shared_ptr<message_impl>> &_messages) {
- bool has_sent(false);
- // lock serialize mutex here as well even if we don't use the
- // serializer as it's used to guard access to the sessions_sent_ map
- std::lock_guard<std::mutex> its_lock(serialize_mutex_);
- for (const auto m : _messages) {
- if (m->get_entries().size() > 0) {
- std::pair<session_t, bool> its_session = get_session(unicast_);
- m->set_session(its_session.first);
- m->set_reboot_flag(its_session.second);
- if (host_->send(VSOMEIP_SD_CLIENT, m, true)) {
- increment_session(unicast_);
- }
- has_sent = true;
- }
- }
- return has_sent;
-}
-
-void service_discovery_impl::stop_offer_service(
- service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info) {
+void
+service_discovery_impl::stop_offer_service(
+ const std::shared_ptr<serviceinfo> &_info) {
std::lock_guard<std::mutex> its_lock(offer_mutex_);
_info->set_ttl(0);
+ const service_t its_service = _info->get_service();
+ const instance_t its_instance = _info->get_instance();
bool stop_offer_required(false);
- // delete from initial phase offers
+ // Delete from initial phase offers
{
std::lock_guard<std::mutex> its_lock(collected_offers_mutex_);
if (collected_offers_.size()) {
- auto its_service = collected_offers_.find(_service);
- if (its_service != collected_offers_.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- if (its_instance->second == _info) {
- its_service->second.erase(its_instance);
-
- if (!collected_offers_[its_service->first].size()) {
- collected_offers_.erase(its_service);
+ auto its_service_it = collected_offers_.find(its_service);
+ if (its_service_it != collected_offers_.end()) {
+ auto its_instance_it = its_service_it->second.find(its_instance);
+ if (its_instance_it != its_service_it->second.end()) {
+ if (its_instance_it->second == _info) {
+ its_service_it->second.erase(its_instance_it);
+
+ if (!collected_offers_[its_service].size()) {
+ collected_offers_.erase(its_service_it);
}
}
}
}
}
- // no need to sent out a stop offer message here as all services
+ // No need to sent out a stop offer message here as all services
// instances contained in the collected offers weren't broadcasted yet
}
- // delete from repetition phase offers
+ // Delete from repetition phase offers
{
std::lock_guard<std::mutex> its_lock(repetition_phase_timers_mutex_);
for (auto rpt = repetition_phase_timers_.begin();
rpt != repetition_phase_timers_.end();) {
- auto its_service = rpt->second.find(_service);
- if (its_service != rpt->second.end()) {
- auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- if (its_instance->second == _info) {
- its_service->second.erase(its_instance);
+ auto its_service_it = rpt->second.find(its_service);
+ if (its_service_it != rpt->second.end()) {
+ auto its_instance_it = its_service_it->second.find(its_instance);
+ if (its_instance_it != its_service_it->second.end()) {
+ if (its_instance_it->second == _info) {
+ its_service_it->second.erase(its_instance_it);
stop_offer_required = true;
- if (!rpt->second[its_service->first].size()) {
- rpt->second.erase(_service);
+ if (!rpt->second[its_service].size()) {
+ rpt->second.erase(its_service);
}
}
}
@@ -3375,36 +2869,33 @@ void service_discovery_impl::stop_offer_service(
}
}
}
- // sent stop offer
+ // Sent stop offer
if(_info->is_in_mainphase() || stop_offer_required) {
- send_stop_offer(_service, _instance, _info);
+ send_stop_offer(_info);
}
// sent out NACKs for all pending subscriptions
- remote_subscription_not_acknowledge_all(_service, _instance);
+ // TODO: remote_subscription_not_acknowledge_all(its_service, its_instance);
}
-bool service_discovery_impl::send_stop_offer(
- service_t _service, instance_t _instance,
- std::shared_ptr<serviceinfo> _info) {
- std::shared_ptr < runtime > its_runtime = runtime_.lock();
- if (its_runtime) {
- if (_info->get_endpoint(false) || _info->get_endpoint(true)) {
- std::vector<std::shared_ptr<message_impl>> its_messages;
- std::shared_ptr<message_impl> its_message;
- its_message = its_runtime->create_message();
- its_messages.push_back(its_message);
+bool
+service_discovery_impl::send_stop_offer(const std::shared_ptr<serviceinfo> &_info) {
- uint32_t its_size(max_message_size_);
- insert_offer_service(its_message, _service, _instance, _info, its_size);
+ if (_info->get_endpoint(false) || _info->get_endpoint(true)) {
+ std::vector<std::shared_ptr<message_impl> > its_messages;
+ std::shared_ptr<message_impl> its_current_message(
+ std::make_shared<message_impl>());
+ its_messages.push_back(its_current_message);
- // Serialize and send
- return serialize_and_send_messages(its_messages);
- }
+ insert_offer_service(its_messages, _info);
+
+ // Serialize and send
+ return send(its_messages);
}
return false;
}
-void service_discovery_impl::start_main_phase_timer() {
+void
+service_discovery_impl::start_main_phase_timer() {
std::lock_guard<std::mutex> its_lock(main_phase_timer_mutex_);
boost::system::error_code ec;
main_phase_timer_.expires_from_now(cyclic_offer_delay_);
@@ -3417,7 +2908,8 @@ void service_discovery_impl::start_main_phase_timer() {
this, std::placeholders::_1));
}
-void service_discovery_impl::on_main_phase_timer_expired(
+void
+service_discovery_impl::on_main_phase_timer_expired(
const boost::system::error_code &_error) {
if (_error) {
return;
@@ -3426,23 +2918,23 @@ void service_discovery_impl::on_main_phase_timer_expired(
start_main_phase_timer();
}
-void service_discovery_impl::send_uni_or_multicast_offerservice(
- service_t _service, instance_t _instance, major_version_t _major,
- minor_version_t _minor, const std::shared_ptr<const serviceinfo> &_info,
- bool _unicast_flag) {
+void
+service_discovery_impl::send_uni_or_multicast_offerservice(
+ const std::shared_ptr<const serviceinfo> &_info, bool _unicast_flag) {
if (_unicast_flag) { // SID_SD_826
if (last_offer_shorter_half_offer_delay_ago()) { // SIP_SD_89
- send_unicast_offer_service(_info, _service, _instance, _major, _minor);
+ send_unicast_offer_service(_info);
} else { // SIP_SD_90
- send_multicast_offer_service(_info, _service, _instance, _major, _minor);
+ send_multicast_offer_service(_info);
}
} else { // SID_SD_826
- send_unicast_offer_service(_info, _service, _instance, _major, _minor);
+ send_unicast_offer_service(_info);
}
}
-bool service_discovery_impl::last_offer_shorter_half_offer_delay_ago() {
- //get remaining time to next offer since last offer
+bool
+service_discovery_impl::last_offer_shorter_half_offer_delay_ago() {
+ // Get remaining time to next offer since last offer
std::chrono::milliseconds remaining(0);
{
std::lock_guard<std::mutex> its_lock(main_phase_timer_mutex_);
@@ -3458,10 +2950,11 @@ bool service_discovery_impl::last_offer_shorter_half_offer_delay_ago() {
return remaining > half_cyclic_offer_delay;
}
-bool service_discovery_impl::check_source_address(
+bool
+service_discovery_impl::check_source_address(
const boost::asio::ip::address &its_source_address) const {
bool is_valid = true;
- // check if source address is same as nodes unicast address
+ // Check if source address is same as nodes unicast address
if(unicast_ == its_source_address) {
VSOMEIP_ERROR << "Source address of message is same as DUT's unicast address! : "
<< its_source_address.to_string();
@@ -3470,217 +2963,202 @@ bool service_discovery_impl::check_source_address(
return is_valid;
}
-void service_discovery_impl::set_diagnosis_mode(const bool _activate) {
+void
+service_discovery_impl::set_diagnosis_mode(const bool _activate) {
is_diagnosis_ = _activate;
}
-bool service_discovery_impl::get_diagnosis_mode() {
+bool
+service_discovery_impl::get_diagnosis_mode() {
return is_diagnosis_;
}
-void service_discovery_impl::remote_subscription_acknowledge(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- client_t _client, bool _acknowledged,
- const std::shared_ptr<sd_message_identifier_t> &_sd_message_id) {
- std::shared_ptr<subscriber_t> its_subscriber;
- {
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- const auto its_service = pending_remote_subscriptions_.find(_service);
- if (its_service != pending_remote_subscriptions_.end()) {
- const auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- const auto its_eventgroup = its_instance->second.find(_eventgroup);
- if (its_eventgroup != its_instance->second.end()) {
- const auto its_client = its_eventgroup->second.find(_client);
- if (its_client != its_eventgroup->second.end()) {
- for (auto iter = its_client->second.begin();
- iter != its_client->second.end();) {
- if ((*iter)->response_message_id_ == _sd_message_id) {
- its_subscriber = *iter;
- iter = its_client->second.erase(iter);
- break;
- } else {
- iter++;
- }
- }
-
- // delete if necessary
- if (!its_client->second.size()) {
- its_eventgroup->second.erase(its_client);
- if (!its_eventgroup->second.size()) {
- its_instance->second.erase(its_eventgroup);
- if (!its_instance->second.size()) {
- its_service->second.erase(its_instance);
- if (!its_service->second.size()) {
- pending_remote_subscriptions_.erase(
- its_service);
- }
- }
- }
- }
- }
- }
+void
+service_discovery_impl::update_remote_subscription(
+ const std::shared_ptr<remote_subscription> &_subscription) {
+ if (!_subscription->is_pending()) {
+ std::shared_ptr<remote_subscription_ack> its_ack;
+ {
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ auto found_ack = pending_remote_subscriptions_.find(_subscription);
+ if (found_ack != pending_remote_subscriptions_.end()) {
+ its_ack = found_ack->second;
}
}
+ if (its_ack) {
+ std::unique_lock<std::recursive_mutex> its_lock(its_ack->get_lock());
+ update_acknowledgement(its_ack);
+ }
}
- if (its_subscriber) {
- remote_subscription_acknowledge_subscriber(_service, _instance,
- _eventgroup, its_subscriber, _acknowledged);
+}
+
+void
+service_discovery_impl::update_acknowledgement(
+ const std::shared_ptr<remote_subscription_ack> &_acknowledgement) {
+ if (_acknowledgement->is_complete()
+ && !_acknowledgement->is_pending()
+ && !_acknowledgement->is_done()) {
+ send_subscription_ack(_acknowledgement);
+
+ std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
+ for (const auto& its_subscription : _acknowledgement->get_subscriptions())
+ pending_remote_subscriptions_.erase(its_subscription);
}
}
-void service_discovery_impl::update_subscription_expiration_timer(
- const std::shared_ptr<message_impl> &_message) {
+
+void
+service_discovery_impl::update_subscription_expiration_timer(
+ const std::vector<std::shared_ptr<message_impl> > &_messages) {
std::lock_guard<std::mutex> its_lock(subscription_expiration_timer_mutex_);
const std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now();
stop_subscription_expiration_timer_unlocked();
-
- std::unique_lock<std::mutex> its_message_lock(_message->get_message_lock());
- for (const auto &entry : _message->get_entries()) {
- if (entry && entry->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
- && entry->get_ttl()) {
- const std::chrono::steady_clock::time_point its_expiration = now
- + std::chrono::seconds(
- entry->get_ttl()
- * get_ttl_factor(
- entry->get_service(),
- entry->get_instance(),
- ttl_factor_subscriptions_));
- if (its_expiration < next_subscription_expiration_) {
- next_subscription_expiration_ = its_expiration;
+ for (const auto &m : _messages) {
+ for (const auto &e : m->get_entries()) {
+ if (e && e->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
+ && e->get_ttl()) {
+ const std::chrono::steady_clock::time_point its_expiration = now
+ + std::chrono::seconds(e->get_ttl()
+ * get_ttl_factor(
+ e->get_service(), e->get_instance(),
+ ttl_factor_subscriptions_));
+ if (its_expiration < next_subscription_expiration_) {
+ next_subscription_expiration_ = its_expiration;
+ }
}
}
}
start_subscription_expiration_timer_unlocked();
}
-void service_discovery_impl::remote_subscription_acknowledge_subscriber(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- const std::shared_ptr<subscriber_t> &_subscriber, bool _acknowledged) {
- std::shared_ptr<message_impl> its_response = _subscriber->response_message_id_->response_;
- bool sent(false);
- {
- std::lock_guard<std::mutex> its_lock(response_mutex_);
- if (_acknowledged) {
- insert_subscription_ack(its_response, _service, _instance,
- _eventgroup, _subscriber->eventgroupinfo_,
- _subscriber->ttl_, _subscriber->counter_,
- _subscriber->major_, _subscriber->reserved_, _subscriber->subscriber);
- } else {
- insert_subscription_nack(its_response, _service, _instance,
- _eventgroup, _subscriber->counter_,
- _subscriber->major_, _subscriber->reserved_);
- }
-
- if (its_response->all_required_acks_contained()) {
- update_subscription_expiration_timer(its_response);
- serialize_and_send(its_response, _subscriber->response_message_id_->sender_);
- // set required acks to 0xFF to mark message as sent
- its_response->set_number_required_acks((std::numeric_limits<uint8_t>::max)());
- sent = true;
- } else {
- its_response->set_initial_events_required(true);
- }
- }
- if (sent) {
- for (const auto& ack_tuple : get_eventgroups_requiring_initial_events(
- its_response)) {
- host_->send_initial_events(std::get<0>(ack_tuple),
- std::get<1>(ack_tuple), std::get<2>(ack_tuple),
- std::get<3>(ack_tuple));
- }
- for (const auto &fie : its_response->forced_initial_events_get()) {
- host_->send_initial_events(fie.service_, fie.instance_,
- fie.eventgroup_, fie.target_);
- }
+bool
+service_discovery_impl::check_stop_subscribe_subscribe(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t& _options) const {
+ const message_impl::entries_t::const_iterator its_next = std::next(_iter);
+ if ((*_iter)->get_ttl() > 0
+ || (*_iter)->get_type() != entry_type_e::STOP_SUBSCRIBE_EVENTGROUP
+ || its_next == _end
+ || (*its_next)->get_type() != entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ return false;
}
+
+ return (*static_cast<eventgroupentry_impl*>(_iter->get())).matches(
+ *(static_cast<eventgroupentry_impl*>(its_next->get())), _options);
}
-void service_discovery_impl::remote_subscription_not_acknowledge_all(
- service_t _service, instance_t _instance) {
- std::map<eventgroup_t, std::vector<std::shared_ptr<subscriber_t>>>its_pending_subscriptions;
- {
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- const auto its_service = pending_remote_subscriptions_.find(_service);
- if (its_service != pending_remote_subscriptions_.end()) {
- const auto its_instance = its_service->second.find(_instance);
- if (its_instance != its_service->second.end()) {
- for (const auto &its_eventgroup : its_instance->second) {
- for (const auto &its_client : its_eventgroup.second) {
- its_pending_subscriptions[its_eventgroup.first].insert(
- its_pending_subscriptions[its_eventgroup.first].end(),
- its_client.second.begin(),
- its_client.second.end());
- }
- }
- // delete everything from this service instance
- its_service->second.erase(its_instance);
- if (!its_service->second.size()) {
- pending_remote_subscriptions_.erase(its_service);
- }
+bool
+service_discovery_impl::has_opposite(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t &_options) const {
+ const auto its_entry = std::dynamic_pointer_cast<eventgroupentry_impl>(*_iter);
+ auto its_other = std::next(_iter);
+ for (; its_other != _end; its_other++) {
+ if ((*its_other)->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ const auto its_other_entry
+ = std::dynamic_pointer_cast<eventgroupentry_impl>(*its_other);
+ if ((its_entry->get_ttl() == 0 && its_other_entry->get_ttl() > 0)
+ || (its_entry->get_ttl() > 0 && its_other_entry->get_ttl() == 0)) {
+ if (its_entry->matches(*(its_other_entry.get()), _options))
+ return true;
}
}
}
- for (const auto &eg : its_pending_subscriptions) {
- for (const auto &its_subscriber : eg.second) {
- remote_subscription_acknowledge_subscriber(_service, _instance,
- eg.first, its_subscriber, false);
+ return false;
+}
+
+bool
+service_discovery_impl::has_same(
+ message_impl::entries_t::const_iterator _iter,
+ message_impl::entries_t::const_iterator _end,
+ const message_impl::options_t &_options) const {
+ const auto its_entry = std::dynamic_pointer_cast<eventgroupentry_impl>(*_iter);
+ auto its_other = std::next(_iter);
+ for (; its_other != _end; its_other++) {
+ if (its_entry->get_type() == (*its_other)->get_type()) {
+ const auto its_other_entry
+ = std::dynamic_pointer_cast<eventgroupentry_impl>(*its_other);
+ if (its_entry->get_ttl() == its_other_entry->get_ttl()
+ && its_entry->matches(*(its_other_entry.get()), _options)) {
+ return true;
+ }
}
}
+ return false;
}
-void service_discovery_impl::remote_subscription_not_acknowledge_all() {
- std::map<service_t,
- std::map<instance_t,
- std::map<eventgroup_t, std::vector<std::shared_ptr<subscriber_t>>>>> to_be_nacked;
- {
- std::lock_guard<std::mutex> its_lock(pending_remote_subscriptions_mutex_);
- for (const auto &its_service : pending_remote_subscriptions_) {
- for (const auto &its_instance : its_service.second) {
- for (const auto &its_eventgroup : its_instance.second) {
- for (const auto &its_client : its_eventgroup.second) {
- to_be_nacked[its_service.first]
- [its_instance.first]
- [its_eventgroup.first].insert(
- to_be_nacked[its_service.first][its_instance.first][its_eventgroup.first].end(),
- its_client.second.begin(),
- its_client.second.end());
+bool
+service_discovery_impl::is_subscribed(
+ const std::shared_ptr<eventgroupentry_impl> &_entry,
+ const message_impl::options_t &_options) const {
+ const auto its_service = _entry->get_service();
+ const auto its_instance = _entry->get_instance();
+ auto its_info = host_->find_eventgroup(
+ its_service, its_instance, _entry->get_eventgroup());
+ if (its_info) {
+ std::shared_ptr<endpoint_definition> its_reliable, its_unreliable;
+ for (const auto& o : _options) {
+ if (o->get_type() == option_type_e::IP4_ENDPOINT) {
+ const auto its_endpoint_option
+ = std::dynamic_pointer_cast<ipv4_option_impl>(o);
+ if (its_endpoint_option) {
+ if (its_endpoint_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP) {
+ its_reliable = endpoint_definition::get(
+ boost::asio::ip::address_v4(
+ its_endpoint_option->get_address()),
+ its_endpoint_option->get_port(),
+ true,
+ its_service, its_instance);
+ } else if (its_endpoint_option->get_layer_four_protocol()
+ == layer_four_protocol_e::UDP) {
+ its_unreliable = endpoint_definition::get(
+ boost::asio::ip::address_v4(
+ its_endpoint_option->get_address()),
+ its_endpoint_option->get_port(),
+ false,
+ its_service, its_instance);
}
}
+ } else if (o->get_type() == option_type_e::IP6_ENDPOINT) {
+ const auto its_endpoint_option
+ = std::dynamic_pointer_cast<ipv6_option_impl>(o);
+ if (its_endpoint_option->get_layer_four_protocol()
+ == layer_four_protocol_e::TCP) {
+ its_reliable = endpoint_definition::get(
+ boost::asio::ip::address_v6(
+ its_endpoint_option->get_address()),
+ its_endpoint_option->get_port(),
+ true,
+ its_service, its_instance);
+ } else if (its_endpoint_option->get_layer_four_protocol()
+ == layer_four_protocol_e::UDP) {
+ its_unreliable = endpoint_definition::get(
+ boost::asio::ip::address_v6(
+ its_endpoint_option->get_address()),
+ its_endpoint_option->get_port(),
+ false,
+ its_service, its_instance);
+ }
}
}
- pending_remote_subscriptions_.clear();
- }
- for (const auto &s : to_be_nacked) {
- for (const auto &i : s.second) {
- for (const auto &eg : i.second) {
- for (const auto &sub : eg.second) {
- remote_subscription_acknowledge_subscriber(s.first, i.first,
- eg.first, sub, false);
+ if (its_reliable || its_unreliable) {
+ for (const auto& its_subscription : its_info->get_remote_subscriptions()) {
+ if ((!its_reliable || its_subscription->get_reliable() == its_reliable)
+ && (!its_unreliable || its_subscription->get_unreliable() == its_unreliable)) {
+ return true;
}
}
}
}
+ return false;
}
-bool service_discovery_impl::check_stop_subscribe_subscribe(
- message_impl::entries_t::const_iterator _iter,
- message_impl::entries_t::const_iterator _end,
- const message_impl::options_t& _options) const {
- const message_impl::entries_t::const_iterator its_next = std::next(_iter);
- if ((*_iter)->get_ttl() > 0
- || (*_iter)->get_type() != entry_type_e::STOP_SUBSCRIBE_EVENTGROUP
- || its_next == _end
- || (*its_next)->get_type() != entry_type_e::SUBSCRIBE_EVENTGROUP) {
- return false;
- }
-
- return (*static_cast<eventgroupentry_impl*>(_iter->get())).is_matching_subscribe(
- *(static_cast<eventgroupentry_impl*>(its_next->get())), _options);
-}
-
-configuration::ttl_factor_t service_discovery_impl::get_ttl_factor(
+configuration::ttl_factor_t
+service_discovery_impl::get_ttl_factor(
service_t _service, instance_t _instance,
const configuration::ttl_map_t& _ttl_map) const {
configuration::ttl_factor_t its_ttl_factor(1);
@@ -3694,15 +3172,23 @@ configuration::ttl_factor_t service_discovery_impl::get_ttl_factor(
return its_ttl_factor;
}
-void service_discovery_impl::on_last_msg_received_timer_expired(
+void
+service_discovery_impl::on_last_msg_received_timer_expired(
const boost::system::error_code &_error) {
if (!_error) {
- // we didn't receive a multicast message within 110% of the cyclic_offer_delay_
+ // We didn't receive a multicast message within 110% of the cyclic_offer_delay_
VSOMEIP_WARNING << "Didn't receive a multicast SD message for " <<
std::dec << last_msg_received_timer_timeout_.count() << "ms.";
- // rejoin multicast group
- if (endpoint_) {
- endpoint_->join(sd_multicast_);
+
+ // Rejoin multicast group
+ if (endpoint_ && !reliable_) {
+#ifndef ANDROID
+ reinterpret_cast<udp_server_endpoint_impl*>(
+ endpoint_.get())->join(sd_multicast_);
+#else
+ dynamic_cast<udp_server_endpoint_impl*>(
+ endpoint_.get())->join(sd_multicast_);
+#endif
}
{
boost::system::error_code ec;
@@ -3716,14 +3202,16 @@ void service_discovery_impl::on_last_msg_received_timer_expired(
}
}
-void service_discovery_impl::stop_last_msg_received_timer() {
+void
+service_discovery_impl::stop_last_msg_received_timer() {
std::lock_guard<std::mutex> its_lock(last_msg_received_timer_mutex_);
boost::system::error_code ec;
last_msg_received_timer_.cancel(ec);
}
-service_discovery_impl::remote_offer_type_e service_discovery_impl::get_remote_offer_type(
- service_t _service, instance_t _instance) {
+service_discovery_impl::remote_offer_type_e
+service_discovery_impl::get_remote_offer_type(
+ service_t _service, instance_t _instance) const {
std::lock_guard<std::mutex> its_lock(remote_offer_types_mutex_);
auto found_si = remote_offer_types_.find(std::make_pair(_service, _instance));
if (found_si != remote_offer_types_.end()) {
@@ -3732,7 +3220,24 @@ service_discovery_impl::remote_offer_type_e service_discovery_impl::get_remote_o
return remote_offer_type_e::UNKNOWN;
}
-bool service_discovery_impl::update_remote_offer_type(
+service_discovery_impl::remote_offer_type_e
+service_discovery_impl::get_remote_offer_type(
+ const std::shared_ptr<subscription> &_subscription) const {
+ bool has_reliable = (_subscription->get_endpoint(true) != nullptr);
+ bool has_unreliable = (_subscription->get_endpoint(false) != nullptr);
+
+ return (has_reliable ?
+ (has_unreliable ?
+ remote_offer_type_e::RELIABLE_UNRELIABLE :
+ remote_offer_type_e::RELIABLE) :
+ (has_unreliable ?
+ remote_offer_type_e::UNRELIABLE :
+ remote_offer_type_e::UNKNOWN));
+}
+
+
+bool
+service_discovery_impl::update_remote_offer_type(
service_t _service, instance_t _instance,
remote_offer_type_e _offer_type,
const boost::asio::ip::address &_reliable_address,
@@ -3761,7 +3266,7 @@ bool service_discovery_impl::update_remote_offer_type(
break;
case remote_offer_type_e::UNKNOWN:
default:
- VSOMEIP_WARNING << __func__ << ": unkown offer type ["
+ VSOMEIP_WARNING << __func__ << ": unknown offer type ["
<< std::hex << std::setw(4) << std::setfill('0') << _service << "."
<< std::hex << std::setw(4) << std::setfill('0') << _instance << "]"
<< _offer_type;
@@ -3770,7 +3275,8 @@ bool service_discovery_impl::update_remote_offer_type(
return ret;
}
-void service_discovery_impl::remove_remote_offer_type(
+void
+service_discovery_impl::remove_remote_offer_type(
service_t _service, instance_t _instance,
const boost::asio::ip::address &_address) {
std::lock_guard<std::mutex> its_lock(remote_offer_types_mutex_);
@@ -3795,47 +3301,134 @@ void service_discovery_impl::remove_remote_offer_type_by_ip(
remote_offers_by_ip_.erase(_address);
}
-std::vector<std::tuple<service_t, instance_t, eventgroup_t,
- std::shared_ptr<endpoint_definition>>>
-service_discovery_impl::get_eventgroups_requiring_initial_events(
- const std::shared_ptr<message_impl>& _response) const {
- std::vector<std::tuple<service_t, instance_t, eventgroup_t,
- std::shared_ptr<endpoint_definition>>> its_acks;
- for (const auto &e : _response->get_entries()) {
- if (e->get_type() == entry_type_e::SUBSCRIBE_EVENTGROUP_ACK
- && e->get_ttl() > 0) {
- const std::shared_ptr<eventgroupentry_impl> casted_e =
- std::static_pointer_cast<eventgroupentry_impl>(e);
- // only entries which require initial events have a target set
- const std::shared_ptr<endpoint_definition> its_reliable =
- casted_e->get_target(true);
- if (its_reliable) {
- its_acks.push_back(
- std::make_tuple(e->get_service(), e->get_instance(),
- casted_e->get_eventgroup(), its_reliable));
+std::shared_ptr<subscription>
+service_discovery_impl::create_subscription(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ major_version_t _major, ttl_t _ttl,
+ const std::shared_ptr<endpoint> &_reliable,
+ const std::shared_ptr<endpoint> &_unreliable) {
+ auto its_subscription = std::make_shared<subscription>();
+ its_subscription->set_major(_major);
+ its_subscription->set_ttl(_ttl);
+
+ if (_reliable) {
+ its_subscription->set_endpoint(_reliable, true);
+ its_subscription->set_tcp_connection_established(_reliable->is_established());
+ }
+
+ if (_unreliable) {
+ its_subscription->set_endpoint(_unreliable, false);
+ its_subscription->set_udp_connection_established(_unreliable->is_established());
+ }
+
+ // check whether the eventgroup is selective
+ auto its_eventgroup = host_->find_eventgroup(_service, _instance, _eventgroup);
+ if (its_eventgroup) {
+ its_subscription->set_selective(its_eventgroup->is_selective());
+ }
+
+ return its_subscription;
+}
+
+void
+service_discovery_impl::send_subscription_ack(
+ const std::shared_ptr<remote_subscription_ack> &_acknowledgement) {
+ if (_acknowledgement->is_done())
+ return;
+
+ _acknowledgement->done();
+
+ std::uint32_t its_answers(1);
+
+ // Find highest number of necessary answers
+ for (const auto& its_subscription : _acknowledgement->get_subscriptions()) {
+ if (its_subscription->get_answers() > its_answers)
+ its_answers = its_subscription->get_answers();
+ }
+
+ // send messages
+ for (std::uint32_t i = 0; i < its_answers; i++) {
+ for (const auto& its_subscription : _acknowledgement->get_subscriptions()) {
+ if (i < its_subscription->get_answers()) {
+ if (its_subscription->get_ttl() > 0) {
+ auto its_info = its_subscription->get_eventgroupinfo();
+ if (its_info) {
+ for (const auto& its_client : its_subscription->get_clients()) {
+ auto its_ttl = (its_subscription->get_client_state(its_client)
+ == remote_subscription_state_e::SUBSCRIPTION_ACKED ?
+ its_subscription->get_ttl() : 0);
+
+ insert_subscription_ack(_acknowledgement, its_info, its_ttl,
+ its_subscription->get_subscriber(), its_client);
+ }
+ }
+ }
}
- const std::shared_ptr<endpoint_definition> its_unreliable =
- casted_e->get_target(false);
- if (its_unreliable) {
- its_acks.push_back(
- std::make_tuple(e->get_service(), e->get_instance(),
- casted_e->get_eventgroup(),
- its_unreliable));
+ }
+
+ auto its_messages = _acknowledgement->get_messages();
+ serialize_and_send(its_messages, _acknowledgement->get_target_address());
+ update_subscription_expiration_timer(its_messages);
+ }
+
+ // We might need to send initial events
+ for (const auto &its_subscription : _acknowledgement->get_subscriptions()) {
+ // Assumption: We do _NOT_ need to check whether this is a child
+ // subscription, as this only applies to selective events, which
+ // are owned by exclusive event groups.
+ if (its_subscription->get_ttl() > 0
+ && its_subscription->is_initial()) {
+ its_subscription->set_initial(false);
+ auto its_info = its_subscription->get_eventgroupinfo();
+ if (its_info) {
+ its_info->send_initial_events(
+ its_subscription->get_reliable(),
+ its_subscription->get_unreliable());
}
}
}
- return its_acks;
}
-void service_discovery_impl::register_offer_acceptance_handler(
- vsomeip::offer_acceptance_handler_t _handler) {
- offer_acceptance_handler_ = _handler;
+void
+service_discovery_impl::add_entry_data(
+ std::vector<std::shared_ptr<message_impl> > &_messages,
+ const entry_data_t &_data) {
+ auto its_current_message = _messages.back();
+ const auto is_fitting = its_current_message->add_entry_data(
+ _data.entry_, _data.options_, _data.other_);
+ if (!is_fitting) {
+ its_current_message = std::make_shared<message_impl>();
+ (void)its_current_message->add_entry_data(
+ _data.entry_, _data.options_, _data.other_);
+ _messages.push_back(its_current_message);
+ }
+}
+
+void
+service_discovery_impl::add_entry_data_to_remote_subscription_ack_msg(
+ const std::shared_ptr<remote_subscription_ack>& _acknowledgement,
+ const entry_data_t &_data) {
+ auto its_current_message = _acknowledgement->get_current_message();
+ const auto is_fitting = its_current_message->add_entry_data(
+ _data.entry_, _data.options_, _data.other_);
+ if (!is_fitting) {
+ its_current_message = _acknowledgement->add_message();
+ (void)its_current_message->add_entry_data(
+ _data.entry_, _data.options_, _data.other_);
+ }
+}
+
+void
+service_discovery_impl::register_sd_acceptance_handler(
+ sd_acceptance_handler_t _handler) {
+ sd_acceptance_handler_ = _handler;
}
-void service_discovery_impl::register_reboot_notification_handler(
+void
+service_discovery_impl::register_reboot_notification_handler(
reboot_notification_handler_t _handler) {
reboot_notification_handler_ = _handler;
}
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/serviceentry_impl.cpp b/implementation/service_discovery/src/serviceentry_impl.cpp
index 8ad66d2..9ea86b1 100755
--- a/implementation/service_discovery/src/serviceentry_impl.cpp
+++ b/implementation/service_discovery/src/serviceentry_impl.cpp
@@ -1,60 +1,60 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "../include/serviceentry_impl.hpp"
-#include "../../message/include/deserializer.hpp"
-#include "../../message/include/serializer.hpp"
-
-namespace vsomeip {
-namespace sd {
-
-serviceentry_impl::serviceentry_impl() {
- minor_version_ = 0;
-}
-
-serviceentry_impl::~serviceentry_impl() {
-}
-
-minor_version_t serviceentry_impl::get_minor_version() const {
- return minor_version_;
-}
-
-void serviceentry_impl::set_minor_version(minor_version_t _version) {
- minor_version_ = _version;
-}
-
-bool serviceentry_impl::serialize(vsomeip::serializer *_to) const {
- bool is_successful = entry_impl::serialize(_to);
-
- is_successful = is_successful
- && _to->serialize(static_cast<uint8_t>(major_version_));
- is_successful = is_successful
- && _to->serialize(static_cast<uint32_t>(ttl_), true);
- is_successful = is_successful
- && _to->serialize(static_cast<uint32_t>(minor_version_));
-
- return is_successful;
-}
-
-bool serviceentry_impl::deserialize(vsomeip::deserializer *_from) {
- bool is_successful = entry_impl::deserialize(_from);
-
- uint8_t tmp_major_version(0);
- is_successful = is_successful && _from->deserialize(tmp_major_version);
- major_version_ = static_cast<major_version_t>(tmp_major_version);
-
- uint32_t tmp_ttl(0);
- is_successful = is_successful && _from->deserialize(tmp_ttl, true);
- ttl_ = static_cast<ttl_t>(tmp_ttl);
-
- uint32_t tmp_minor_version(0);
- is_successful = is_successful && _from->deserialize(tmp_minor_version);
- minor_version_ = static_cast<minor_version_t>(tmp_minor_version);
-
- return is_successful;
-}
-
-} // namespace sd
-} // namespace vsomeip
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../include/serviceentry_impl.hpp"
+#include "../../message/include/deserializer.hpp"
+#include "../../message/include/serializer.hpp"
+
+namespace vsomeip_v3 {
+namespace sd {
+
+serviceentry_impl::serviceentry_impl() {
+ minor_version_ = 0;
+}
+
+serviceentry_impl::~serviceentry_impl() {
+}
+
+minor_version_t serviceentry_impl::get_minor_version() const {
+ return minor_version_;
+}
+
+void serviceentry_impl::set_minor_version(minor_version_t _version) {
+ minor_version_ = _version;
+}
+
+bool serviceentry_impl::serialize(vsomeip_v3::serializer *_to) const {
+ bool is_successful = entry_impl::serialize(_to);
+
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint8_t>(major_version_));
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint32_t>(ttl_), true);
+ is_successful = is_successful
+ && _to->serialize(static_cast<uint32_t>(minor_version_));
+
+ return is_successful;
+}
+
+bool serviceentry_impl::deserialize(vsomeip_v3::deserializer *_from) {
+ bool is_successful = entry_impl::deserialize(_from);
+
+ uint8_t tmp_major_version(0);
+ is_successful = is_successful && _from->deserialize(tmp_major_version);
+ major_version_ = static_cast<major_version_t>(tmp_major_version);
+
+ uint32_t tmp_ttl(0);
+ is_successful = is_successful && _from->deserialize(tmp_ttl, true);
+ ttl_ = static_cast<ttl_t>(tmp_ttl);
+
+ uint32_t tmp_minor_version(0);
+ is_successful = is_successful && _from->deserialize(tmp_minor_version);
+ minor_version_ = static_cast<minor_version_t>(tmp_minor_version);
+
+ return is_successful;
+}
+
+} // namespace sd
+} // namespace vsomeip_v3
diff --git a/implementation/service_discovery/src/subscription.cpp b/implementation/service_discovery/src/subscription.cpp
index aca8967..03a55d7 100644
--- a/implementation/service_discovery/src/subscription.cpp
+++ b/implementation/service_discovery/src/subscription.cpp
@@ -5,30 +5,19 @@
#include "../include/subscription.hpp"
-namespace vsomeip {
-namespace sd {
-
-subscription::subscription(major_version_t _major, ttl_t _ttl,
- std::shared_ptr<endpoint> _reliable,
- std::shared_ptr<endpoint> _unreliable,
- subscription_type_e _subscription_type,
- uint8_t _counter)
- : major_(_major), ttl_(_ttl),
- reliable_(_reliable), unreliable_(_unreliable),
- is_acknowledged_(true),
- tcp_connection_established_(false),
- udp_connection_established_(false),
- subscription_type_(_subscription_type),
- counter_(_counter) {
-}
+#include <vsomeip/internal/logger.hpp>
-subscription::~subscription() {
-}
+namespace vsomeip_v3 {
+namespace sd {
major_version_t subscription::get_major() const {
return major_;
}
+void subscription::set_major(major_version_t _major) {
+ major_ = _major;
+}
+
ttl_t subscription::get_ttl() const {
return ttl_;
}
@@ -41,7 +30,7 @@ std::shared_ptr<endpoint> subscription::get_endpoint(bool _reliable) const {
return (_reliable ? reliable_ : unreliable_);
}
-void subscription::set_endpoint(std::shared_ptr<endpoint> _endpoint,
+void subscription::set_endpoint(const std::shared_ptr<endpoint>& _endpoint,
bool _reliable) {
if (_reliable)
reliable_ = _endpoint;
@@ -49,12 +38,29 @@ void subscription::set_endpoint(std::shared_ptr<endpoint> _endpoint,
unreliable_ = _endpoint;
}
-bool subscription::is_acknowledged() const {
- return is_acknowledged_;
+bool subscription::is_selective() const {
+ return is_selective_;
+}
+void subscription::set_selective(const bool _is_selective) {
+ is_selective_ = _is_selective;
}
-void subscription::set_acknowledged(bool _is_acknowledged) {
- is_acknowledged_ = _is_acknowledged;
+subscription_state_e
+subscription::get_state(const client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ auto found_client = clients_.find(_client);
+ if (found_client != clients_.end())
+ return found_client->second;
+ return subscription_state_e::ST_UNKNOWN;
+}
+
+void
+subscription::set_state(
+ const client_t _client, const subscription_state_e _state) {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ auto found_client = clients_.find(_client);
+ if (found_client != clients_.end())
+ found_client->second = _state;
}
bool subscription::is_tcp_connection_established() const {
@@ -71,13 +77,44 @@ void subscription::set_udp_connection_established(bool _is_established) {
udp_connection_established_ = _is_established;
}
-subscription_type_e subscription::get_subscription_type() const {
- return subscription_type_;
+bool
+subscription::add_client(const client_t _client) {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ auto find_client = clients_.find(_client);
+ if (find_client != clients_.end())
+ return false;
+
+ clients_[_client] = subscription_state_e::ST_UNKNOWN;
+ return true;
+}
+
+bool
+subscription::remove_client(const client_t _client) {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ auto its_size = clients_.size();
+ clients_.erase(_client);
+ return (its_size > clients_.size());
+}
+
+std::set<client_t> subscription::get_clients() const {
+ std::set<client_t> its_clients;
+ {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ for (const auto its_item : clients_)
+ its_clients.insert(its_item.first);
+ }
+ return its_clients;
+}
+
+bool subscription::has_client() const {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ return (clients_.size() > 0);
}
-uint8_t subscription::get_counter() const {
- return counter_;
+bool subscription::has_client(const client_t _client) const {
+ std::lock_guard<std::mutex> its_lock(clients_mutex_);
+ return (clients_.find(_client) != clients_.end());
}
} // namespace sd
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/tracing/include/channel_impl.hpp b/implementation/tracing/include/channel_impl.hpp
index 9034657..cc2e583 100644
--- a/implementation/tracing/include/channel_impl.hpp
+++ b/implementation/tracing/include/channel_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
-#define VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
+#ifndef VSOMEIP_V3_TRACE_CHANNEL_IMPL_HPP_
+#define VSOMEIP_V3_TRACE_CHANNEL_IMPL_HPP_
#include <atomic>
#include <functional>
@@ -14,7 +14,7 @@
#include <vsomeip/trace.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace trace {
typedef std::function<bool (service_t, instance_t, method_t)> filter_func_t;
@@ -44,7 +44,7 @@ public:
bool matches(service_t _service, instance_t _instance, method_t _method);
private:
- filter_id_t add_filter_intern(filter_func_t _func, bool _is_positive);
+ filter_id_t add_filter_intern(const filter_func_t& _func, bool _is_positive);
std::string id_;
std::string name_;
@@ -57,6 +57,6 @@ private:
};
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_TRACING_CHANNEL_IMPL_HPP_
+#endif // VSOMEIP_V3_TRACE_CHANNEL_IMPL_HPP_
diff --git a/implementation/tracing/include/connector_impl.hpp b/implementation/tracing/include/connector_impl.hpp
index 3234fed..8274b9f 100644
--- a/implementation/tracing/include/connector_impl.hpp
+++ b/implementation/tracing/include/connector_impl.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_TC_TRACE_CONNECTOR_HPP
-#define VSOMEIP_TC_TRACE_CONNECTOR_HPP
+#ifndef VSOMEIP_V3_TRACE_CONNECTOR_HPP_
+#define VSOMEIP_V3_TRACE_CONNECTOR_HPP_
#ifdef USE_DLT
#include <dlt/dlt.h>
@@ -24,10 +24,10 @@
#include "header.hpp"
#include "../../endpoints/include/buffer.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace cfg {
- struct trace;
+ struct trace;
}
namespace trace {
@@ -53,7 +53,7 @@ public:
VSOMEIP_EXPORT bool is_sd_message(const byte_t *_data, uint16_t _data_size) const;
VSOMEIP_EXPORT std::shared_ptr<channel> add_channel(const std::string &_id,
- const std::string &_description);
+ const std::string &_description);
VSOMEIP_EXPORT bool remove_channel(const std::string &_id);
VSOMEIP_EXPORT std::shared_ptr<channel> get_channel(const std::string &_id) const;
@@ -63,19 +63,18 @@ public:
private:
bool is_enabled_;
bool is_sd_enabled_;
- bool is_initialized_;
std::map<std::string, std::shared_ptr<channel_impl>> channels_;
mutable std::mutex channels_mutex_;
#ifdef USE_DLT
- std::map<std::string, std::shared_ptr<DltContext>> contexts_;
+ std::map<std::string, std::shared_ptr<DltContext>> contexts_;
mutable std::mutex contexts_mutex_;
#endif
};
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
#endif // VSOMEIP_TC_TRACE_CONNECTOR_HPP
diff --git a/implementation/tracing/include/defines.hpp b/implementation/tracing/include/defines.hpp
index 2325259..022f42f 100644
--- a/implementation/tracing/include/defines.hpp
+++ b/implementation/tracing/include/defines.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef TRACING_INCLUDE_DEFINES_HPP_
-#define TRACING_INCLUDE_DEFINES_HPP_
+#ifndef VSOMEIP_TRACE_DEFINES_HPP_
+#define VSOMEIP_TRACE_DEFINES_HPP_
#define VSOMEIP_TC_DEFAULT_CHANNEL_NAME "Trace Connector Network Logging"
#define VSOMEIP_TC_DEFAULT_FILTER_TYPE "positive"
-#define VSOMEIP_TC_INSTANCE_POS_MIN 8
-#define VSOMEIP_TC_INSTANCE_POS_MAX 9
+#define VSOMEIP_TC_INSTANCE_POS_MIN 8
+#define VSOMEIP_TC_INSTANCE_POS_MAX 9
-#endif /* TRACING_INCLUDE_DEFINES_HPP_ */
+#endif // VSOMEIP_TRACE_DEFINES_HPP_
diff --git a/implementation/tracing/include/enumeration_types.hpp b/implementation/tracing/include/enumeration_types.hpp
index 352ddd3..3f83586 100644
--- a/implementation/tracing/include/enumeration_types.hpp
+++ b/implementation/tracing/include/enumeration_types.hpp
@@ -3,10 +3,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_TRACE_ENUMERATION_TYPES_HPP
-#define VSOMEIP_TRACE_ENUMERATION_TYPES_HPP
+#ifndef VSOMEIP_V3_TRACE_ENUMERATION_TYPES_HPP_
+#define VSOMEIP_V3_TRACE_ENUMERATION_TYPES_HPP_
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace trace {
enum class filter_type_e : uint8_t {
@@ -15,6 +15,6 @@ enum class filter_type_e : uint8_t {
};
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_TC_ENUMERATION_TYPES_HPP
+#endif // VSOMEIP_V3_TRACE_ENUMERATION_TYPES_HPP_
diff --git a/implementation/tracing/include/header.hpp b/implementation/tracing/include/header.hpp
index 55ec73e..e3dc4c1 100644
--- a/implementation/tracing/include/header.hpp
+++ b/implementation/tracing/include/header.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_TRACE_HEADER_HPP
-#define VSOMEIP_TRACE_HEADER_HPP
+#ifndef VSOMEIP_V3_TRACE_HEADER_HPP_
+#define VSOMEIP_V3_TRACE_HEADER_HPP_
#include <memory>
@@ -14,7 +14,7 @@
#define VSOMEIP_TRACE_HEADER_SIZE 10
-namespace vsomeip {
+namespace vsomeip_v3 {
class endpoint;
@@ -40,6 +40,6 @@ struct header {
};
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_TRACE_HEADER_HPP
+#endif // VSOMEIP_V3_TRACE_HEADER_HPP_
diff --git a/implementation/tracing/src/channel_impl.cpp b/implementation/tracing/src/channel_impl.cpp
index 58f67e6..c0bc391 100644
--- a/implementation/tracing/src/channel_impl.cpp
+++ b/implementation/tracing/src/channel_impl.cpp
@@ -3,9 +3,9 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../include/channel_impl.hpp"
-#include "../../logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace trace {
const filter_id_t FILTER_ID_ERROR(0);
@@ -231,7 +231,7 @@ void channel_impl::remove_filter(filter_id_t _id) {
negative_.erase(_id);
}
-filter_id_t channel_impl::add_filter_intern(filter_func_t _func, bool _is_positive) {
+filter_id_t channel_impl::add_filter_intern(const filter_func_t& _func, bool _is_positive) {
filter_id_t its_id = current_filter_id_.fetch_add(1);
std::lock_guard<std::mutex> its_lock(mutex_);
@@ -270,4 +270,4 @@ bool channel_impl::matches(
}
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/tracing/src/connector_impl.cpp b/implementation/tracing/src/connector_impl.cpp
index f8655db..f71c92e 100644
--- a/implementation/tracing/src/connector_impl.cpp
+++ b/implementation/tracing/src/connector_impl.cpp
@@ -4,16 +4,15 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <vsomeip/constants.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/channel_impl.hpp"
#include "../include/connector_impl.hpp"
#include "../include/defines.hpp"
-#include "../../configuration/include/internal.hpp"
#include "../../configuration/include/trace.hpp"
-#include "../../logging/include/logger.hpp"
#include "../../utility/include/byteorder.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace trace {
const char *VSOMEIP_TC_DEFAULT_CHANNEL_ID = "TC";
@@ -25,8 +24,7 @@ std::shared_ptr<connector_impl> connector_impl::get() {
connector_impl::connector_impl() :
is_enabled_(false),
- is_sd_enabled_(false),
- is_initialized_(false) {
+ is_sd_enabled_(false) {
channels_[VSOMEIP_TC_DEFAULT_CHANNEL_ID]
= std::make_shared<channel_impl>(VSOMEIP_TC_DEFAULT_CHANNEL_ID,
@@ -223,4 +221,4 @@ void connector_impl::trace(const byte_t *_header, uint16_t _header_size,
}
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/tracing/src/header.cpp b/implementation/tracing/src/header.cpp
index 2f4f3f8..0940e59 100644
--- a/implementation/tracing/src/header.cpp
+++ b/implementation/tracing/src/header.cpp
@@ -10,7 +10,7 @@
#include "../../endpoints/include/client_endpoint.hpp"
#include "../../utility/include/byteorder.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
namespace trace {
bool header::prepare(const std::shared_ptr<endpoint> &_endpoint,
@@ -52,8 +52,8 @@ bool header::prepare(const endpoint *_endpoint, bool _is_sending,
}
void header::prepare(const boost::asio::ip::address_v4 &_address,
- std::uint16_t _port, protocol_e _protocol,
- bool _is_sending, instance_t _instance) {
+ std::uint16_t _port, protocol_e _protocol,
+ bool _is_sending, instance_t _instance) {
unsigned long its_address_as_long = _address.to_ulong();
data_[0] = VSOMEIP_LONG_BYTE3(its_address_as_long);
data_[1] = VSOMEIP_LONG_BYTE2(its_address_as_long);
@@ -68,4 +68,4 @@ void header::prepare(const boost::asio::ip::address_v4 &_address,
}
} // namespace trace
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/implementation/utility/include/byteorder.hpp b/implementation/utility/include/byteorder.hpp
index f6a0e1b..ea2dc38 100644
--- a/implementation/utility/include/byteorder.hpp
+++ b/implementation/utility/include/byteorder.hpp
@@ -1,58 +1,58 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_BYTEORDER_HPP
-#define VSOMEIP_BYTEORDER_HPP
-
-#if defined(LINUX)
-#include <endian.h>
-#elif defined(FREEBSD)
-#include <sys/endian.h>
-#else
-// TEST IF THERE COULD BE AN ERROR!
-//#error "Undefined OS (only Linux/FreeBSD are currently supported)"
-#endif
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x0) << 8 | (x1)))
-#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3)))
-
-#define VSOMEIP_WORDS_TO_LONG(x0, x1) (uint32_t((x0) << 16 | (x1)))
-
-#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) & 0xFF))
-#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) >> 8))
-
-#define VSOMEIP_LONG_BYTE0(x) (uint8_t((x) & 0xFF))
-#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 8) & 0xFF))
-#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 16) & 0xFF))
-#define VSOMEIP_LONG_BYTE3(x) (uint8_t(((x) >> 24) & 0xFF))
-
-#define VSOMEIP_LONG_WORD0(x) (uint16_t((x) & 0xFFFF))
-#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) >> 16) & 0xFFFF))
-
-#elif __BYTE_ORDER == __BIG_ENDIAN
-
-#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x1) << 8 | (x0)))
-#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0)))
-
-#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) >> 8))
-#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) & 0xFF))
-
-#define VSOMEIP_LONG_BYTE0(x) (uint8_t(((x) >> 24) & 0xFF))
-#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 16) & 0xFF))
-#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 8) & 0xFF))
-#define VSOMEIP_LONG_BYTE3(x) (uint8_t((x) & 0xFF))
-
-#define VSOMEIP_LONG_WORD0(x) (uint16_t((((x) >> 16) & 0xFFFF))
-#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) & 0xFFFF))
-
-#else
-
-#error "__BYTE_ORDER is not defined!"
-
-#endif
-
-#endif // VSOMEIP_BYTEORDER_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_BYTEORDER_HPP
+#define VSOMEIP_V3_BYTEORDER_HPP
+
+#if defined(LINUX)
+#include <endian.h>
+#elif defined(FREEBSD)
+#include <sys/endian.h>
+#else
+// TEST IF THERE COULD BE AN ERROR!
+//#error "Undefined OS (only Linux/FreeBSD are currently supported)"
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x0) << 8 | (x1)))
+#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x0) << 24 | (x1) << 16 | (x2) << 8 | (x3)))
+
+#define VSOMEIP_WORDS_TO_LONG(x0, x1) (uint32_t((x0) << 16 | (x1)))
+
+#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) & 0xFF))
+#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) >> 8))
+
+#define VSOMEIP_LONG_BYTE0(x) (uint8_t((x) & 0xFF))
+#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 8) & 0xFF))
+#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 16) & 0xFF))
+#define VSOMEIP_LONG_BYTE3(x) (uint8_t(((x) >> 24) & 0xFF))
+
+#define VSOMEIP_LONG_WORD0(x) (uint16_t((x) & 0xFFFF))
+#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) >> 16) & 0xFFFF))
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+#define VSOMEIP_BYTES_TO_WORD(x0, x1) (uint16_t((x1) << 8 | (x0)))
+#define VSOMEIP_BYTES_TO_LONG(x0, x1, x2, x3) (uint32_t((x3) << 24 | (x2) << 16 | (x1) << 8 | (x0)))
+
+#define VSOMEIP_WORD_BYTE0(x) (uint8_t((x) >> 8))
+#define VSOMEIP_WORD_BYTE1(x) (uint8_t((x) & 0xFF))
+
+#define VSOMEIP_LONG_BYTE0(x) (uint8_t(((x) >> 24) & 0xFF))
+#define VSOMEIP_LONG_BYTE1(x) (uint8_t(((x) >> 16) & 0xFF))
+#define VSOMEIP_LONG_BYTE2(x) (uint8_t(((x) >> 8) & 0xFF))
+#define VSOMEIP_LONG_BYTE3(x) (uint8_t((x) & 0xFF))
+
+#define VSOMEIP_LONG_WORD0(x) (uint16_t((((x) >> 16) & 0xFFFF))
+#define VSOMEIP_LONG_WORD1(x) (uint16_t(((x) & 0xFFFF))
+
+#else
+
+#error "__BYTE_ORDER is not defined!"
+
+#endif
+
+#endif // VSOMEIP_V3_BYTEORDER_HPP_
diff --git a/implementation/utility/include/criticalsection.hpp b/implementation/utility/include/criticalsection.hpp
index c980130..2040b74 100644
--- a/implementation/utility/include/criticalsection.hpp
+++ b/implementation/utility/include/criticalsection.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CRITICALSECTION_HPP
-#define VSOMEIP_CRITICALSECTION_HPP
+#ifndef VSOMEIP_V3_CRITICALSECTION_HPP
+#define VSOMEIP_V3_CRITICALSECTION_HPP
#include <memory>
#include <mutex>
-namespace vsomeip {
+namespace vsomeip_v3 {
#ifdef _WIN32
@@ -41,6 +41,6 @@ namespace vsomeip {
#endif
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif //VSOMEIP_CRITICALSECTION_HPP
+#endif //VSOMEIP_V3_CRITICALSECTION_HPP
diff --git a/implementation/utility/include/utility.hpp b/implementation/utility/include/utility.hpp
index c5d8afe..9975bf9 100644
--- a/implementation/utility/include/utility.hpp
+++ b/implementation/utility/include/utility.hpp
@@ -3,31 +3,27 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_UTILITY_HPP
-#define VSOMEIP_UTILITY_HPP
+#ifndef VSOMEIP_V3_UTILITY_HPP
+#define VSOMEIP_V3_UTILITY_HPP
+#include <map>
+#include <set>
#include <memory>
#include <vector>
-#include <set>
#include <atomic>
#ifdef _WIN32
- #include <stdlib.h>
- #define bswap_16(x) _byteswap_ushort(x)
- #define bswap_32(x) _byteswap_ulong(x)
-#else
- #include <byteswap.h>
+ #define WIN32_LEAN_AND_MEAN
+ #include <windows.h>
#endif
#include <vsomeip/enumeration_types.hpp>
#include <vsomeip/message.hpp>
#include "criticalsection.hpp"
-#include "../../../implementation/configuration/include/policy.hpp"
-namespace vsomeip {
+namespace vsomeip_v3 {
class configuration;
-struct policy;
class utility {
public:
@@ -96,29 +92,19 @@ public:
static uint32_t get_payload_size(const byte_t *_data, uint32_t _size);
+ static bool is_routing_manager(const std::shared_ptr<configuration> &_config);
+ static void remove_lockfile(const std::shared_ptr<configuration> &_config);
static bool exists(const std::string &_path);
static bool VSOMEIP_IMPORT_EXPORT is_file(const std::string &_path);
static bool VSOMEIP_IMPORT_EXPORT is_folder(const std::string &_path);
static const std::string get_base_path(const std::shared_ptr<configuration> &_config);
- static const std::string get_shm_name(const std::shared_ptr<configuration> &_config);
-
- static CriticalSection its_local_configuration_mutex__;
-
- static struct configuration_data_t *the_configuration_data__;
- static bool auto_configuration_init(const std::shared_ptr<configuration> &_config);
- static void auto_configuration_exit(client_t _client,
- const std::shared_ptr<configuration> &_config);
-
- static bool is_routing_manager_host(client_t _client);
- static void set_routing_manager_host(client_t _client);
- static bool is_used_client_id(client_t _client,
- const std::shared_ptr<configuration> &_config);
static client_t request_client_id(const std::shared_ptr<configuration> &_config,
const std::string &_name, client_t _client);
static void release_client_id(client_t _client);
static std::set<client_t> get_used_client_ids();
+ static void reset_client_ids();
static inline bool is_valid_message_type(message_type_e _type) {
return (_type == message_type_e::MT_REQUEST
@@ -148,34 +134,20 @@ public:
|| _code == return_code_e::E_WRONG_MESSAGE_TYPE);
}
- VSOMEIP_EXPORT static bool parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid, ::std::shared_ptr<policy> &_policy);
- VSOMEIP_EXPORT static bool parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid);
-
private:
- static void check_client_id_consistency();
- static std::uint16_t get_max_number_of_clients(std::uint16_t _diagnosis_max);
- static inline bool parse_range(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_first, uint16_t &_last);
- static inline bool parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id);
- static inline bool get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
- static inline bool get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
- static inline bool get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length);
- static inline bool is_range(const byte_t* &_buffer, uint32_t &_buffer_size);
- static inline bool parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes, ranges_t& its_ranges, uint32_t &_buffer_size);
-
- static std::atomic<std::uint16_t> its_configuration_refs__;
- static std::uint16_t* used_client_ids__;
-
- static const uint8_t uid_width_;
- static const uint8_t gid_width_;
- static const uint8_t id_width_;
- static const uint8_t range_width_;
- static const uint8_t skip_union_length_ ;
- static const uint8_t skip_union_type_ ;
- static const uint8_t skip_union_length_type_ ;
- static const uint8_t skip_struct_length_;
- static const uint8_t skip_array_length_;
+ static std::uint16_t get_max_client_number(const std::shared_ptr<configuration> &_config);
+
+ static std::mutex mutex__;
+ static client_t next_client__;
+ static std::map<client_t, std::string> used_clients__;
+#ifdef _WIN32
+ static HANDLE lock_handle__;
+#else
+ static int lock_fd__;
+#endif
+ static bool is_checked__;
};
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_UTILITY_HPP
+#endif // VSOMEIP_V3_UTILITY_HPP
diff --git a/implementation/utility/src/criticalsection.cpp b/implementation/utility/src/criticalsection.cpp
index 413ad19..78b0b5c 100644
--- a/implementation/utility/src/criticalsection.cpp
+++ b/implementation/utility/src/criticalsection.cpp
@@ -8,7 +8,7 @@
#include <Windows.h>
-namespace vsomeip {
+namespace vsomeip_v3 {
struct CriticalSection::Impl final {
CRITICAL_SECTION m_criticalSection;
@@ -36,6 +36,6 @@ namespace vsomeip {
LeaveCriticalSection(&m_impl->m_criticalSection);
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
#endif
diff --git a/implementation/utility/src/utility.cpp b/implementation/utility/src/utility.cpp
index 9919ea8..4147463 100644
--- a/implementation/utility/src/utility.cpp
+++ b/implementation/utility/src/utility.cpp
@@ -3,12 +3,17 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <iomanip>
+
#ifdef _WIN32
#include <iostream>
+ #include <tchar.h>
#include <intrin.h>
#else
#include <dlfcn.h>
#include <signal.h>
+ #include <unistd.h>
+ #include <fcntl.h>
#include <sys/mman.h>
#include <thread>
#include <sstream>
@@ -18,20 +23,23 @@
#include <vsomeip/constants.hpp>
#include <vsomeip/defines.hpp>
+#include <vsomeip/internal/logger.hpp>
#include "../include/byteorder.hpp"
#include "../include/utility.hpp"
#include "../../configuration/include/configuration.hpp"
-#include "../../configuration/include/internal.hpp"
-#include "../../logging/include/logger.hpp"
+namespace vsomeip_v3 {
+
+std::mutex utility::mutex__;
+client_t utility::next_client__(VSOMEIP_CLIENT_UNSET);
+std::map<client_t, std::string> utility::used_clients__;
#ifdef _WIN32
- #ifndef _WINSOCKAPI_
- #include <Windows.h>
- #endif
+HANDLE utility::lock_handle__(INVALID_HANDLE_VALUE);
+#else
+int utility::lock_fd__(-1);
#endif
-
-namespace vsomeip {
+bool utility::is_checked__(false);
uint64_t utility::get_message_size(const byte_t *_data, size_t _size) {
uint64_t its_size(0);
@@ -51,1066 +59,214 @@ uint32_t utility::get_payload_size(const byte_t *_data, uint32_t _size) {
return (its_size);
}
-bool utility::exists(const std::string &_path) {
- struct stat its_stat;
- return (stat(_path.c_str(), &its_stat) == 0);
-}
-
-bool utility::is_file(const std::string &_path) {
- struct stat its_stat;
- if (stat(_path.c_str(), &its_stat) == 0) {
- if (its_stat.st_mode & S_IFREG)
- return true;
- }
- return false;
-}
-
-bool utility::is_folder(const std::string &_path) {
- struct stat its_stat;
- if (stat(_path.c_str(), &its_stat) == 0) {
- if (its_stat.st_mode & S_IFDIR)
- return true;
- }
- return false;
-}
-
-const std::string utility::get_base_path(
- const std::shared_ptr<configuration> &_config) {
- return std::string(VSOMEIP_BASE_PATH + _config->get_network() + "-");
-}
-
-const std::string utility::get_shm_name(
- const std::shared_ptr<configuration> &_config) {
- return std::string("/" + _config->get_network());
-}
-
-// pointer to shared memory
-configuration_data_t *utility::the_configuration_data__(nullptr);
-// critical section to protect shared memory pointers, handles and ref count in this process
-CriticalSection utility::its_local_configuration_mutex__;
-// number of times auto_configuration_init() has been called in this process
-std::atomic<std::uint16_t> utility::its_configuration_refs__(0);
-// pointer to used client IDs array in shared memory
-std::uint16_t* utility::used_client_ids__(0);
-
-#ifdef _WIN32
-// global (inter-process) mutex
-static HANDLE configuration_data_mutex(INVALID_HANDLE_VALUE);
-// memory mapping handle
-static HANDLE its_descriptor(INVALID_HANDLE_VALUE);
-#endif
-
-bool utility::auto_configuration_init(const std::shared_ptr<configuration> &_config) {
- std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
- const std::uint16_t its_max_clients =
- get_max_number_of_clients(_config->get_diagnosis_mask());
+bool utility::is_routing_manager(const std::shared_ptr<configuration> &_config) {
+ // Only the first caller can become routing manager.
+ // Therefore, subsequent calls can be immediately answered...
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ if (is_checked__)
+ return false;
- const size_t its_shm_size = sizeof(configuration_data_t) +
- (its_max_clients + 1) * sizeof(client_t);
+ is_checked__ = true;
#ifdef _WIN32
- if (its_configuration_refs__ > 0) {
- assert(configuration_data_mutex != INVALID_HANDLE_VALUE);
- assert(its_descriptor != INVALID_HANDLE_VALUE);
- assert(the_configuration_data__ != nullptr);
-
- ++its_configuration_refs__;
- } else {
- configuration_data_mutex = CreateMutex(
- NULL, // default security attributes
- true, // initially owned
- "vSomeIP_SharedMemoryLock"); // named mutex
- if (configuration_data_mutex) {
-
- if (GetLastError() == ERROR_ALREADY_EXISTS) {
- VSOMEIP_INFO << "utility::auto_configuration_init: use existing shared memory";
-
- // mapping already exists, wait for mutex release and map in
- DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE);
- if (waitResult == WAIT_OBJECT_0) {
-
- its_descriptor = CreateFileMapping(
- INVALID_HANDLE_VALUE, // use paging file
- NULL, // default security
- PAGE_READWRITE, // read/write access
- 0, // maximum object size (high-order DWORD)
- its_shm_size, // maximum object size (low-order DWORD)
- utility::get_shm_name(_config).c_str());// name of mapping object
-
- if (its_descriptor && GetLastError() == ERROR_ALREADY_EXISTS) {
-
- void *its_segment = (LPTSTR)MapViewOfFile(its_descriptor, // handle to map object
- FILE_MAP_ALL_ACCESS, // read/write permission
- 0,
- 0,
- its_shm_size);
-
- if (its_segment) {
- the_configuration_data__
- = reinterpret_cast<configuration_data_t *>(its_segment);
-
- ++its_configuration_refs__;
- used_client_ids__ = reinterpret_cast<unsigned short*>(
- reinterpret_cast<size_t>(&the_configuration_data__->routing_manager_host_) + sizeof(unsigned short));
-
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: MapViewOfFile failed (" << GetLastError() << ")";
- }
- } else {
- if (its_descriptor) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: CreateFileMapping failed. expected existing mapping";
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: CreateFileMapping failed (" << GetLastError() << ")";
- }
- }
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: WaitForSingleObject(mutex) failed (" << GetLastError() << ")";
- }
-
- } else {
- VSOMEIP_INFO << "utility::auto_configuration_init: create new shared memory";
-
- // create and init new mapping
- its_descriptor = CreateFileMapping(
- INVALID_HANDLE_VALUE, // use paging file
- NULL, // default security
- PAGE_READWRITE, // read/write access
- 0, // maximum object size (high-order DWORD)
- its_shm_size, // maximum object size (low-order DWORD)
- utility::get_shm_name(_config).c_str());// name of mapping object
-
- if (its_descriptor) {
- void *its_segment = (LPTSTR)MapViewOfFile(its_descriptor, // handle to map object
- FILE_MAP_ALL_ACCESS, // read/write permission
- 0,
- 0,
- its_shm_size);
- if (its_segment) {
- the_configuration_data__
- = reinterpret_cast<configuration_data_t *>(its_segment);
-
- the_configuration_data__->client_base_
- = static_cast<unsigned short>((_config->get_diagnosis_address() << 8) & _config->get_diagnosis_mask());
- the_configuration_data__->max_clients_ = its_max_clients;
- the_configuration_data__->max_used_client_ids_index_ = 1;
- the_configuration_data__->max_assigned_client_id_ = 0x00;
- the_configuration_data__->routing_manager_host_ = 0x0000;
- // the clientid array starts right after the routing_manager_host_ struct member
- used_client_ids__ = reinterpret_cast<unsigned short*>(
- reinterpret_cast<size_t>(&the_configuration_data__->routing_manager_host_) + sizeof(unsigned short));
- used_client_ids__[0] = the_configuration_data__->client_base_;
- the_configuration_data__->client_base_++;
- std::string its_name = _config->get_routing_host();
- if (its_name == "")
- the_configuration_data__->routing_manager_host_ = the_configuration_data__->client_base_;
-
- its_configuration_refs__++;
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: MapViewOfFile failed (" << GetLastError() << ")";
- }
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: CreateFileMapping failed (" << GetLastError() << ")";
- }
- }
-
- // always release mutex
- ReleaseMutex(configuration_data_mutex);
- } else {
- VSOMEIP_ERROR << "utility::auto_configuration_init: CreateMutex failed (" << GetLastError() << ")";
+ wchar_t its_tmp_folder[MAX_PATH];
+ if (GetTempPathW(MAX_PATH, its_tmp_folder)) {
+ std::wstring its_lockfile(its_tmp_folder);
+ std::string its_network(_config->get_network() + ".lck");
+ its_lockfile.append(its_network.begin(), its_network.end());
+ lock_handle__ = CreateFileW(its_lockfile.c_str(), GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
+ if (lock_handle__ == INVALID_HANDLE_VALUE) {
+ VSOMEIP_ERROR << __func__ << ": CreateFileW failed: "
+ << its_lockfile << " " << std::hex << GetLastError();
}
-
- // cleanup in case of error
- if (the_configuration_data__ == nullptr) {
- if (its_descriptor != INVALID_HANDLE_VALUE) {
- CloseHandle(its_descriptor);
- its_descriptor = INVALID_HANDLE_VALUE;
- }
- if (configuration_data_mutex != INVALID_HANDLE_VALUE) {
- CloseHandle(configuration_data_mutex);
- configuration_data_mutex = INVALID_HANDLE_VALUE;
- }
- }
- }
-#else
- if (its_configuration_refs__ > 0) {
- // shm is already mapped into the process
- its_configuration_refs__++;
} else {
- int its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR | O_CREAT | O_EXCL,
- static_cast<mode_t>(_config->get_permissions_shm()));
- if (its_descriptor > -1) {
- if (-1 == chmod(std::string("/dev/shm").append(utility::get_shm_name(_config)).c_str(),
- static_cast<mode_t>(_config->get_permissions_uds()))) {
- VSOMEIP_ERROR << __func__ << ": chmod: " << strerror(errno);
- }
- if (-1 == ftruncate(its_descriptor, its_shm_size)) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "ftruncate failed: " << std::strerror(errno);
- } else {
- void *its_segment = mmap(0, its_shm_size,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- its_descriptor, 0);
- if(MAP_FAILED == its_segment) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "mmap failed: " << std::strerror(errno);
- } else {
- the_configuration_data__
- = reinterpret_cast<configuration_data_t *>(its_segment);
- if (the_configuration_data__ != nullptr) {
- int ret;
- pthread_mutexattr_t attr;
- ret = pthread_mutexattr_init(&attr);
- if (0 == ret) {
- ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
- if (0 != ret) {
- VSOMEIP_ERROR << "pthread_mutexattr_setpshared() failed " << ret;
- }
- ret = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
- if (0 != ret) {
- VSOMEIP_ERROR << "pthread_mutexattr_setrobust() failed " << ret;
- }
-
- } else {
- VSOMEIP_ERROR << "pthread_mutexattr_init() failed " << ret;
- }
- ret = pthread_mutex_init(&the_configuration_data__->mutex_, (0==ret)?&attr:NULL);
- if (0 != ret) {
- VSOMEIP_ERROR << "pthread_mutex_init() failed " << ret;
- }
- ret = pthread_mutex_lock(&the_configuration_data__->mutex_);
- if (0 != ret) {
- VSOMEIP_ERROR << "pthread_mutex_lock() failed " << ret;
- }
-
- the_configuration_data__->client_base_
- = static_cast<unsigned short>((_config->get_diagnosis_address() << 8) & _config->get_diagnosis_mask());
- the_configuration_data__->max_clients_ = its_max_clients;
- the_configuration_data__->max_used_client_ids_index_ = 1;
- the_configuration_data__->max_assigned_client_id_ = 0x00;
- the_configuration_data__->routing_manager_host_ = 0x0000;
- // the clientid array starts right after the routing_manager_host_ struct member
- used_client_ids__ = reinterpret_cast<unsigned short*>(
- reinterpret_cast<size_t>(&the_configuration_data__->routing_manager_host_) + sizeof(unsigned short));
- used_client_ids__[0] = the_configuration_data__->client_base_;
- the_configuration_data__->client_base_++;
-
- std::string its_name = _config->get_routing_host();
-
- its_configuration_refs__++;
-
- the_configuration_data__->initialized_ = 1;
-
- ret = pthread_mutex_unlock(&the_configuration_data__->mutex_);
- if (0 != ret) {
- VSOMEIP_ERROR << "pthread_mutex_unlock() failed " << ret;
- }
- }
-
- if(-1 == ::close(its_descriptor)) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "close failed: " << std::strerror(errno);
- }
- }
- }
- } else if (errno == EEXIST) {
- its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR,
- static_cast<mode_t>(_config->get_permissions_shm()));
-
- int retry_count = 8;
- std::chrono::milliseconds retry_delay = std::chrono::milliseconds(10);
- while (its_descriptor == -1 && retry_count-- > 0) {
- std::this_thread::sleep_for(retry_delay);
- its_descriptor = shm_open(utility::get_shm_name(_config).c_str(), O_RDWR,
- static_cast<mode_t>(_config->get_permissions_shm()));
- retry_delay *= 2;
- }
-
- if (-1 == its_descriptor) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "shm_open failed: " << std::strerror(errno);
- } else {
- // truncate to make sure we work on valid shm;
- // in case creator already called truncate, this effectively becomes a noop
- if (-1 == ftruncate(its_descriptor, its_shm_size)) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "ftruncate failed: " << std::strerror(errno);
- } else {
- void *its_segment = mmap(0, its_shm_size,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- its_descriptor, 0);
- if(MAP_FAILED == its_segment) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "mmap failed: " << std::strerror(errno);
- } else {
- configuration_data_t *configuration_data
- = reinterpret_cast<configuration_data_t *>(its_segment);
-
- // check if it is ready for use (for 3 seconds)
- int retry_count = 300;
- while (configuration_data->initialized_ == 0 && --retry_count > 0) {
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
-
- if (configuration_data->initialized_ == 0) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: data in shm not initialized";
- } else {
- the_configuration_data__ = configuration_data;
-
- int its_result = pthread_mutex_lock(&the_configuration_data__->mutex_);
-
- used_client_ids__ = reinterpret_cast<unsigned short*>(
- reinterpret_cast<size_t>(&the_configuration_data__->routing_manager_host_)
- + sizeof(unsigned short));
-
- if (EOWNERDEAD == its_result) {
- VSOMEIP_WARNING << "utility::auto_configuration_init EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
- }
-
- its_configuration_refs__++;
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
- }
-
- if (-1 == ::close(its_descriptor)) {
- VSOMEIP_ERROR << "utility::auto_configuration_init: "
- "close failed: " << std::strerror(errno);
- }
- }
- }
- }
- }
+ VSOMEIP_ERROR << __func__ << ": Could not get temp folder: "
+ << std::hex << GetLastError();
+ lock_handle__ = INVALID_HANDLE_VALUE;
}
-#endif
- return (the_configuration_data__ != nullptr);
-}
-
-void utility::auto_configuration_exit(client_t _client,
- const std::shared_ptr<configuration> &_config) {
- std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
- if (the_configuration_data__) {
-#ifdef _WIN32
- // not manipulating data in shared memory, no need to take global mutex
-
- assert(configuration_data_mutex != INVALID_HANDLE_VALUE);
- assert(its_descriptor != INVALID_HANDLE_VALUE);
-
- its_configuration_refs__--;
-
- if (is_routing_manager_host(_client)) {
- set_routing_manager_host(0x0000);
- }
- if (its_configuration_refs__ == 0) {
- UnmapViewOfFile(the_configuration_data__);
- the_configuration_data__ = nullptr;
- used_client_ids__ = nullptr;
-
- CloseHandle(its_descriptor);
- its_descriptor = NULL;
-
- CloseHandle(configuration_data_mutex);
- configuration_data_mutex = NULL;
- }
+ return (lock_handle__ != INVALID_HANDLE_VALUE);
#else
- its_configuration_refs__--;
-
- bool unlink_shm = false;
- if (is_routing_manager_host(_client)) {
- set_routing_manager_host(0x0000);
- unlink_shm = true;
- }
+ std::string its_base_path(VSOMEIP_BASE_PATH + _config->get_network());
+ std::string its_lockfile(its_base_path + ".lck");
+ int its_lock_ctrl(-1);
- if (its_configuration_refs__ == 0) {
- const std::uint16_t its_max_clients =
- get_max_number_of_clients(_config->get_diagnosis_mask());
- const size_t its_shm_size = sizeof(configuration_data_t) +
- (its_max_clients + 1) * sizeof(client_t);
- if (-1 == ::munmap(the_configuration_data__, its_shm_size)) {
- VSOMEIP_ERROR << "utility::auto_configuration_exit: "
- "munmap failed: " << std::strerror(errno);
- } else {
- VSOMEIP_INFO << "utility::auto_configuration_exit: "
- "munmap succeeded.";
- the_configuration_data__ = nullptr;
- used_client_ids__ = nullptr;
- if (unlink_shm) {
- shm_unlink(utility::get_shm_name(_config).c_str());
- }
- }
+ struct flock its_lock_data = { F_WRLCK, SEEK_SET, 0, 0, 0 };
- }
-#endif
- }
-}
-
-bool utility::is_used_client_id(client_t _client,
- const std::shared_ptr<configuration> &_config) {
- for (int i = 0;
- i < the_configuration_data__->max_used_client_ids_index_;
- i++) {
- if (used_client_ids__[i] == _client) {
- return true;
- }
+ lock_fd__ = open(its_lockfile.c_str(), O_WRONLY | O_CREAT, S_IWUSR | S_IWGRP);
+ if (-1 != lock_fd__) {
+ its_lock_data.l_pid = getpid();
+ its_lock_ctrl = fcntl(lock_fd__, F_SETLK, &its_lock_data);
+ } else {
+ VSOMEIP_ERROR << __func__
+ << ": Could not open " << its_lockfile << ": " << std::strerror(errno);
}
-#ifndef _WIN32
- std::stringstream its_client;
- its_client << utility::get_base_path(_config) << std::hex << _client;
- if (exists(its_client.str())) {
- if (-1 == ::unlink(its_client.str().c_str())) {
- VSOMEIP_WARNING << "unlink failed for " << its_client.str() << ". Client identifier 0x"
- << std::hex << _client << " can't be reused!";
- return true;
- }
- }
+ return (its_lock_ctrl != -1);
#endif
- return false;
}
-std::set<client_t> utility::get_used_client_ids() {
- std::set<client_t> clients;
-
- std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
-
- if (the_configuration_data__ != nullptr) {
-#ifdef _WIN32
- DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE);
- assert(waitResult == WAIT_OBJECT_0);
- (void)waitResult;
-#else
- if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
- VSOMEIP_WARNING << "utility::request_client_id EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
- }
-#endif
- for (int i = 1;
- i < the_configuration_data__->max_used_client_ids_index_;
- i++) {
- clients.insert(used_client_ids__[i]);
- }
-
-#ifdef _WIN32
- BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
- assert(releaseResult);
- (void)releaseResult;
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
- }
-
- return clients;
-}
-
-client_t utility::request_client_id(const std::shared_ptr<configuration> &_config, const std::string &_name, client_t _client) {
- std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
-
- if (the_configuration_data__ != nullptr) {
- const std::string its_name = _config->get_routing_host();
-#ifdef _WIN32
- DWORD waitResult = WaitForSingleObject(configuration_data_mutex, INFINITE);
- assert(waitResult == WAIT_OBJECT_0);
- (void)waitResult;
-#else
- if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
- VSOMEIP_WARNING << "utility::request_client_id EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
- }
-
- pid_t pid = getpid();
- if (its_name == "" || _name == its_name) {
- if (the_configuration_data__->pid_ != 0) {
- if (pid != the_configuration_data__->pid_) {
- if (kill(the_configuration_data__->pid_, 0) == -1) {
- VSOMEIP_WARNING << "Routing Manager seems to be inactive. Taking over...";
- the_configuration_data__->routing_manager_host_ = 0x0000;
- }
- }
- }
- }
-#endif
-
- bool set_client_as_manager_host(false);
- if (its_name != "" && its_name == _name) {
- if (the_configuration_data__->routing_manager_host_ == 0x0000) {
- set_client_as_manager_host = true;
- } else {
- VSOMEIP_ERROR << "Routing manager with id " << the_configuration_data__->routing_manager_host_ << " already exists.";
-#ifdef _WIN32
- BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
- assert(releaseResult);
- (void)releaseResult;
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
- return ILLEGAL_CLIENT;
- }
- } else if (its_name == "" && the_configuration_data__->routing_manager_host_ == 0x0000) {
- set_client_as_manager_host = true;
- }
+void utility::remove_lockfile(const std::shared_ptr<configuration> &_config) {
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ if (!is_checked__) // No need to do anything as automatic
+ return;
- if (the_configuration_data__->max_used_client_ids_index_
- == the_configuration_data__->max_clients_) {
- VSOMEIP_ERROR << "Max amount of possible concurrent active"
- << " vsomeip applications reached (" << std::dec <<
- the_configuration_data__->max_clients_ << ").";
#ifdef _WIN32
- BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
- assert(releaseResult);
- (void)releaseResult;
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
- return ILLEGAL_CLIENT;
- }
-
- bool use_autoconfig = true;
- if (_name != "" && _client != ILLEGAL_CLIENT) { // preconfigured client id
- // check if application name has preconfigured client id in json
- const client_t its_preconfigured_client_id = _config->get_id(_name);
- if (its_preconfigured_client_id) {
- // preconfigured client id for application name present in json
- if (its_preconfigured_client_id == _client) {
- // preconfigured client id for application name present in json
- // and requested
- if (!is_used_client_id(_client, _config)) {
- use_autoconfig = false;
- }
- } else {
- // preconfigured client id for application name present in
- // json, but different client id requested
- if (!is_used_client_id(its_preconfigured_client_id, _config)) {
- // assign preconfigured client id if not already used
- _client = its_preconfigured_client_id;
- use_autoconfig = false;
- } else if (!is_used_client_id(_client, _config)) {
- // if preconfigured client id is already used and
- // requested is unused assign requested
- use_autoconfig = false;
- }
- }
- }
- }
+ if (lock_handle__ != INVALID_HANDLE_VALUE) {
+ if (CloseHandle(lock_handle__) == 0) {
+ VSOMEIP_ERROR << __func__ << ": CloseHandle failed."
+ << std::hex << GetLastError();
+ }
+ wchar_t its_tmp_folder[MAX_PATH];
+ if (GetTempPathW(MAX_PATH, its_tmp_folder)) {
+ std::wstring its_lockfile(its_tmp_folder);
+ std::string its_network(_config->get_network() + ".lck");
+ its_lockfile.append(its_network.begin(), its_network.end());
+ if (DeleteFileW(its_lockfile.c_str()) == 0) {
+ VSOMEIP_ERROR << __func__ << ": DeleteFileW failed: "
+ << its_lockfile << ": " << std::hex << GetLastError();
- if (use_autoconfig) {
- if (_client == ILLEGAL_CLIENT || is_used_client_id(_client, _config)) {
- if (the_configuration_data__->max_assigned_client_id_ != 0x00) {
- _client = the_configuration_data__->max_assigned_client_id_;
- } else {
- _client = the_configuration_data__->client_base_;
- }
}
- int increase_count = 0;
-
- while (_client <= the_configuration_data__->max_assigned_client_id_
- || _config->is_configured_client_id(_client)
- || is_used_client_id(_client, _config)) {
- if (_client + 1 > used_client_ids__[0] + the_configuration_data__->max_clients_) {
- _client = the_configuration_data__->client_base_;
- the_configuration_data__->max_assigned_client_id_ = the_configuration_data__->client_base_;
- } else {
- _client++;
- increase_count++;
- if (increase_count > the_configuration_data__->max_clients_) {
- VSOMEIP_ERROR << "Max amount of possible concurrent active"
- << " vsomeip applications reached (" << std::dec <<
- the_configuration_data__->max_clients_ << ").";
-#ifdef _WIN32
- BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
- assert(releaseResult);
- (void)releaseResult;
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
- return ILLEGAL_CLIENT;
- }
- }
- }
- the_configuration_data__->max_assigned_client_id_ = _client;
- }
-
- if (set_client_as_manager_host) {
- the_configuration_data__->routing_manager_host_ = _client;
-#ifndef _WIN32
- the_configuration_data__->pid_ = pid;
-#endif
+ } else {
+ VSOMEIP_ERROR << __func__ << ": Could not get temp folder."
+ << std::hex << GetLastError();
}
-
- used_client_ids__[the_configuration_data__->max_used_client_ids_index_] = _client;
- the_configuration_data__->max_used_client_ids_index_++;
-
-
-#ifdef _WIN32
- BOOL releaseResult = ReleaseMutex(configuration_data_mutex);
- assert(releaseResult);
- (void)releaseResult;
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
- return _client;
}
- return ILLEGAL_CLIENT;
-}
-
-void utility::release_client_id(client_t _client) {
- std::unique_lock<CriticalSection> its_lock(its_local_configuration_mutex__);
- if (the_configuration_data__ != nullptr) {
-#ifdef _WIN32
- WaitForSingleObject(configuration_data_mutex, INFINITE);
#else
- if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
- VSOMEIP_WARNING << "utility::release_client_id EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
- }
-#endif
- int i = 0;
- for (; i < the_configuration_data__->max_used_client_ids_index_; i++) {
- if (used_client_ids__[i] == _client) {
- break;
- }
- }
-
- if (i < the_configuration_data__->max_used_client_ids_index_) {
- for (; i < (the_configuration_data__->max_used_client_ids_index_ - 1); i++) {
- used_client_ids__[i] = used_client_ids__[i+1];
- }
- the_configuration_data__->max_used_client_ids_index_--;
- }
-#ifdef _WIN32
- ReleaseMutex(configuration_data_mutex);
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
+ std::string its_base_path(VSOMEIP_BASE_PATH + _config->get_network());
+ std::string its_lockfile(its_base_path + ".lck");
+
+ if (lock_fd__ != -1) {
+ if (close(lock_fd__) == -1) {
+ VSOMEIP_ERROR << __func__ << ": Could not close lock_fd__"
+ << std::strerror(errno);
+ }
}
-}
-
-bool utility::is_routing_manager_host(client_t _client) {
- if (the_configuration_data__ == nullptr) {
- VSOMEIP_ERROR << "utility::is_routing_manager_host: configuration data not available";
- return false;
- }
-
-#ifdef _WIN32
- WaitForSingleObject(configuration_data_mutex, INFINITE);
-#else
- if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
- VSOMEIP_WARNING << "utility::is_routing_manager_host EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
+ if (remove(its_lockfile.c_str()) == -1) {
+ VSOMEIP_ERROR << __func__ << ": Could not remove " << its_lockfile
+ << ": " << std::strerror(errno);
}
#endif
-
- bool is_routing_manager = (the_configuration_data__->routing_manager_host_ == _client);
-
-#ifdef _WIN32
- ReleaseMutex(configuration_data_mutex);
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
-
- return is_routing_manager;
+ is_checked__ = false;
}
-void utility::set_routing_manager_host(client_t _client) {
- if (the_configuration_data__ == nullptr) {
- VSOMEIP_ERROR << "utility::set_routing_manager_host: configuration data not available";
- return;
- }
-
-#ifdef _WIN32
- WaitForSingleObject(configuration_data_mutex, INFINITE);
-#else
- if (EOWNERDEAD == pthread_mutex_lock(&the_configuration_data__->mutex_)) {
- VSOMEIP_WARNING << "utility::set_routing_manager_host EOWNERDEAD";
- check_client_id_consistency();
- if (0 != pthread_mutex_consistent(&the_configuration_data__->mutex_)) {
- VSOMEIP_ERROR << "pthread_mutex_consistent() failed ";
- }
- }
-#endif
-
- the_configuration_data__->routing_manager_host_ = _client;
-
-#ifdef _WIN32
- ReleaseMutex(configuration_data_mutex);
-#else
- pthread_mutex_unlock(&the_configuration_data__->mutex_);
-#endif
+bool utility::exists(const std::string &_path) {
+ struct stat its_stat;
+ return (stat(_path.c_str(), &its_stat) == 0);
}
-
-inline bool utility::get_struct_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
- uint32_t its_length = 0;
- bool length_field_deployed(false);
- // [TR_SOMEIP_00080] d If the length of the length field is not specified, a length of 0
- // has to be assumed and no length field is in the message.
- if (length_field_deployed) {
- if (_buffer_size >= sizeof(uint32_t)) {
- std::memcpy(&its_length, _buffer, sizeof(uint32_t));
- _length = bswap_32(its_length);
- _buffer_size -= skip_struct_length_;
- _buffer += skip_struct_length_;
+bool utility::is_file(const std::string &_path) {
+ struct stat its_stat;
+ if (stat(_path.c_str(), &its_stat) == 0) {
+ if (its_stat.st_mode & S_IFREG)
return true;
- }
- } else {
- _length = 0;
- return true;
}
-
return false;
}
-inline bool utility::get_union_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
- uint32_t its_length = 0;
-
- // [TR_SOMEIP_00125] d If the Interface Specification does not specify the length of the
- // length field for a union, 32 bit length of the length field shall be used.
- if (_buffer_size >= sizeof(uint32_t)) {
- std::memcpy(&its_length, _buffer, sizeof(uint32_t));
- _length = bswap_32(its_length);
- _buffer_size -= skip_union_length_;
- _buffer += skip_union_length_;
- return true;
+bool utility::is_folder(const std::string &_path) {
+ struct stat its_stat;
+ if (stat(_path.c_str(), &its_stat) == 0) {
+ if (its_stat.st_mode & S_IFDIR)
+ return true;
}
return false;
}
-inline bool utility::get_array_length(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_length) {
- uint32_t its_length = 0;
-
- // [TR_SOMEIP_00106] d The layout of arrays with dynamic length basically is based on
- // the layout of fixed length arrays. To determine the size of the array the serialization
- // adds a length field (default length 32 bit) in front of the data, which counts the bytes
- // of the array. The length does not include the size of the length field. Thus, when
- // transporting an array with zero elements the length is set to zero.
- if (_buffer_size >= sizeof(uint32_t)) {
- std::memcpy(&its_length, _buffer, sizeof(uint32_t));
- _length = bswap_32(its_length);
- _buffer_size -= skip_array_length_;
- _buffer += skip_array_length_;
- return true;
- }
- return false;
+const std::string utility::get_base_path(
+ const std::shared_ptr<configuration> &_config) {
+ return std::string(VSOMEIP_BASE_PATH + _config->get_network() + "-");
}
-inline bool utility::is_range(const byte_t* &_buffer, uint32_t &_buffer_size) {
- uint32_t its_type = 0;
-
- // [TR_SOMEIP_00128] If the Interface Specification does not specify the length of the
- // type field of a union, 32 bit length of the type field shall be used.
- if (_buffer_size >= sizeof(uint32_t)) {
- std::memcpy(&its_type, _buffer, sizeof(uint32_t));
- its_type = bswap_32(its_type);
- _buffer_size -= skip_union_type_;
- _buffer += skip_union_type_;
- if (its_type == 0x02) {
- return true;
- } else {
- return false;
- }
+client_t
+utility::request_client_id(
+ const std::shared_ptr<configuration> &_config,
+ const std::string &_name, client_t _client) {
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ static const std::uint16_t its_max_num_clients = get_max_client_number(_config);
+
+ static const std::uint16_t its_diagnosis_mask = _config->get_diagnosis_mask();
+ static const std::uint16_t its_client_mask = static_cast<std::uint16_t>(~its_diagnosis_mask);
+ static const client_t its_masked_diagnosis_address = static_cast<client_t>(
+ (_config->get_diagnosis_address() << 8) & its_diagnosis_mask);
+ static const client_t its_biggest_client = its_masked_diagnosis_address | its_client_mask;
+ static const client_t its_smallest_client = its_masked_diagnosis_address;
+
+ if (next_client__ == VSOMEIP_CLIENT_UNSET) {
+ next_client__ = its_smallest_client;
}
- return false;
-}
-inline bool utility::parse_id_item(const byte_t* &_buffer, uint32_t& parsed_ids_bytes, ranges_t& its_ranges, uint32_t &_buffer_size) {
- // get "union IdItem" length
- uint32_t iditem_length = 0;
- if (get_union_length(_buffer, _buffer_size, iditem_length)) {
- // determine type of union
- uint16_t its_first = 0;
- uint16_t its_last = 0;
- if (is_range(_buffer, _buffer_size)) {
- // get range of instance IDs "struct IdRange" length
- uint32_t range_length = 0;
- if (get_struct_length(_buffer, _buffer_size, range_length)) {
- // read first and last instance range
- if (parse_range(_buffer, _buffer_size, its_first, its_last)) {
- its_ranges.insert(std::make_pair(its_first, its_last));
- } else {
- return false;
- }
+ if (_client != VSOMEIP_CLIENT_UNSET) { // predefined client identifier
+ const auto its_iterator = used_clients__.find(_client);
+ if (its_iterator == used_clients__.end()) { // unused identifier
+ used_clients__[_client] = _name;
+ return _client;
+ } else { // already in use
+
+ // The name matches the assigned name --> return client
+ // NOTE: THIS REQUIRES A CONSISTENT CONFIGURATION!!!
+ if (its_iterator->second == _name) {
+ return _client;
}
- } else {
- // a single instance ID
- if (parse_id(_buffer, _buffer_size, its_first)) {
- if (its_first != ANY_METHOD) {
- if (its_first != 0x00) {
- its_last = its_first;
- its_ranges.insert(std::make_pair(its_first, its_last));
- }
- } else {
- its_first = 0x01;
- its_last = 0xFFFE;
- its_ranges.insert(std::make_pair(its_first, its_last));
- }
- }
- }
- parsed_ids_bytes += (skip_union_length_type_ + iditem_length);
- }
- return true;
-}
-
-inline bool utility::parse_range(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_first, uint16_t &_last){
- uint16_t its_first = 0;
- uint16_t its_last = 0;
- if (_buffer_size >= sizeof(uint16_t) * 2) {
- if (parse_id(_buffer, _buffer_size, its_first)) {
- _first = its_first;
- }
- if (parse_id(_buffer, _buffer_size, its_last)) {
- _last = its_last;
- }
- if (_first != _last
- && (_first == ANY_METHOD || _last == ANY_METHOD)) {
- return false;
- }
- if (_first != 0x0 && _last != 0x00
- && _first <= _last) {
- if (_first == ANY_METHOD &&
- _last == ANY_METHOD) {
- _first = 0x01;
- _last = 0xFFFE;
- }
- return true;
- } else {
- if (_first == 0x00 && _last > _first
- && _last != ANY_METHOD) {
- _first = 0x01;
- return true;
- }
- return false;
+ VSOMEIP_WARNING << "Requested client identifier "
+ << std::setw(4) << std::setfill('0')
+ << std::hex << _client
+ << " is already used by application \""
+ << its_iterator->second
+ << "\".";
+ // intentionally fall through
}
}
- return false;
-}
-inline bool utility::parse_id(const byte_t* &_buffer, uint32_t &_buffer_size, uint16_t &_id) {
- uint16_t its_id = 0;
- if (_buffer_size >= sizeof(uint16_t)) {
- std::memcpy(&its_id, _buffer, sizeof(uint16_t));
- _id = bswap_16(its_id);
- _buffer_size -= id_width_;
- _buffer += id_width_;
- return true;
+ if (next_client__ == its_biggest_client) {
+ // start at beginning of client range again when the biggest client was reached
+ next_client__ = its_smallest_client;
}
- return false;
+ std::uint16_t increase_count = 0;
+ do {
+ next_client__ = (next_client__ & static_cast<std::uint16_t>(~its_client_mask)) // save diagnosis address bits
+ | (static_cast<std::uint16_t>((next_client__ // set all diagnosis address bits to one
+ | static_cast<std::uint16_t>(~its_client_mask)) + 1u) // and add one to the result
+ & its_client_mask); // set the diagnosis address bits to zero again
+ if (increase_count++ == its_max_num_clients) {
+ VSOMEIP_ERROR << __func__ << " no free client IDs left! "
+ "Max amount of possible concurrent active vsomeip "
+ "applications reached (" << std::dec << used_clients__.size()
+ << ").";
+ return VSOMEIP_CLIENT_UNSET;
+ }
+ } while (used_clients__.find(next_client__) != used_clients__.end()
+ || _config->is_configured_client_id(next_client__));
+
+ used_clients__[next_client__] = _name;
+ return next_client__;
}
-bool utility::parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid) {
- uint32_t its_uid = 0xffffffff;
- uint32_t its_gid = 0xffffffff;
-
- if (_buffer_size >= sizeof(uint32_t) * 2) {
- std::memcpy(&its_uid, _buffer, sizeof(uint32_t));
- _uid = bswap_32(its_uid);
-
- std::memcpy(&its_gid, _buffer + sizeof(uint32_t), sizeof(uint32_t));
- _gid = bswap_32(its_gid);
-
- _buffer_size -= (uid_width_ + gid_width_);
- _buffer += (uid_width_ + gid_width_);
- return true;
- }
- return false;
+void
+utility::release_client_id(client_t _client) {
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ used_clients__.erase(_client);
}
-bool utility::parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size, uint32_t &_uid, uint32_t &_gid, ::std::shared_ptr<policy> &_policy) {
- uint32_t its_uid = 0xffffffff;
- uint32_t its_gid = 0xffffffff;
- bool has_error(false);
-
- // get user ID String
- if (parse_uid_gid(_buffer, _buffer_size, its_uid, its_gid)) {
- _uid = its_uid;
- _gid = its_gid;
-
- // policy elements
- std::pair<uint32_t, uint32_t> its_uid_range, its_gid_range;
- std::set<std::pair<uint32_t, uint32_t>> its_uids, its_gids;
-
- // fill uid and gid range
- std::get<0>(its_uid_range) = its_uid;
- std::get<1>(its_uid_range) = its_uid;
- std::get<0>(its_gid_range) = its_gid;
- std::get<1>(its_gid_range) = its_gid;
- its_uids.insert(its_uid_range);
- its_gids.insert(its_gid_range);
-
- _policy->ids_.insert(std::make_pair(its_uids, its_gids));
- _policy->allow_who_ = true;
- _policy->allow_what_ = true;
-
- // get struct AclUpdate
- uint32_t acl_length = 0;
- if (get_struct_length(_buffer, _buffer_size, acl_length)) {
- // get requests array length
- uint32_t requests_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, requests_array_length)) {
- // loop through requests array consisting of n x "struct Request"
- uint32_t parsed_req_bytes = 0;
- while (parsed_req_bytes + skip_struct_length_ <= requests_array_length) {
- // get request struct length
- uint32_t req_length = 0;
- if (get_struct_length(_buffer, _buffer_size, req_length)) {
- if (req_length != 0)
- parsed_req_bytes += skip_struct_length_;
-
- uint16_t its_service_id = 0;
- ids_t its_instance_method_ranges;
- // get serviceID
- if (!parse_id(_buffer, _buffer_size, its_service_id)) {
- has_error = true;
- } else {
- if (its_service_id == 0x00
- || its_service_id == 0xFFFF) {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
- << its_service_id << " is not allowed!";
- return false;
- }
- // add length of serviceID
- parsed_req_bytes += id_width_;
- }
-
- // get instances array length
- uint32_t instances_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, instances_array_length)) {
- // loop trough instances array consisting of n x "struct Instance"
- uint32_t parsed_inst_bytes = 0;
- while (parsed_inst_bytes + skip_struct_length_ <= instances_array_length) {
- // get instance struct length
- uint32_t inst_length = 0;
- if (get_struct_length(_buffer, _buffer_size, inst_length)) {
- if (inst_length != 0)
- parsed_inst_bytes += skip_struct_length_;
-
- ranges_t its_instance_ranges;
- ranges_t its_method_ranges;
- // get "IdItem[] ids" array length
- uint32_t ids_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
- uint32_t parsed_ids_bytes = 0;
- while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
- if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
- return false;
- }
- }
- parsed_inst_bytes += (skip_array_length_ + ids_array_length);
- }
- // get "IdItem[] methods" array length
- uint32_t methods_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, methods_array_length)) {
- uint32_t parsed_method_bytes = 0;
- while (parsed_method_bytes + skip_struct_length_ <= methods_array_length) {
- if (!parse_id_item(_buffer, parsed_method_bytes, its_method_ranges, _buffer_size)) {
- return false;
- }
- }
- if (!its_instance_ranges.empty() && !its_method_ranges.empty()) {
- its_instance_method_ranges.insert(std::make_pair(its_instance_ranges, its_method_ranges));
- }
- parsed_inst_bytes += (skip_array_length_ + methods_array_length);
- }
- }
- }
- parsed_req_bytes += (skip_array_length_ + instances_array_length);
- }
- if (!its_instance_method_ranges.empty()) {
- _policy->services_.insert(
- std::make_pair(its_service_id, its_instance_method_ranges));
- }
- }
- }
- }
- // get offers array length
- uint32_t offers_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, offers_array_length)){
- // loop through offers array
- uint32_t parsed_offers_bytes = 0;
- while (parsed_offers_bytes + skip_struct_length_ <= offers_array_length) {
- // get service ID
- uint16_t its_service_id = 0;
- ranges_t its_instance_ranges;
- // get serviceID
- if (!parse_id(_buffer, _buffer_size, its_service_id)) {
- has_error = true;
- } else {
- if (its_service_id == 0x00
- || its_service_id == 0xFFFF) {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with service ID: 0x"
- << its_service_id << " is not allowed!";
- return false;
- }
- // add length of serviceID
- parsed_offers_bytes += id_width_;
- }
-
- // get "IdItem[] ids" array length
- uint32_t ids_array_length = 0;
- if (get_array_length(_buffer, _buffer_size, ids_array_length)) {
- uint32_t parsed_ids_bytes = 0;
- while (parsed_ids_bytes + skip_struct_length_ <= ids_array_length) {
- if (!parse_id_item(_buffer, parsed_ids_bytes, its_instance_ranges, _buffer_size)) {
- return false;
- }
- }
- parsed_offers_bytes += (skip_array_length_ + ids_array_length);
- }
- if (!its_instance_ranges.empty()) {
- _policy->offers_.insert(
- std::make_pair(its_service_id, its_instance_ranges));
- }
- }
- }
- } else {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy with empty request / offer section is not allowed!";
- has_error = true;
- }
- } else {
- VSOMEIP_WARNING << std::hex << "vSomeIP Security: Policy without UID / GID is not allowed!";
- has_error = true;
- }
+std::set<client_t>
+utility::get_used_client_ids() {
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ std::set<client_t> its_used_clients;
+ for (const auto& c : used_clients__)
+ its_used_clients.insert(c.first);
+ return its_used_clients;
+}
- if (!has_error)
- return true;
- else
- return false;
+void utility::reset_client_ids() {
+ std::lock_guard<std::mutex> its_lock(mutex__);
+ used_clients__.clear();
+ next_client__ = VSOMEIP_CLIENT_UNSET;
}
-void utility::check_client_id_consistency() {
- if (1 < the_configuration_data__->max_used_client_ids_index_) {
- client_t prevID = used_client_ids__[0];
- int i = 1;
- for (; i < the_configuration_data__->max_used_client_ids_index_; i++) {
- const client_t currID = used_client_ids__[i];
- if (prevID == currID) {
- break;
- }
- prevID = currID;
- }
- if (i < the_configuration_data__->max_used_client_ids_index_) {
- for (; i < (the_configuration_data__->max_used_client_ids_index_ - 1); i++) {
- used_client_ids__[i] = used_client_ids__[i+1];
- }
- the_configuration_data__->max_used_client_ids_index_--;
- }
- }
-}
-std::uint16_t utility::get_max_number_of_clients(std::uint16_t _diagnosis_max) {
+std::uint16_t utility::get_max_client_number(
+ const std::shared_ptr<configuration> &_config) {
std::uint16_t its_max_clients(0);
const int bits_for_clients =
#ifdef _WIN32
@@ -1118,22 +274,11 @@ std::uint16_t utility::get_max_number_of_clients(std::uint16_t _diagnosis_max) {
#else
__builtin_popcount(
#endif
- static_cast<std::uint16_t>(~_diagnosis_max));
+ static_cast<std::uint16_t>(~_config->get_diagnosis_mask()));
for (int var = 0; var < bits_for_clients; ++var) {
its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
}
return its_max_clients;
}
-const uint8_t utility::uid_width_ = sizeof(uint32_t);
-const uint8_t utility::gid_width_ = sizeof(uint32_t);
-const uint8_t utility::id_width_ = sizeof(uint16_t);
-const uint8_t utility::range_width_ = sizeof(uint32_t);
-
-const uint8_t utility::skip_union_length_ = sizeof(uint32_t);
-const uint8_t utility::skip_union_type_ = sizeof(uint32_t);
-const uint8_t utility::skip_union_length_type_ = sizeof(uint32_t) + sizeof(uint32_t);
-const uint8_t utility::skip_struct_length_ = sizeof(uint32_t);
-const uint8_t utility::skip_array_length_ = sizeof(uint32_t);
-
-} // namespace vsomeip
+} // namespace vsomeip_v3
diff --git a/interface/compat/vsomeip/application.hpp b/interface/compat/vsomeip/application.hpp
new file mode 100644
index 0000000..0d4b671
--- /dev/null
+++ b/interface/compat/vsomeip/application.hpp
@@ -0,0 +1,1093 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_APPLICATION_HPP
+#define VSOMEIP_APPLICATION_HPP
+
+#include <chrono>
+#include <memory>
+#include <set>
+#include <map>
+#include <vector>
+
+#include "../../compat/vsomeip/constants.hpp"
+#include "../../compat/vsomeip/enumeration_types.hpp"
+#include "../../compat/vsomeip/function_types.hpp"
+#include "../../compat/vsomeip/handler.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+class configuration;
+class event;
+class payload;
+struct policy;
+
+/**
+ * \defgroup vsomeip
+ *
+ * @{
+ */
+
+/**
+ *
+ * \brief This class contains the public API of the vsomeip implementation.
+ *
+ * Due to its heavy resource footprint, it should exist once per client and can
+ * be instantiated using the API of @ref runtime. It manages the lifecycle of
+ * the vsomeip client and allocates all resources needed to communicate.
+ *
+ */
+class application {
+public:
+ virtual ~application() {}
+
+ /**
+ *
+ * \brief Returns the name of the application as given during creation
+ *
+ * The application name is used to identify the application. It is either
+ * set explicitely when the application object is created or configured by
+ * the environment variable VSOMEIP_APPLICATION_NAME.
+ *
+ * Note: A user application can use several vsomeip application objects in
+ * parallel. The application names must be set explicitly in this case
+ * because VSOMEIP_APPLICATION_NAME only allows to specify a single name.
+ *
+ *
+ * \return Application name
+ *
+ */
+ virtual const std::string & get_name() const = 0;
+
+ /**
+ *
+ * \brief Returns the client identifier that was assigned to the
+ * application object.
+ *
+ * Each request sent by and each response sent to the application contain
+ * the client identifier as part of the request identifier within the
+ * SOME/IP message header. The client identifier can either be configured
+ * by the configured as part of the application node within a vsomeip
+ * configuration file or is automatically set to an unused client
+ * identifier by vsomeip. If the client identifier is automatically set,
+ * its high byte will always match the diagnosis address of the device.
+ *
+ * \return Client ID of application
+ *
+ */
+ virtual client_t get_client() const = 0;
+
+ /**
+ *
+ * \brief Does nothing.
+ *
+ * This method exists for compatibility reasons only. It is a null
+ * operation and will be removed with the next major vsomeip version.
+ *
+ */
+ virtual void set_configuration(const std::shared_ptr<configuration> _configuration) = 0;
+
+ /**
+ *
+ * \brief Initializes the application.
+ *
+ * The init method must be called first after creating a vsomeip
+ * application and executes the following steps to initialize it:
+ * - Loading the configuration from a dynamic module
+ * - Loading the configuration from a .json file or
+ * - Loading the configuration from compiled data (not yet available)
+ * - Determining routing configuration and initialization of the routing
+ * itself
+ * - Installing signal handlers
+ *
+ */
+ virtual bool init() = 0;
+
+ /**
+ *
+ * \brief Starts message processing.
+ *
+ * This method must be called after init to start message processing. It
+ * will block until the message processing is terminated using the @ref
+ * stop method or by receiving signals. It processes messages received
+ * via the sockets and uses registered callbacks to pass them to the user
+ * application.
+ *
+ */
+ virtual void start() = 0;
+
+ /**
+ *
+ * \brief Stops message processing.
+ *
+ * This method stops message processing. Thus, @ref start will return
+ * after a call to stop.
+ *
+ */
+ virtual void stop() = 0;
+
+ /**
+ *
+ * \brief Offers a SOME/IP service instance.
+ *
+ * The user application must call this method for each service it offers
+ * to register it at the vsomeip routing component, which makes the
+ * service visible to interested clients. Dependent on the configuration
+ * the service is available internally only or internally and externally.
+ * To offer a service to the external network, the configuration must
+ * contain a port for the offered service instance. If no such port
+ * configuration is provided, the service is not visible outside the
+ * device.
+ *
+ * \param _service Service identifier of the offered service interface.
+ * \param _instance Instance identifier of the offered service instance.
+ * \param _major Major service version (Default: 0).
+ * \param _minor Minor service version (Default: 0).
+ *
+ */
+ virtual void offer_service(service_t _service, instance_t _instance,
+ major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
+ DEFAULT_MINOR) = 0;
+
+ /**
+ *
+ * \brief Stops offering a SOME/IP service instance.
+ *
+ * The user application must call this method to withdraw a service offer.
+ *
+ * \param _service Service identifier of the offered service interface.
+ * \param _instance Instance identifer of the offered service instance.
+ * \param _major Major service version (Default: 0).
+ * \param _minor Minor service version (Default: 0).
+ *
+ */
+ virtual void stop_offer_service(service_t _service, instance_t _instance,
+ major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
+ DEFAULT_MINOR) = 0;
+
+ /**
+ *
+ * \brief Offers a SOME/IP event or field.
+ *
+ * A user application must call this method for each event/field it wants
+ * to offer. The event is registered at the vsomeip routing component that
+ * enables other applications to subscribe to the event/field as well as
+ * to get and set the field value.
+ *
+ * \param _service Service identifier of the interface containing the
+ * event.
+ * \param _instance Instance identifier of the interface containing the
+ * event.
+ * \param _event Event identifier of the offered event.
+ * \param _eventgroups List of eventgroup identifiers of the eventgroups
+ * that contain the event.
+ * \param _is_field Selector for event or field.
+ *
+ */
+ virtual void offer_event(service_t _service,
+ instance_t _instance, event_t _event,
+ const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field) = 0;
+
+ /**
+ *
+ * \brief Stops offering a SOME/IP event or field.
+ *
+ * A user application must call this method to withdraw the offer of an
+ * event or field.
+ *
+ * \param _service Service identifier of the interface that contains the
+ * event
+ * \param _instance Instance identifier of the interface that contains the
+ * event
+ * \param _event Event identifier of the offered event.
+ *
+ */
+ virtual void stop_offer_event(service_t _service,
+ instance_t _instance, event_t _event) = 0;
+
+ /**
+ *
+ * \brief Registers the application as client of a service instance.
+ *
+ * A user application must call this method for each service instance it
+ * wants to use. The request is stored within the routing component and the
+ * application is registered as client for the service as soon as the
+ * service instance becomes available.
+ *
+ * \param _service Service identifier of the requested service interface.
+ * \param _instance Instance identifier of the requested service instance.
+ * \param _major Major service version (Default: 0xFF).
+ * \param _minor Minor service version (Default: 0xFFFFFF).
+ * \param _use_exclusive_proxy Create an IP endpoint that is exclusively
+ * used for the communication of this application to the service instance.
+ *
+ */
+ virtual void request_service(service_t _service, instance_t _instance,
+ major_version_t _major = ANY_MAJOR,
+ minor_version_t _minor = ANY_MINOR,
+ bool _use_exclusive_proxy = false) = 0;
+
+ /**
+ *
+ * \brief Unregister the application as client of a service instance.
+ *
+ * A user application should call this method if it does not request to
+ * use the service instance any longer. The method unregisters the request
+ * a the routing component, which removes the service instance from the
+ * list of requested service instances if the call releases the last
+ * existing request for the service instance. This is important for
+ * external service instances, as the SOME/IP Service Discovery can avoid
+ * to send unnecessary Find messages.
+ *
+ * \param _service Service identifier of the offered service interface.
+ * \param _instance Instance identifier of the offered service instance.
+ *
+ */
+ virtual void release_service(service_t _service, instance_t _instance) = 0;
+
+ /**
+ *
+ * \brief Registers the application as user of an event or field.
+ *
+ * A user application must call this method before being able to receive
+ * event or field data. The method registers the event or field at the
+ * routing component.
+ *
+ * \param _service Service identifier of the interface that contains the
+ * event.
+ * \param _instance Instance identifier of the interface that contains the
+ * event.
+ * \param _event Event identifier of the event.
+ * \param _eventgroups List of Eventgroup identifiers of the eventgroups
+ * that contain the event.
+ * \param _is_field Pure event (false) or field (true).
+ *
+ */
+ virtual void request_event(service_t _service, instance_t _instance,
+ event_t _event, const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field) = 0;
+ /**
+ *
+ * \brief Unregister the application as user of an event or field.
+ *
+ * Unregister the application as user of an event or field and completely
+ * removes the event/field if the application is the last existing user.
+ *
+ * \param _service Service identifier of the interface that contains the
+ * event or field.
+ * \param _instance Instance identifier of the instance that contains the
+ * event or field.
+ * \param _event Event identifier of the event or field.
+ * .
+ */
+ virtual void release_event(service_t _service, instance_t _instance,
+ event_t _event) = 0;
+
+ /**
+ *
+ * \brief Subscribes to an eventgroup.
+ *
+ * A user application must call this function to subscribe to an eventgroup.
+ * Before calling subscribe it must register all events it interested in by
+ * calls to @ref request_event. The method additionally allows to specify
+ * a specific event. If a specific event is specified, all other events of
+ * the eventgroup are not received by the application.
+ *
+ * Note: For external services, providing a specific event does not change
+ * anything regarding the message routing. The specific event is only used
+ * to filter incoming events and to determine which initial events must be
+ * sent.
+ *
+ * \param _service Service identifier of the service that contains the
+ * eventgroup.
+ * \param _instance Instance identifier of the service that contains the
+ * eventgroup.
+ * \param _eventgroup Eventgroup identifier of the eventgroup.
+ * \param _major Major version number of the service.
+ * \param _subscription_type Specifies how the events shall be received.
+ * \param _event All (Default) or a specific event.
+ *
+ */
+ virtual void subscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, major_version_t _major = DEFAULT_MAJOR,
+ subscription_type_e _subscription_type = subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
+ event_t _event = ANY_EVENT) = 0;
+
+ /**
+ *
+ * \brief Unsubscribes from an eventgroup.
+ *
+ * \param _service Service identifier of the service that contains the
+ * eventgroup.
+ * \param _instance Instance identifier of the service that contains the
+ * eventgroup.
+ * \param _eventgroup Eventgroup identifier of the eventgroup.
+ *
+ */
+ virtual void unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup) = 0;
+
+ /**
+ *
+ * \brief Retrieve for the availability of a service instance.
+ *
+ * If the version is also given, the result will only be true if the
+ * service instance is available in that specific version.
+ *
+ * \param _service Service identifier of the service instance.
+ * \param _instance Instance identifier of the service instance.
+ * \param _major Major interface version. Use ANY_MAJOR to ignore the
+ * major version.
+ * \param _minor Minor interface version. Use ANY_MINOR to ignore the
+ * minor version.
+ *
+ */
+ virtual bool is_available(service_t _service, instance_t _instance,
+ major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) const = 0;
+
+ /**
+ *
+ * \brief Sends a message.
+ *
+ * Serializes the specified message object, determines the taget and sends
+ * the message to the target. For requests, the request identifier is
+ * automatically built from the client identifier and the session
+ * identifier.
+ *
+ * \param _message Message object.
+ * \param _flush If set to true, the message is immediately sent. Otherwise
+ * the message might be deferred and sent together with other messages.
+ *
+ */
+ virtual void send(std::shared_ptr<message> _message, bool _flush = true) = 0;
+
+ /**
+ *
+ * \brief Fire an event or field notification.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ *
+ */
+ virtual void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload) const = 0;
+
+ /**
+ *
+ * \brief Fire an event to a specific client.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ * \param _client Target client.
+ *
+ */
+ virtual void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client) const = 0;
+
+ /**
+ *
+ * \brief Register a state handler with the vsomeip runtime.
+ *
+ * The state handler tells if this client is successfully [de]registered
+ * at the central vsomeip routing component. This is called during the
+ * @ref start and @ref stop methods of this class to inform the user
+ * application about the registration state.
+ *
+ * \param _handler Handler function to be called on state change.
+ *
+ */
+ virtual void register_state_handler(state_handler_t _handler) = 0;
+
+ /**
+ *
+ * \brief Unregister the state handler.
+ *
+ */
+ virtual void unregister_state_handler() = 0;
+
+ /**
+ *
+ * \brief Registers a handler for the specified method or event.
+ *
+ * A user application must call this method to register callbacks for
+ * for messages that match the specified service, instance, method/event
+ * pattern. It is possible to specify wildcard values for all three
+ * identifiers arguments.
+ *
+ * Notes:
+ * - Only a single handler can be registered per service, instance,
+ * method/event combination.
+ * - A subsequent call will overwrite an existing registration.
+ * - Handler registrations containing wildcards can be active in parallel
+ * to handler registrations for specific service, instance, method/event
+ * combinations.
+ *
+ * \param _service Service identifier of the service that contains the
+ * method or event. Can be set to ANY_SERVICE to register a handler for
+ * a message independent from a specific service.
+ * \param _instance Instance identifier of the service instance that
+ * contains the method or event. Can be set to ANY_INSTANCE to register
+ * a handler for a message independent from a specific service.
+ * \param _method Method/Event identifier of the method/event that is
+ * to be handled. Can be set to ANY_METHOD to register a handler for
+ * all methods and events.
+ * \param _handler Callback that will be called if a message arrives
+ * that matches the specified service, instance and method/event
+ * parameters.
+ *
+ */
+ virtual void register_message_handler(service_t _service,
+ instance_t _instance, method_t _method,
+ message_handler_t _handler) = 0;
+ /**
+ *
+ * \brief Unregisters the message handler for the specified service
+ * method/event notification.
+ *
+ * \param _service Service identifier of the service that contains the
+ * method or event. Can be set to ANY_SERVICE to unregister a handler for
+ * a message independent from a specific service.
+ * \param _instance Instance identifier of the service instance that
+ * contains the method or event. Can be set to ANY_INSTANCE to unregister
+ * a handler for a message independent from a specific service.
+ * \param _method Method/Event identifier of the method/event that is
+ * to be handled. Can be set to ANY_METHOD to unregister a handler for
+ * all methods and events.
+ */
+ virtual void unregister_message_handler(service_t _service,
+ instance_t _instance, method_t _method) = 0;
+
+ /**
+ *
+ * \brief Register a callback that is called when service instances
+ * availability changes.
+ *
+ * This method allows for the registration of callbacks that are called
+ * whenever a service appears or disappears. It is possible to specify
+ * wildcards for service, instance and/or version. Additionally, the
+ * version specification is optional and defaults to DEFAULT_MAJOR
+ * /DEFAULT_MINOR.
+ *
+ * \param _service Service identifier of the service instance whose
+ * availability shall be reported. Can be set to ANY_SERVICE.
+ * \param _instance Instance identifier of the service instance whose
+ * availability shall be reported. Can be set to ANY_INSTANCE.
+ * \param _handler Callback to be called if availability changes.
+ * \param _major Major service version. The parameter defaults to
+ * DEFAULT_MAJOR and can be set to ANY_MAJOR.
+ * \param _minor Minor service version. The parameter defaults to
+ * DEFAULT_MINOR and can be set to ANY_MINOR.
+ *
+ */
+ virtual void register_availability_handler(service_t _service,
+ instance_t _instance, availability_handler_t _handler,
+ major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0;
+
+ /**
+ *
+ * \brief Unregister an availability callback.
+ *
+ * \param _service Service identifier of the service instance whose
+ * availability shall be reported. Can be set to ANY_SERVICE.
+ * \param _instance Instance identifier of the service instance whose
+ * availability shall be reported. Can be set to ANY_INSTANCE.
+ * \param _handler Callback to be called if availability changes.
+ * \param _major Major service version. The parameter defaults to
+ * DEFAULT_MAJOR and can be set to ANY_MAJOR.
+ * \param _minor Minor service version. The parameter defaults to
+ * DEFAULT_MINOR and can be set to ANY_MINOR. *
+ */
+ virtual void unregister_availability_handler(service_t _service,
+ instance_t _instance,
+ major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0;
+
+ /**
+ *
+ * \brief Registers a subscription handler.
+ *
+ * A subscription handler is called whenever the subscription state of an
+ * eventgroup changes. The callback is called with the client identifier
+ * and a boolean that indicates whether the client subscribed or
+ * unsubscribed.
+ *
+ * \param _service Service identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _instance Instance identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * subscription state is to be monitored.
+ * \param _handler Callback that shall be called.
+ *
+ */
+ virtual void register_subscription_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ subscription_handler_t _handler) = 0;
+
+ /**
+ *
+ * \brief Unregister a subscription handler.
+ *
+ * \param _service Service identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _instance Instance identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * subscription state is to be monitored.
+ *
+ */
+ virtual void unregister_subscription_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup) = 0;
+
+ // [Un]Register handler for subscription errors
+ /**
+ *
+ * \brief Allows for the registration of a subscription error handler.
+ *
+ * This handler is called whenever a subscription request for an eventgroup
+ * was either accepted or rejected. The respective callback is called with
+ * ether OK (0x00) or REJECTED (0x07).
+ *
+ * \param _service Service identifier of service instance whose
+ * subscription error state is to be monitored.
+ * \param _instance Instance identifier of service instance whose
+ * subscription error state is to be monitored.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * subscription error state is to be monitored.
+ * \param _handler Callback that shall be called.
+ *
+ */
+ virtual void register_subscription_error_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup,
+ error_handler_t _handler) = 0;
+
+ /**
+ *
+ * \brief Removes a registered subscription error callback.
+ *
+ * \param _service Service identifier of service instance whose
+ * error callback shall be removed.
+ * \param _instance Instance identifier of service instance whose
+ * error callback shall be removed.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * error callback shall be removed.
+ *
+ */
+ virtual void unregister_subscription_error_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup) = 0;
+
+ /**
+ *
+ * \brief Unregister all registered handlers.
+ *
+ */
+ virtual void clear_all_handler() = 0;
+
+ /**
+ *
+ * \brief This method tells whether or not this application controls the
+ * message routing.
+ *
+ * The application that controls the routing hosts the routing manager
+ * and (optionally) loads the Service Discovery component.
+ *
+ * \return true, if this is the central routing instance, and false
+ * otherwise
+ *
+ */
+ virtual bool is_routing() const = 0;
+
+ /**
+ *
+ * \brief Offers a SOME/IP event or field.
+ *
+ * A user application must call this method for each event/field it wants
+ * to offer. The event is registered at the vsomeip routing component that
+ * enables other applications to subscribe to the event/field as well as
+ * to get and set the field value.
+ *
+ * This version of offer_event adds some additional functionalities:
+ * - It is possible to configure a cycle time. The notification message of
+ * this event is then resent cyclically.
+ * - The parameter _change_resets_cycle is available to control how event
+ * notification works in case the data is updated by the application. If
+ * set to true, an update of the data immediately leads to a
+ * notification. Otherwise, the updated data is sent only after the
+ * expiration of the cycle time.
+ * - It is possible to specify callback function that can be used to
+ * implement a predicate that determines whether or not two event values
+ * are considered different. Field notifications are only sent if the
+ * predicate evaluates to true (or if a notify method is called with the
+ * force flag being set).
+ *
+ * \param _service Service identifier of the interface containing the
+ * event.
+ * \param _instance Instance identifier of the interface containing the
+ * event.
+ * \param _event Event identifier of the offered event.
+ * \param _eventgroups List of eventgroup identifiers of the eventgroups
+ * that contain the event.
+ * \param _is_field Selector for event or field.
+ * \param _cycle Sets the cycle time of the event. If nonzero, data is
+ * resent cyclically after the cycle time expired.
+ * \param _change_resets_cycle Tells if a change immediately leads to
+ * a notification.
+ * \param _epsilon_change_func Predicate that determines if two given
+ * payloads are considered different.
+ *
+ * Note: The different versions of offer_event exist for compatibility
+ * reasons. They will be merged with the next major vsomeip version.
+ */
+ virtual void offer_event(service_t _service,
+ instance_t _instance, event_t _event,
+ const std::set<eventgroup_t> &_eventgroups,
+ bool _is_field,
+ std::chrono::milliseconds _cycle,
+ bool _change_resets_cycle,
+ const epsilon_change_func_t &_epsilon_change_func) = 0;
+
+ /**
+ *
+ * \brief Fire an event or field notification.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ * \param _force Forces the notification to be sent (even if the event
+ * is a field and the value did not change).
+ *
+ * Note: The different versions of notify do exist for compatibility
+ * reasons. They will be merged with the next major vsomeip release.
+ */
+ virtual void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force) const = 0;
+
+ /**
+ *
+ * \brief Fire an event or field notification.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ * \param _client Target client.
+ * \param _force Forces the notification to be sent (even if the event
+ * is a field and the value did not change).
+ *
+ * Note: The different versions of notify_one do exist for compatibility
+ * reasons. They will be merged with the next major vsomeip release.
+ */
+ virtual void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force) const = 0;
+
+ typedef std::map<service_t, std::map<instance_t, std::map<major_version_t, minor_version_t >>> available_t;
+ /**
+ * \brief Returns all available instances that match the given combination
+ * of service, instance and version.
+ *
+ * This method checks the availability of the service instances that
+ * match the specified combination of service, instance and version
+ * parameters. If at least one matching service instance is available,
+ * the method returns true, otherwise it returns false. All available
+ * service instances are returned to the caller by filling the
+ * _available parameter.
+ *
+ * \param _available Map that is filled with the available instances.
+ * \param _service Service identifier that specifies which service(s)
+ * are checked.
+ * \param _instance Instance identifier that specifies which instance(s)
+ * are checked.
+ * \param _major_version Major version(s) of the service instances that
+ * are checked
+ * \param _minor_version Minor version(s) of the service instance that
+ * are checked
+ */
+ virtual bool are_available(available_t &_available,
+ service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
+ major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
+
+ /**
+ *
+ * \brief Fire an event or field notification.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ * \param _force Forces the notification to be sent (even if the event
+ * is a field and the value did not change).
+ * \param _flush Must be set to ensure the event is immediately fired.
+ *
+ * Note: The different versions of notify do exist for compatibility
+ * reasons. They will be merged with the next major vsomeip release.
+ */
+ virtual void notify(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force, bool _flush) const = 0;
+
+ /**
+ *
+ * \brief Fire an event or field notification.
+ *
+ * The specified event is updated with the specified payload data.
+ * Dependent on the type of the event, the payload is distributed to all
+ * notified clients (always for events, only if the payload has changed
+ * for fields).
+ *
+ * Note: Prior to using this method, @ref offer_event has to be called by
+ * the service provider.
+ *
+ * \param _service Service identifier of the service that contains the
+ * event.
+ * \param _instance Instance identifier of the service instance that
+ * holds the event.
+ * \param _event Event identifier of the event.
+ * \param _payload Serialized payload of the event.
+ * \param _client Target client.
+ * \param _force Forces the notification to be sent (even if the event
+ * is a field and the value did not change).
+ * \param _flush Must be set to ensure the event is immediately fired.
+ *
+ * Note: The different versions of notify_one do exist for compatibility
+ * reasons. They will be merged with the next major vsomeip release.
+ */
+ virtual void notify_one(service_t _service, instance_t _instance,
+ event_t _event, std::shared_ptr<payload> _payload,
+ client_t _client, bool _force, bool _flush) const = 0;
+
+ /**
+ * \brief Set the current routing state.
+ *
+ * The routing state impacts the behavior of the SOME/IP Service Discovery component. It
+ * can be set to RUNNING, SUSPENDED, RESUMED, SHUTDOWN or UNKNOWN. Applications only need
+ * to set the routing state if they are responsible for controlling the routing manager.
+ * In most environments the vsomeip daemon is controlling the routing manager.
+ *
+ * \param _routing_state the current routing state
+ */
+ virtual void set_routing_state(routing_state_e _routing_state) = 0;
+
+ /**
+ *
+ * \brief Unsubscribes from an eventgroup.
+ *
+ * \param _service Service identifier of the service that contains the
+ * eventgroup.
+ * \param _instance Instance identifier of the service that contains the
+ * eventgroup.
+ * \param _eventgroup Eventgroup identifier of the eventgroup.
+ * \param _event Event to unsubscribe (pass ANY_EVENT for all events of the eventgroup)
+ */
+ virtual void unsubscribe(service_t _service, instance_t _instance,
+ eventgroup_t _eventgroup, event_t _event) = 0;
+
+
+ /**
+ *
+ * \brief Registers a subscription status listener.
+ *
+ * When registered such a handler it will be called for
+ * every application::subscribe call.
+ *
+ * This method is intended to replace the application::
+ * register_subscription_error_handler call in future releases.
+ *
+ * \param _service Service identifier of the service that is subscribed to.
+ * \param _instance Instance identifier of the service that is subscribed to.
+ * \param _eventgroup Eventgroup identifier of the eventgroup is subscribed to.
+ * \param _event Event indentifier of the event is subscribed to.
+ * \param _handler A subscription status handler which will be called by vSomeIP
+ * as a follow of application::subscribe.
+ */
+ virtual void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler) = 0;
+
+ /**
+ *
+ * \brief Registers a subscription status listener.
+ *
+ * When registered such a handler it will be called for
+ * every application::subscribe call.
+ *
+ * This method is intended to replace the application::
+ * register_subscription_error_handler call in future releases.
+ *
+ * \param _service Service identifier of the service that is subscribed to.
+ * \param _instance Instance identifier of the service that is subscribed to.
+ * \param _eventgroup Eventgroup identifier of the eventgroup is subscribed to.
+ * \param _event Event indentifier of the event is subscribed to.
+ * \param _handler A subscription status handler which will be called by vSomeIP
+ * as a follow of application::subscribe.
+ * \param _is_selective Flag to enable calling the provided handler if the
+ * subscription is answered with a SUBSCRIBE_NACK.
+ */
+ virtual void register_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event,
+ subscription_status_handler_t _handler, bool _is_selective) = 0;
+
+ /**
+ *
+ * \brief Returns all registered services / instances on this node in an async callback.
+ *
+ * When called with a handler of type offered_services_handler_t,
+ * all at the routing manager registered services on this node get returned in a vector of
+ * service / instance pairs depending on the given _offer_type.
+ *
+ * \param _offer_type type of offered services to be returned (OT_LOCAL = 0x00, OT_REMOTE = 0x01, OT_ALL = 0x02)
+ * \param offered_services_handler_t handler which gets called with a vector of service instance pairs that are currently offered
+ */
+ virtual void get_offered_services_async(offer_type_e _offer_type, offered_services_handler_t _handler) = 0;
+
+ /**
+ *
+ * \brief Sets a handler to be called cyclically for watchdog monitoring.
+ *
+ * The handler shall be called in the given interval, but not before start()
+ * has been called, and not after call to stop() returned.
+ *
+ * In case the application is running, i.e. start() succeeded, but the
+ * handler will not be invoke within the (approximate) interval it may
+ * be assumed that I/O or internal dispatcher threads are non-functional.
+ *
+ * \remark Accuracy of call interval is limited by clock/timer granularity
+ * or scheduling effects, thus it may underrun or overrun by small
+ * amount.
+ *
+ * \note Only one handler can be active at the time, thus last handler set
+ * by calling this function will be invoked.
+ *
+ * \note To disable calling an active handler, invoke this method again,
+ * passing nullptr as _handler and/or std::chrono::seconds::zero()
+ * as _interval.
+ *
+ * \param _handler A watchdog handler, pass nullptr to deactivate.
+ * \param _interval Call interval in seconds, pass std::chrono::seconds::zero() to deactivate.
+ */
+ virtual void set_watchdog_handler(watchdog_handler_t _handler, std::chrono::seconds _interval) = 0;
+
+ /**
+ *
+ * \brief Registers a subscription handler.
+ *
+ * A subscription handler is called whenever the subscription state of an
+ * eventgroup changes. The callback is called with the client identifier
+ * and a boolean that indicates whether the client subscribed or
+ * unsubscribed.
+ *
+ * \param _service Service identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _instance Instance identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * subscription state is to be monitored.
+ * \param _handler Callback that shall be called.
+ *
+ */
+ virtual void register_async_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ async_subscription_handler_t _handler) = 0;
+
+ /**
+ * \brief Enables or disables calling of registered offer acceptance
+ * handler for given IP address
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \param _address IP address for which offer acceptance handler should be
+ * called
+ * \param _path Path which indicates need for offer acceptance
+ * \param _enable enable or disable calling of offer acceptance handler
+ */
+ virtual void set_offer_acceptance_required(ip_address_t _address,
+ const std::string _path,
+ bool _enable) = 0;
+
+ /**
+ * \brief Returns all configured IP addresses which require calling of
+ * registered offer acceptance handler
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \return map with known IP addresses requiring offer acceptance handling
+ */
+ typedef std::map<ip_address_t, std::string> offer_acceptance_map_type_t;
+ virtual offer_acceptance_map_type_t get_offer_acceptance_required() = 0;
+
+ /**
+ * \brief Registers a handler which will be called upon reception of
+ * a remote offer with the offering ECU's IP address as parameter
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \param _handler The handler to be called
+ */
+ virtual void register_offer_acceptance_handler(
+ offer_acceptance_handler_t _handler) = 0;
+
+ /**
+ * \brief Registers a handler which will be called upon detection of a
+ * reboot of a remote ECU with the remote ECU's IP address as a parameter
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \param _handler The handler to be called
+ */
+ virtual void register_reboot_notification_handler(
+ reboot_notification_handler_t _handler) = 0;
+
+ /**
+ * \brief Registers a handler which will be called when the routing reached
+ * READY state.
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \param _handler The handler to be called
+ */
+ virtual void register_routing_ready_handler(
+ routing_ready_handler_t _handler) = 0;
+
+ /**
+ * \brief Registers a handler which will be called when the routing state
+ * changes.
+ *
+ * This method has only an effect when called on the application acting as
+ * routing manager
+ *
+ * \param _handler The handler to be called
+ */
+ virtual void register_routing_state_handler(
+ routing_state_handler_t _handler) = 0;
+
+ /**
+ * \brief Update service configuration to offer a local service on the
+ * network as well
+ *
+ * This function is intended to take the necessary information to offer a
+ * service remotely if it was offered only locally beforehand.
+ * Precondition: The service must already be offered locally before
+ * calling this method.
+ * This function only has an effect if called on an application acting as
+ * routing manager.
+ *
+ * \param _service Service identifier
+ * \param _instance Instance identifier
+ * \param _port The port number on which the service should be offered
+ * \param _reliable Offer via TCP or UDP
+ * \param _magic_cookies_enabled Flag to enable magic cookies
+ * \param _offer Offer the service or stop offering it remotely
+ */
+ virtual bool update_service_configuration(service_t _service,
+ instance_t _instance,
+ std::uint16_t _port,
+ bool _reliable,
+ bool _magic_cookies_enabled,
+ bool _offer) = 0;
+
+ /**
+ * \brief Update security configuration of routing manager and all local clients
+ * The given handler gets called with "SU_SUCCESS" if the policy for UID
+ * and GID was updated or added successfully. If not all clients did confirm
+ * the update, SU_TIMEOUT is set.
+ *
+ * \param _uid UID of the policy
+ * \param _gid GID of the policy
+ * \param _policy The security policy to apply
+ * \param _payload serialized security policy object
+ * \param _handler handler which gets called after all clients have
+ * confirmed the policy update
+ */
+ virtual void update_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ std::shared_ptr<policy> _policy,
+ std::shared_ptr<payload> _payload,
+ security_update_handler_t _handler) = 0;
+
+ /**
+ * \brief Remove a security configuration for routing manager and all local clients
+ * The given handler gets called with "SU_SUCCESS" if the policy for UID
+ * and GID was removed successfully. SU_UNKNOWN_USER_ID is set if the
+ * UID and GID was not found. If not all clients did confirm the removal,
+ * SU_TIMEOUT is set.
+ *
+ * \param _uid UID of the policy to remove
+ * \param _gid GID of the policy to remove
+ * \param _handler handler which gets called after all clients have
+ * confirmed the policy removal
+ */
+ virtual void remove_security_policy_configuration(uint32_t _uid,
+ uint32_t _gid,
+ security_update_handler_t _handler) = 0;
+};
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_APPLICATION_HPP
diff --git a/interface/compat/vsomeip/constants.hpp b/interface/compat/vsomeip/constants.hpp
new file mode 100644
index 0000000..2d14920
--- /dev/null
+++ b/interface/compat/vsomeip/constants.hpp
@@ -0,0 +1,63 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_CONSTANTS_HPP
+#define VSOMEIP_CONSTANTS_HPP
+
+#include <string>
+
+#include "../../compat/vsomeip/enumeration_types.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+const major_version_t DEFAULT_MAJOR = 0x00;
+const minor_version_t DEFAULT_MINOR = 0x00000000;
+const ttl_t DEFAULT_TTL = 0xFFFFFF; // "until next reboot"
+
+const std::string DEFAULT_MULTICAST = "224.0.0.0";
+const uint16_t DEFAULT_PORT = 30500;
+const uint16_t ILLEGAL_PORT = 0xFFFF;
+
+const uint16_t NO_TRACE_FILTER_EXPRESSION = 0x0000;
+
+const service_t ANY_SERVICE = 0xFFFF;
+const instance_t ANY_INSTANCE = 0xFFFF;
+const method_t ANY_METHOD = 0xFFFF;
+const major_version_t ANY_MAJOR = 0xFF;
+const minor_version_t ANY_MINOR = 0xFFFFFFFF;
+
+const eventgroup_t DEFAULT_EVENTGROUP = 0x0001;
+
+const client_t ILLEGAL_CLIENT = 0x0000;
+
+const byte_t MAGIC_COOKIE_CLIENT_MESSAGE = 0x00;
+const byte_t MAGIC_COOKIE_SERVICE_MESSAGE = 0x80;
+const length_t MAGIC_COOKIE_SIZE = 0x00000008;
+const request_t MAGIC_COOKIE_REQUEST = 0xDEADBEEF;
+const client_t MAGIC_COOKIE_NETWORK_BYTE_ORDER = 0xADDE;
+const protocol_version_t MAGIC_COOKIE_PROTOCOL_VERSION = 0x01;
+const interface_version_t MAGIC_COOKIE_INTERFACE_VERSION = 0x01;
+const message_type_e MAGIC_COOKIE_CLIENT_MESSAGE_TYPE =
+ message_type_e::MT_REQUEST_NO_RETURN;
+const message_type_e MAGIC_COOKIE_SERVICE_MESSAGE_TYPE =
+ message_type_e::MT_NOTIFICATION;
+const return_code_e MAGIC_COOKIE_RETURN_CODE = return_code_e::E_OK;
+
+const byte_t CLIENT_COOKIE[] = { 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x01, 0x01, 0x00 };
+
+const byte_t SERVICE_COOKIE[] = { 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x01, 0x02, 0x00 };
+
+const event_t ANY_EVENT = 0xFFFF;
+const client_t ANY_CLIENT = 0xFFFF;
+
+const pending_subscription_id_t DEFAULT_SUBSCRIPTION = 0x0;
+const pending_security_update_id_t DEFAULT_SECURITY_UPDATE_ID = 0x0;
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_CONSTANTS_HPP
diff --git a/interface/compat/vsomeip/defines.hpp b/interface/compat/vsomeip/defines.hpp
new file mode 100644
index 0000000..0442fae
--- /dev/null
+++ b/interface/compat/vsomeip/defines.hpp
@@ -0,0 +1,41 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_DEFINES_HPP
+#define VSOMEIP_DEFINES_HPP
+
+#define VSOMEIP_PROTOCOL_VERSION 0x1
+
+// 0 = unlimited, if not specified otherwise via configuration file
+#define VSOMEIP_MAX_LOCAL_MESSAGE_SIZE 0
+// 0 = unlimited, if not specified otherwise via configuration file
+#define VSOMEIP_MAX_TCP_MESSAGE_SIZE 0
+#define VSOMEIP_MAX_UDP_MESSAGE_SIZE 1416
+
+#define VSOMEIP_PACKET_SIZE VSOMEIP_MAX_UDP_MESSAGE_SIZE
+
+#define VSOMEIP_SOMEIP_HEADER_SIZE 8
+#define VSOMEIP_SOMEIP_MAGIC_COOKIE_SIZE 8
+#define VSOMEIP_FULL_HEADER_SIZE 16
+
+#define VSOMEIP_SERVICE_POS_MIN 0
+#define VSOMEIP_SERVICE_POS_MAX 1
+#define VSOMEIP_METHOD_POS_MIN 2
+#define VSOMEIP_METHOD_POS_MAX 3
+#define VSOMEIP_EVENT_POS_MIN 2
+#define VSOMEIP_EVENT_POS_MAX 3
+#define VSOMEIP_LENGTH_POS_MIN 4
+#define VSOMEIP_LENGTH_POS_MAX 7
+#define VSOMEIP_CLIENT_POS_MIN 8
+#define VSOMEIP_CLIENT_POS_MAX 9
+#define VSOMEIP_SESSION_POS_MIN 10
+#define VSOMEIP_SESSION_POS_MAX 11
+#define VSOMEIP_PROTOCOL_VERSION_POS 12
+#define VSOMEIP_INTERFACE_VERSION_POS 13
+#define VSOMEIP_MESSAGE_TYPE_POS 14
+#define VSOMEIP_RETURN_CODE_POS 15
+#define VSOMEIP_PAYLOAD_POS 16
+
+#endif // VSOMEIP_DEFINES_HPP
diff --git a/interface/compat/vsomeip/enumeration_types.hpp b/interface/compat/vsomeip/enumeration_types.hpp
new file mode 100644
index 0000000..71ff38a
--- /dev/null
+++ b/interface/compat/vsomeip/enumeration_types.hpp
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_ENUMERATION_TYPES_HPP
+#define VSOMEIP_ENUMERATION_TYPES_HPP
+
+#include <cstdint>
+
+namespace vsomeip {
+
+enum class state_type_e : uint8_t {
+ ST_REGISTERED = 0x0,
+ ST_DEREGISTERED = 0x1
+};
+
+// SIP_RPC_684
+enum class message_type_e : uint8_t {
+ MT_REQUEST = 0x00,
+ MT_REQUEST_NO_RETURN = 0x01,
+ MT_NOTIFICATION = 0x02,
+ MT_REQUEST_ACK = 0x40,
+ MT_REQUEST_NO_RETURN_ACK = 0x41,
+ MT_NOTIFICATION_ACK = 0x42,
+ MT_RESPONSE = 0x80,
+ MT_ERROR = 0x81,
+ MT_RESPONSE_ACK = 0xC0,
+ MT_ERROR_ACK = 0xC1,
+ MT_UNKNOWN = 0xFF
+};
+
+// SIP_RPC_371
+enum class return_code_e : uint8_t {
+ E_OK = 0x00,
+ E_NOT_OK = 0x01,
+ E_UNKNOWN_SERVICE = 0x02,
+ E_UNKNOWN_METHOD = 0x03,
+ E_NOT_READY = 0x04,
+ E_NOT_REACHABLE = 0x05,
+ E_TIMEOUT = 0x06,
+ E_WRONG_PROTOCOL_VERSION = 0x07,
+ E_WRONG_INTERFACE_VERSION = 0x08,
+ E_MALFORMED_MESSAGE = 0x09,
+ E_WRONG_MESSAGE_TYPE = 0xA,
+ E_UNKNOWN = 0xFF
+};
+
+enum class subscription_type_e : uint8_t {
+ SU_RELIABLE_AND_UNRELIABLE = 0x00,
+ SU_PREFER_UNRELIABLE = 0x01,
+ SU_PREFER_RELIABLE = 0x02,
+ SU_UNRELIABLE = 0x03,
+ SU_RELIABLE = 0x04,
+};
+
+enum class routing_state_e : uint8_t {
+ RS_RUNNING = 0x00,
+ RS_SUSPENDED = 0x01,
+ RS_RESUMED = 0x02,
+ RS_SHUTDOWN = 0x03,
+ RS_DIAGNOSIS = 0x04,
+ RS_UNKNOWN = 0xFF
+};
+
+enum class offer_type_e : uint8_t {
+ OT_LOCAL = 0x00,
+ OT_REMOTE = 0x01,
+ OT_ALL = 0x02,
+};
+
+enum class security_update_state_e : uint8_t {
+ SU_SUCCESS = 0x00,
+ SU_NOT_ALLOWED = 0x01,
+ SU_UNKNOWN_USER_ID = 0x02,
+ SU_INVALID_FORMAT = 0x03
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_ENUMERATION_TYPES_HPP
diff --git a/interface/compat/vsomeip/error.hpp b/interface/compat/vsomeip/error.hpp
new file mode 100644
index 0000000..175f265
--- /dev/null
+++ b/interface/compat/vsomeip/error.hpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_ERROR_HPP
+#define VSOMEIP_ERROR_HPP
+
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+enum class error_code_e : uint8_t {
+ CONFIGURATION_MISSING,
+ PORT_CONFIGURATION_MISSING,
+ CLIENT_ENDPOINT_CREATION_FAILED,
+ SERVER_ENDPOINT_CREATION_FAILED,
+ SERVICE_PROPERTY_MISMATCH
+};
+
+extern const char *ERROR_INFO[];
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_ERROR_HPP
+
diff --git a/interface/compat/vsomeip/export.hpp b/interface/compat/vsomeip/export.hpp
new file mode 100644
index 0000000..a8577ee
--- /dev/null
+++ b/interface/compat/vsomeip/export.hpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef __EXPORT__HPP__
+#define __EXPORT__HPP__
+
+#if _WIN32
+ #define VSOMEIP_EXPORT __declspec(dllexport)
+ #define VSOMEIP_EXPORT_CLASS_EXPLICIT
+
+ #if VSOMEIP_DLL_COMPILATION
+ #define VSOMEIP_IMPORT_EXPORT __declspec(dllexport)
+ #else
+ #define VSOMEIP_IMPORT_EXPORT __declspec(dllimport)
+ #endif
+
+ #if VSOMEIP_DLL_COMPILATION_CONFIG
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG __declspec(dllexport)
+ #else
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG __declspec(dllimport)
+ #endif
+#else
+ #define VSOMEIP_EXPORT
+ #define VSOMEIP_IMPORT_EXPORT
+ #define VSOMEIP_IMPORT_EXPORT_CONFIG
+#endif
+
+#endif
diff --git a/interface/compat/vsomeip/function_types.hpp b/interface/compat/vsomeip/function_types.hpp
new file mode 100644
index 0000000..aa086dd
--- /dev/null
+++ b/interface/compat/vsomeip/function_types.hpp
@@ -0,0 +1,22 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_FUNCTION_TYPES_HPP
+#define VSOMEIP_FUNCTION_TYPES_HPP
+
+#include <functional>
+#include <memory>
+
+namespace vsomeip {
+
+class payload;
+
+typedef std::function<
+ bool (const std::shared_ptr<payload> &,
+ const std::shared_ptr<payload> &) > epsilon_change_func_t;
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_FUNCTION_TYPES_HPP
diff --git a/interface/compat/vsomeip/handler.hpp b/interface/compat/vsomeip/handler.hpp
new file mode 100644
index 0000000..4c74255
--- /dev/null
+++ b/interface/compat/vsomeip/handler.hpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_HANDLER_HPP
+#define VSOMEIP_HANDLER_HPP
+
+#include <functional>
+#include <memory>
+
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+class message;
+
+typedef std::function< void (state_type_e) > state_handler_t;
+typedef std::function< void (const std::shared_ptr< message > &) > message_handler_t;
+typedef std::function< void (service_t, instance_t, bool) > availability_handler_t;
+typedef std::function< bool (client_t, bool) > subscription_handler_t;
+typedef std::function< void (const uint16_t) > error_handler_t;
+typedef std::function< void (const service_t, const instance_t, const eventgroup_t,
+ const event_t, const uint16_t) > subscription_status_handler_t;
+typedef std::function< void (client_t, bool, std::function< void (const bool) > )> async_subscription_handler_t;
+
+typedef std::function< void (const std::vector<std::pair<service_t, instance_t>> &_services) > offered_services_handler_t;
+typedef std::function< void () > watchdog_handler_t;
+
+struct ip_address_t {
+ union {
+ ipv4_address_t v4_;
+ ipv6_address_t v6_;
+ } address_;
+ bool is_v4_;
+
+ bool operator<(const ip_address_t& _other) const {
+ if (is_v4_ && _other.is_v4_) {
+ return address_.v4_ < _other.address_.v4_;
+ } else if (!is_v4_ && !_other.is_v4_) {
+ return address_.v6_ < _other.address_.v6_;
+ } else if (is_v4_ && !_other.is_v4_) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool operator==(const ip_address_t& _other) const {
+ if (is_v4_ && _other.is_v4_) {
+ return address_.v4_ == _other.address_.v4_;
+ } else if (!is_v4_ && !_other.is_v4_) {
+ return address_.v6_ == _other.address_.v6_;
+ } else {
+ return false;
+ }
+ }
+
+ bool operator!=(const ip_address_t& _other) const {
+ return !(*this == _other);
+ }
+
+};
+typedef std::function<bool(const ip_address_t&)> offer_acceptance_handler_t;
+typedef std::function<void(const ip_address_t&)> reboot_notification_handler_t;
+typedef std::function<void()> routing_ready_handler_t;
+typedef std::function<void(routing_state_e)> routing_state_handler_t;
+typedef std::function<void(security_update_state_e)> security_update_handler_t;
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_HANDLER_HPP
diff --git a/interface/compat/vsomeip/internal/deserializable.hpp b/interface/compat/vsomeip/internal/deserializable.hpp
new file mode 100644
index 0000000..10ead19
--- /dev/null
+++ b/interface/compat/vsomeip/internal/deserializable.hpp
@@ -0,0 +1,24 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_DESERIALIZABLE_HPP
+#define VSOMEIP_DESERIALIZABLE_HPP
+
+#include "../../../compat/vsomeip/export.hpp"
+
+namespace vsomeip {
+
+class deserializer;
+
+class deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~deserializable() {
+ }
+ VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from) = 0;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_SERIALIZABLE_HPP
diff --git a/interface/compat/vsomeip/internal/serializable.hpp b/interface/compat/vsomeip/internal/serializable.hpp
new file mode 100644
index 0000000..8363f4b
--- /dev/null
+++ b/interface/compat/vsomeip/internal/serializable.hpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_SERIALIZABLE_HPP
+#define VSOMEIP_SERIALIZABLE_HPP
+
+#include "../../../compat/vsomeip/export.hpp"
+
+namespace vsomeip {
+
+class serializer;
+
+/**
+ * Abstract base class for element that can be serialized.
+ */
+class serializable {
+public:
+ VSOMEIP_EXPORT virtual ~serializable() {}
+
+ /**
+ * \brief serialize the content of the object
+ */
+ VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const = 0;
+};
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_SERIALIZABLE_HPP
diff --git a/interface/compat/vsomeip/message.hpp b/interface/compat/vsomeip/message.hpp
new file mode 100644
index 0000000..b7049ee
--- /dev/null
+++ b/interface/compat/vsomeip/message.hpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_MESSAGE_HPP
+#define VSOMEIP_MESSAGE_HPP
+
+#include <memory>
+
+#include "../../compat/vsomeip/message_base.hpp"
+
+namespace vsomeip {
+
+class payload;
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * @{
+ *
+ */
+
+/**
+ * \brief Implements regular SOME/IP messages.
+ *
+ * This class extends @ref message_base by an unstructured payload. Except
+ * SOME/IP Service Discovery messages, all SOME/IP messages within vsomeip
+ * are represented by message objects.
+ */
+
+class message: virtual public message_base {
+public:
+ virtual ~message() {}
+
+ /**
+ * \brief Returns a pointer to the message payload.
+ */
+ virtual std::shared_ptr<payload> get_payload() const = 0;
+
+ /**
+ * \brief Set the message payload.
+ */
+ virtual void set_payload(std::shared_ptr<payload> _payload) = 0;
+};
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_MESSAGE_HPP
diff --git a/interface/compat/vsomeip/message_base.hpp b/interface/compat/vsomeip/message_base.hpp
new file mode 100644
index 0000000..ffc81fb
--- /dev/null
+++ b/interface/compat/vsomeip/message_base.hpp
@@ -0,0 +1,211 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_MESSAGE_BASE_HPP
+#define VSOMEIP_MESSAGE_BASE_HPP
+
+#include "../../compat/vsomeip/enumeration_types.hpp"
+#include "../../compat/vsomeip/export.hpp"
+#include "../../compat/vsomeip/internal/deserializable.hpp"
+#include "../../compat/vsomeip/internal/serializable.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * @{
+ *
+ */
+
+/**
+ * \brief Base class to implement SOME/IP messages.
+ *
+ * This class implements the SOME/IP message header and connects to the
+ * serialzing/deserializing functionalities. The class is inherited by
+ * the message classes within ::vsomeip and vsomeip::sd that add the
+ * payload representations for regular and Service Discovery messages.
+ */
+class message_base
+ : public serializable,
+ public deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~message_base() {};
+
+ /**
+ * \brief Returns the message identifier.
+ *
+ * The method returns the message identifier that consists of
+ * service identifier and method identifier.
+ */
+ VSOMEIP_EXPORT virtual message_t get_message() const = 0;
+ /**
+ * \brief Set the message identifier.
+ *
+ * The methods sets service identifier and method identifier in
+ * a single call.
+ *
+ * \param _message The new message identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_message(message_t _message) = 0;
+
+ /**
+ * \brief Returns the service identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual service_t get_service() const = 0;
+
+ /**
+ * \brief Set the service identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_service(service_t _service) = 0;
+
+ /**
+ * \brief Returns the instance identifier.
+ *
+ * The instance identifier is _not_ part of the SOME/IP header. It is
+ * either derived from the incoming message (local) or from the port
+ * that was used to send a message (external).
+ */
+ VSOMEIP_EXPORT virtual instance_t get_instance() const = 0;
+
+ /**
+ * \brief Set the instance identifier in the message header.
+ *
+ * To address the correct service instance, vsomeip uses the instance
+ * identifier. For external services it is mapped to a IP address and port
+ * combination before the message is sent. For internal messages is
+ * transferred as additional data appended to the SOME/IP messages.
+ * Therefore, before sending a message, a user application must set the
+ * instance identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_instance(instance_t _instance) = 0;
+
+ /**
+ * \brief Get the method/event identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual method_t get_method() const = 0;
+
+ /**
+ * \brief Set the method/event identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_method(method_t _method) = 0;
+
+ /**
+ * \brief Get the payload length from the message header.
+ */
+ VSOMEIP_EXPORT virtual length_t get_length() const = 0;
+
+ /**
+ * \brief Get the request identifier from the message header.
+ *
+ * The request identifier consists of the client identifier and the
+ * session identifier. As it does really make sense to set it as
+ * a whole, setting is not supported.
+ */
+ VSOMEIP_EXPORT virtual request_t get_request() const = 0;
+
+ /**
+ * \brief Set the client identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual client_t get_client() const = 0;
+
+ /**
+ * \brief Set the client identifier in the message header.
+ *
+ * For requests this is automatically done by @ref application::send.
+ * For notications this is not needed.
+ */
+ VSOMEIP_EXPORT virtual void set_client(client_t _client) = 0;
+
+ /**
+ * \brief Get the session identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual session_t get_session() const = 0;
+
+ /**
+ * \brief Set the session identifier in the message header.
+ *
+ * For requests this is automatically done by @ref application::send
+ * For notifications it is not needed to set the session identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_session(session_t _session) = 0;
+
+ /**
+ * \brief Get the protocol version from the message header.
+ *
+ * As the protocol version is a fixed value for a vsomeip implementation,
+ * it cannot be set.
+ */
+ VSOMEIP_EXPORT virtual protocol_version_t get_protocol_version() const = 0;
+
+ /**
+ * \brief Get the interface version from the message header.
+ */
+ VSOMEIP_EXPORT virtual interface_version_t get_interface_version() const = 0;
+
+ /**
+ * \brief Set the interface version in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_interface_version(interface_version_t _version) = 0;
+
+ /**
+ * \brief Get the message type from the message header.
+ */
+ VSOMEIP_EXPORT virtual message_type_e get_message_type() const = 0;
+
+ /**
+ * \brief Set the message type in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_message_type(message_type_e _type) = 0;
+
+ /**
+ * \brief Get the return code from the message header.
+ */
+ VSOMEIP_EXPORT virtual return_code_e get_return_code() const = 0;
+
+ /**
+ * \brief Set the return code in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_return_code(return_code_e _code) = 0;
+
+ /**
+ * \brief Return the transport mode that was/will be used to send the message.
+ */
+ VSOMEIP_EXPORT virtual bool is_reliable() const = 0;
+
+ /**
+ * \brief Set the transport mode that will be used to send the message.
+ */
+ VSOMEIP_EXPORT virtual void set_reliable(bool _is_reliable) = 0;
+
+ /**
+ * \brief Return whether or not the message is an initial event.
+ */
+ VSOMEIP_EXPORT virtual bool is_initial() const = 0;
+
+ /**
+ * \brief Set whether or not the message is an initial event.
+ */
+ VSOMEIP_EXPORT virtual void set_initial(bool _is_initial) = 0;
+
+ /**
+ * \brief Return whether or not the CRC value received is valid.
+ */
+ VSOMEIP_EXPORT virtual bool is_valid_crc() const = 0;
+
+ /**
+ * \brief Set whether or not the CRC value received is valid.
+ */
+ VSOMEIP_EXPORT virtual void set_is_valid_crc(bool _is_valid_crc) = 0;
+
+};
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_MESSAGE_BASE_HPP
diff --git a/interface/compat/vsomeip/payload.hpp b/interface/compat/vsomeip/payload.hpp
new file mode 100644
index 0000000..e604a3d
--- /dev/null
+++ b/interface/compat/vsomeip/payload.hpp
@@ -0,0 +1,105 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_PAYLOAD_HPP
+#define VSOMEIP_PAYLOAD_HPP
+
+#include <vector>
+
+#include "../../compat/vsomeip/export.hpp"
+#include "../../compat/vsomeip/internal/deserializable.hpp"
+#include "../../compat/vsomeip/internal/serializable.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * @{
+ *
+ */
+
+/**
+ *
+ * \brief This class implements an array of bytes to be used as
+ * payload for SOME/IP messages.
+ *
+*/
+class payload: public serializable, public deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~payload() {}
+
+ /**
+ * \brief Returns true if the given payload is equal to this one.
+ *
+ * \param _other Payload that shall be compared to this payload.
+ */
+ VSOMEIP_EXPORT virtual bool operator ==(const payload &_other) = 0;
+
+ /**
+ * \brief Returns pointer to the payload content
+ */
+ VSOMEIP_EXPORT virtual byte_t * get_data() = 0;
+
+ /**
+ * \brief Returns constant pointer to the payload content
+ */
+ VSOMEIP_EXPORT virtual const byte_t * get_data() const = 0;
+
+ /**
+ * \brief Copies the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer remains untouched.
+ *
+ * \param _data Pointer to a data buffer.
+ * \param _length Length of the data buffer.
+ */
+ VSOMEIP_EXPORT virtual void set_data(const byte_t *_data,
+ length_t _length) = 0;
+
+ /**
+ * \brief Copies the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer remains untouched.
+ *
+ * \param _data Vector containing the data
+ */
+ VSOMEIP_EXPORT virtual void set_data(
+ const std::vector<byte_t> &_data) = 0;
+
+ /**
+ * \brief Returns the length of the payload content.
+ */
+ VSOMEIP_EXPORT virtual length_t get_length() const = 0;
+
+ /**
+ * \brief Set the maximum length of the payload content.
+ *
+ * This function must be called before directly copying data using the
+ * pointer to the internal buffer.
+ */
+ VSOMEIP_EXPORT virtual void set_capacity(length_t _length) = 0;
+
+ /**
+ * \brief Moves the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer is owned by the payload object afterwards.
+ *
+ * \param _data Vector containing the data
+ */
+ VSOMEIP_EXPORT virtual void set_data(
+ std::vector<byte_t> &&_data) = 0;
+};
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_PAYLOAD_HPP
diff --git a/interface/compat/vsomeip/plugin.hpp b/interface/compat/vsomeip/plugin.hpp
new file mode 100644
index 0000000..4d608f1
--- /dev/null
+++ b/interface/compat/vsomeip/plugin.hpp
@@ -0,0 +1,89 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_PLUGIN_HPP
+#define VSOMEIP_PLUGIN_HPP
+
+#include <memory>
+
+#if WIN32
+ #if VSOMEIP_DLL_COMPILATION_PLUGIN
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN __declspec(dllexport)
+ #else
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN __declspec(dllimport)
+ #endif
+#else
+ #define VSOMEIP_IMPORT_EXPORT_PLUGIN
+#endif
+
+#define VSOMEIP_PLUGIN_INIT_SYMBOL "vsomeip_plugin_init"
+
+namespace vsomeip {
+
+enum class plugin_type_e : uint8_t {
+ APPLICATION_PLUGIN,
+ PRE_CONFIGURATION_PLUGIN,
+ CONFIGURATION_PLUGIN,
+ SD_RUNTIME_PLUGIN
+};
+
+class plugin;
+typedef std::shared_ptr<plugin> (*create_plugin_func)();
+typedef create_plugin_func (*plugin_init_func)();
+
+/**
+ * Base class for all plug-ins
+ */
+class VSOMEIP_IMPORT_EXPORT_PLUGIN plugin {
+public:
+ virtual ~plugin() {}
+
+ virtual uint32_t get_plugin_version() const = 0;
+ virtual const std::string &get_plugin_name() const = 0;
+ virtual plugin_type_e get_plugin_type() const = 0;
+};
+
+template<class Plugin_>
+class plugin_impl : public plugin {
+public:
+ static std::shared_ptr<plugin> get_plugin() {
+ return std::make_shared<Plugin_>();
+ }
+
+ plugin_impl(const std::string &_name, uint32_t _version,
+ plugin_type_e _type) {
+ name_ = _name;
+ version_ = _version;
+ type_ = _type;
+ }
+
+ const std::string &get_plugin_name() const {
+ return name_;
+ }
+
+ uint32_t get_plugin_version() const {
+ return version_;
+ }
+
+ plugin_type_e get_plugin_type() const {
+ return type_;
+ }
+
+private:
+ uint32_t version_;
+ std::string name_;
+ plugin_type_e type_;
+};
+
+#define VSOMEIP_PLUGIN(class_name) \
+ extern "C" { \
+ VSOMEIP_EXPORT vsomeip::create_plugin_func vsomeip_plugin_init() { \
+ return class_name::get_plugin; \
+ } \
+ }
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_PLUGIN_HPP
diff --git a/interface/compat/vsomeip/plugins/application_plugin.hpp b/interface/compat/vsomeip/plugins/application_plugin.hpp
new file mode 100644
index 0000000..7f0bb4a
--- /dev/null
+++ b/interface/compat/vsomeip/plugins/application_plugin.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_APPLICATION_PLUGIN_HPP
+#define VSOMEIP_APPLICATION_PLUGIN_HPP
+
+#include <string>
+#include <memory>
+
+#include "../../../compat/vsomeip/export.hpp"
+
+// Version should be incremented on breaking API change
+#define VSOMEIP_APPLICATION_PLUGIN_VERSION 1
+
+namespace vsomeip {
+
+enum class application_plugin_state_e : uint8_t {
+ STATE_INITIALIZED,
+ STATE_STARTED,
+ STATE_STOPPED
+};
+
+/**
+ * The application plug-in can be used to extend application behavior
+ * via an module/plug-in.
+ */
+class application_plugin {
+public:
+ virtual ~application_plugin() {}
+
+ // Called by vSomeIP to inform an application plug-in about its actual state
+ // Call should not be blocked from plug-in as there is no threading.
+ // The caller thread of "application::init/::start/::stop" will inform the plug-in.
+ virtual void on_application_state_change(const std::string _application_name,
+ const application_plugin_state_e _app_state) = 0;
+};
+
+}
+
+#endif // VSOMEIP_APPLICATION_PLUGIN_HPP
diff --git a/interface/compat/vsomeip/plugins/pre_configuration_plugin.hpp b/interface/compat/vsomeip/plugins/pre_configuration_plugin.hpp
new file mode 100644
index 0000000..bce60b0
--- /dev/null
+++ b/interface/compat/vsomeip/plugins/pre_configuration_plugin.hpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2016-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+
+#include "../../../compat/vsomeip/export.hpp"
+
+// Version should be incremented on breaking API change
+#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION 1
+
+namespace vsomeip {
+/**
+ * The pre configuration plug-in can be used to extend configuration load behavior
+ * via an module/plug-in.
+ */
+class pre_configuration_plugin {
+public:
+ virtual ~pre_configuration_plugin() {}
+
+ // Plug-In should return a valid path to a vSomeIP configuration.
+ // vSomeIP will use this path for config loading if such a plug-in is availablel.
+ virtual std::string get_configuration_path() = 0;
+};
+}
+
+#endif // VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
diff --git a/interface/compat/vsomeip/primitive_types.hpp b/interface/compat/vsomeip/primitive_types.hpp
new file mode 100644
index 0000000..93c9960
--- /dev/null
+++ b/interface/compat/vsomeip/primitive_types.hpp
@@ -0,0 +1,66 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_PRIMITIVE_TYPES_HPP
+#define VSOMEIP_PRIMITIVE_TYPES_HPP
+
+#include <array>
+#include <cstdint>
+
+#ifndef _WIN32
+#include <sys/types.h>
+#endif
+
+namespace vsomeip {
+
+typedef uint32_t message_t;
+typedef uint16_t service_t;
+typedef uint16_t method_t;
+typedef uint16_t event_t;
+
+typedef uint16_t instance_t;
+typedef uint16_t eventgroup_t;
+
+typedef uint8_t major_version_t;
+typedef uint32_t minor_version_t;
+
+typedef uint32_t ttl_t;
+
+typedef uint32_t request_t;
+typedef uint16_t client_t;
+typedef uint16_t session_t;
+
+typedef uint32_t length_t;
+
+typedef uint8_t protocol_version_t;
+typedef uint8_t interface_version_t;
+
+typedef uint8_t byte_t;
+
+// Addresses
+typedef std::array<byte_t, 4> ipv4_address_t;
+typedef std::array<byte_t, 16> ipv6_address_t;
+
+typedef std::string trace_channel_t;
+
+typedef std::string trace_filter_type_t;
+
+typedef std::uint16_t pending_subscription_id_t;
+
+typedef std::uint32_t pending_remote_offer_id_t;
+
+typedef std::uint32_t pending_security_update_id_t;
+
+#ifdef _WIN32
+ typedef std::uint32_t uid_t;
+ typedef std::uint32_t gid_t;
+#else
+ typedef ::uid_t uid_t;
+ typedef ::uid_t gid_t;
+#endif
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_PRIMITIVE_TYPES_HPP
diff --git a/interface/compat/vsomeip/runtime.hpp b/interface/compat/vsomeip/runtime.hpp
new file mode 100644
index 0000000..a3cb0d3
--- /dev/null
+++ b/interface/compat/vsomeip/runtime.hpp
@@ -0,0 +1,216 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_RUNTIME_HPP
+#define VSOMEIP_RUNTIME_HPP
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "../../compat/vsomeip/export.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+
+class application;
+class message;
+class payload;
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * The vsomeip module contains all elements a user applications needs to:
+ *
+ * - offer SOME/IP service instances
+ * - request SOME/IP service instances
+ * - offer SOME/IP eventgroups
+ * - subscribe to SOME/IP eventgroups
+ * - send and receive SOME/IP messages (request/response)
+ * - implement SOME/IP events and fields
+ *
+ * @{
+ *
+ */
+
+/**
+ *
+ * \brief Singleton class containing all public resource management
+ * facilities of vsomeip.
+ *
+ * The methods of this class shall be used to create instances of all the
+ * classes needed to facilitate SOME/IP communication. In particular, it is
+ * the entry point to create instances of the @ref application class that
+ * contains the main public API of vsomeip.
+ *
+ */
+class VSOMEIP_IMPORT_EXPORT runtime {
+public:
+
+ static std::string get_property(const std::string &_name);
+ static void set_property(const std::string &_name, const std::string &_value);
+
+ static std::shared_ptr<runtime> get();
+
+ virtual ~runtime() {
+ }
+
+ /**
+ *
+ * \brief Creates a vsomeip application object.
+ *
+ * An application object manages service offers and requests as well as
+ * event subscriptions. It allows to register user application functions
+ * as callbacks that are called on specific events during runtime, e.g
+ * to react on incoming SOME/IP messages.
+ * An application object is identified by a unique name that is also used
+ * in (and therefore has to match) the configuration files of vsomeip. If
+ * the name is left empty, the application name is taken from the
+ * environment variable "VSOMEIP_APPLICATION_NAME"
+ *
+ * \param _name Name of the application on the system.
+ *
+ */
+ virtual std::shared_ptr<application> create_application(
+ const std::string &_name = "") = 0;
+
+ /**
+ *
+ * \brief Constructs an empty message object.
+ *
+ * The message can then be used to call @application::send to send a
+ * SOME/IP message. The user application is responsible for setting
+ * the message type, the service instance and the message payload
+ * after this call and before calling @application::send.
+ *
+ * \param _reliable Determines whether this message shall be sent
+ * over a reliable connection (TCP) or not (UDP).
+ *
+ */
+ virtual std::shared_ptr<message> create_message(
+ bool _reliable = false) const = 0;
+ /**
+ *
+ * \brief Constructs an empty request message.
+ *
+ * The message can then be used to call @ref application::send to send a
+ * SOME/IP message. The message type is set to REQUEST after the
+ * call and the request identifier is automatically set during the
+ * @ref application::send call.
+ *
+ * The user application is responsible for setting the service instance
+ * and the payload.
+ *
+ * \param _reliable Determines whether this message shall be sent
+ * over a reliable connection (TCP) or not (UDP).
+ *
+ */
+ virtual std::shared_ptr<message> create_request(
+ bool _reliable = false) const = 0;
+
+ /*
+ * \brief Constructs an empty response message from a given request
+ * message.
+ *
+ * The message can then be used to call @ref application::send to send a
+ * SOME/IP message. The message type is set to RESPONSE after the
+ * call and the request identifier is automatically set from the
+ * request message.
+ *
+ * The user application is responsible for setting the service instance
+ * and the payload.
+ *
+ * \param _request The request message that shall be answered by
+ * the response message.
+ *
+ */
+ virtual std::shared_ptr<message> create_response(
+ const std::shared_ptr<message> &_request) const = 0;
+
+ /**
+ *
+ * \brief Creates an empty notification message.
+ *
+ * The message can then be used to call @ref application::send to send a
+ * SOME/IP message. The message type is set to NOTIFICATION after the
+ * call.
+ *
+ * The user application is responsible for setting the service instance
+ * and the payload.
+ *
+ * \param _reliable Determines whether this message shall be sent
+ * over a reliable connection (TCP) or not (UDP).
+ *
+ * Note: Creating notification messages and sending them using
+ * @ref application::send is possible but not the standard way of sending
+ * notification with vsomeip. The standard way is calling
+ * @ref application::offer_event and setting the value using the
+ * @ref application::notify / @ref application::notify_one methods.
+ *
+ */
+ virtual std::shared_ptr<message> create_notification(
+ bool _reliable = false) const = 0;
+
+ /**
+ *
+ * \brief Creates an empty payload object.
+ *
+ */
+ virtual std::shared_ptr<payload> create_payload() const = 0;
+
+ /**
+ *
+ * \brief Creates a payload object filled with the given data.
+ *
+ * \param _data Bytes to be copied into the payload object.
+ * \param _size Number of bytes to be copied into the payload object.
+ *
+ */
+ virtual std::shared_ptr<payload> create_payload(
+ const byte_t *_data, uint32_t _size) const = 0;
+
+ /**
+ *
+ * \brief Creates a payload object filled with the given data.
+ *
+ * \param _data Bytes to be copied into the payload object.
+ *
+ */
+ virtual std::shared_ptr<payload> create_payload(
+ const std::vector<byte_t> &_data) const = 0;
+
+ /**
+ *
+ * \brief Retrieves the application object for the application with the
+ * given name.
+ *
+ * If no such application is found, an empty shared_ptr is returned
+ * (nullptr).
+ *
+ * \param _name Name of the application to be found.
+ *
+ */
+ virtual std::shared_ptr<application> get_application(
+ const std::string &_name) const = 0;
+
+ /**
+ *
+ * \brief Removes the application object for the application with the
+ * given name.
+ *
+ * If no such application is found, this is a null operation.
+ *
+ * \param _name Name of the application to be removed.
+ *
+ */
+ virtual void remove_application( const std::string &_name) = 0;
+};
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_RUNTIME_HPP
diff --git a/interface/compat/vsomeip/trace.hpp b/interface/compat/vsomeip/trace.hpp
new file mode 100644
index 0000000..ebdd418
--- /dev/null
+++ b/interface/compat/vsomeip/trace.hpp
@@ -0,0 +1,218 @@
+// Copyright (C) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef VSOMEIP_TRACE_HPP_
+#define VSOMEIP_TRACE_HPP_
+
+#include <memory>
+#include <vector>
+
+#include "../../compat/vsomeip/constants.hpp"
+#include "../../compat/vsomeip/primitive_types.hpp"
+
+namespace vsomeip {
+/**
+ * \defgroup vsomeip
+ *
+ * @{
+ */
+namespace trace {
+
+/**
+ * \brief Unique identifier for trace filters.
+ */
+typedef uint32_t filter_id_t;
+
+/**
+ * \brief Error value.
+ */
+extern const filter_id_t FILTER_ID_ERROR;
+
+/**
+ * \brief The default channel id "TC".
+ */
+extern const char *VSOMEIP_TC_DEFAULT_CHANNEL_ID;
+
+/**
+ * \brief Filters contain at least one match that specified
+ * which messages are filtered.
+ */
+typedef std::tuple<service_t, instance_t, method_t> match_t;
+
+/**
+ * \brief Representation of a DLT trace channel.
+ *
+ * A trace channel contains one or more filters that specify the
+ * messages that are forwarded to the trace.
+ */
+class channel {
+public:
+ virtual ~channel() {};
+
+ /**
+ * \brief Get the identifier of the channel.
+ *
+ * \return Channel identifier.
+ */
+ virtual std::string get_id() const = 0;
+
+ /**
+ * \brief Get the name of the channel.
+ *
+ * \return Channel name.
+ */
+ virtual std::string get_name() const = 0;
+
+ /**
+ * \brief Add a filter to the channel.
+ *
+ * Add a simple filter containing a single match.
+ *
+ * Note: The match is allowed to contain wildcards
+ * (ANY_INSTANCE, ANY_SERVICE, ANY_METHOD).
+ *
+ * \param _match The tuple specifying the matching messages.
+ * \param _is_positive True for positive filters,
+ * false for negative filters. Default value is true.
+ *
+ * \return Filter identifier of the added filter or
+ * FILTER_ID_ERROR if adding failed.
+ */
+ virtual filter_id_t add_filter(
+ const match_t &_match,
+ bool _is_positive = true) = 0;
+
+ /**
+ * \brief Add a filter to the channel.
+ *
+ * Add a filter containing a list of matches to the
+ * channel. The filter matches if at least on of the
+ * matches corresponds to a message.
+ *
+ * Note: The matches are allowed to contain wildcards
+ * (ANY_INSTANCE, ANY_SERVICE, ANY_METHOD).
+ *
+ * \param _matches List of tuples specifying the matching messages.
+ * \param _is_positive True for positive filters,
+ * false for negative filters. Default value is true.
+ *
+ * \return Filter identifier of the added filter or
+ * FILTER_ID_ERROR if adding failed.
+ */
+ virtual filter_id_t add_filter(
+ const std::vector<match_t> &_matches,
+ bool _is_positive = true) = 0;
+
+ /**
+ * \brief Add a filter to the channel.
+ *
+ * Add a filter containing a matches range to the
+ * channel. The filter matches if the message identifiers
+ * lie within the range specified by from and to. Thus,
+ * the messages service identifier is greater equal than
+ * the service identifier specified in from and less equal
+ * than the service identifier specified in to.
+ *
+ * Note: from and to must not contain wildcards
+ * (ANY_INSTANCE, ANY_SERVICE, ANY_METHOD).
+ *
+ * \param _from Tuples specifying the matching message with
+ * the smallest identifiers.
+ * \param _from Tuples specifying the matching message with
+ * the greatest identifiers.
+ * \param _is_positive True for positive filters,
+ * false for negative filters. Default value is true.
+ *
+ * \return Filter identifier of the added filter or
+ * FILTER_ID_ERROR if adding failed.
+ */
+ virtual filter_id_t add_filter(
+ const match_t &_from, const match_t &_to,
+ bool _is_positive = true) = 0;
+
+ /**
+ * \brief Remove a filter from the channel.
+ *
+ * Remove the filter with the given filter identifier
+ * from the channel.
+ *
+ * \param _id Filter identifier of the filter that shall
+ * be removed.
+ */
+ virtual void remove_filter(
+ filter_id_t _id) = 0;
+};
+
+/**
+ * \brief Singleton class to connect to the DLT tracing.
+ *
+ * The main configuration class of the DLT tracing. It holds
+ * the trace channels which determine the messages that are
+ * forwarded to the trace.
+ */
+class connector {
+public:
+ /**
+ * \brief Get access to the connector.
+ *
+ * \return Shared pointer to the singleton object.
+ */
+ static std::shared_ptr<connector> get();
+
+ virtual ~connector() {};
+
+ /**
+ * \brief Add a trace channel to the connector.
+ *
+ * Creates a trace channel with the given identifier and name
+ * and adds it to the connector.
+ *
+ * \param _id Id of the trace channel.
+ * \param _name Name of the trace channel
+ *
+ * \return Shared pointer to the created trace channel or
+ * nullptr if the trace channel could not be created because
+ * another trace channel with the given identifier does
+ * already exist.
+ */
+ virtual std::shared_ptr<channel> add_channel(
+ const std::string &_id,
+ const std::string &_name) = 0;
+
+ /**
+ * \brief Remove a trace channel from the connector.
+ *
+ * Removes the trace channel with the given identifier from
+ * the connector.
+ *
+ * \param _id Identifier of a trace channel.
+ *
+ * \return True of the trace channel was removed, False if
+ * it could not be removed, because it is the default trace
+ * channel.
+ */
+ virtual bool remove_channel(
+ const std::string &_id) = 0;
+
+ /**
+ * \brief Get a trace channel from the connector.
+ *
+ * \param _id Identifier of the trace channel to be returned.
+ * Optional argument that is predefined with the identifier
+ * of the default trace channel.
+ *
+ * \return Shared pointer to the created trace channel or
+ * nullptr if the trace channel does not exist.
+ */
+ virtual std::shared_ptr<channel> get_channel(
+ const std::string &_id = VSOMEIP_TC_DEFAULT_CHANNEL_ID) const = 0;
+};
+
+} // namespace trace
+
+/** @} */
+
+} // namespace vsomeip
+
+#endif // VSOMEIP_CONSTANTS_HPP
diff --git a/interface/compat/vsomeip/vsomeip.hpp b/interface/compat/vsomeip/vsomeip.hpp
new file mode 100644
index 0000000..101e136
--- /dev/null
+++ b/interface/compat/vsomeip/vsomeip.hpp
@@ -0,0 +1,21 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_VSOMEIP_HPP
+#define VSOMEIP_VSOMEIP_HPP
+
+/**
+ * \brief The central vsomeip header. Include this to use vsomeip.
+ */
+
+#include "../../compat/vsomeip/application.hpp"
+#include "../../compat/vsomeip/constants.hpp"
+#include "../../compat/vsomeip/defines.hpp"
+#include "../../compat/vsomeip/message.hpp"
+#include "../../compat/vsomeip/payload.hpp"
+#include "../../compat/vsomeip/runtime.hpp"
+#include "../../compat/vsomeip/trace.hpp"
+
+#endif // VSOMEIP_VSOMEIP_HPP
diff --git a/interface/vsomeip/application.hpp b/interface/vsomeip/application.hpp
index a1296e8..a67368f 100644
--- a/interface/vsomeip/application.hpp
+++ b/interface/vsomeip/application.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_APPLICATION_HPP
-#define VSOMEIP_APPLICATION_HPP
+#ifndef VSOMEIP_V3_APPLICATION_HPP_
+#define VSOMEIP_V3_APPLICATION_HPP_
#include <chrono>
#include <memory>
@@ -18,9 +18,9 @@
#include <vsomeip/constants.hpp>
#include <vsomeip/handler.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
-class configuration;
+class configuration_public;
class event;
class payload;
struct policy;
@@ -81,14 +81,11 @@ public:
virtual client_t get_client() const = 0;
/**
+ * \brief Get the diagnosis address
*
- * \brief Does nothing.
- *
- * This method exists for compatibility reasons only. It is a null
- * operation and will be removed with the next major vsomeip version.
- *
+ * \return diagnosis address
*/
- virtual void set_configuration(const std::shared_ptr<configuration> _configuration) = 0;
+ virtual diagnosis_t get_diagnosis() const = 0;
/**
*
@@ -120,7 +117,6 @@ public:
virtual void start() = 0;
/**
- *
* \brief Stops message processing.
*
* This method stops message processing. Thus, @ref start will return
@@ -130,6 +126,26 @@ public:
virtual void stop() = 0;
/**
+ * \brief Process messages / events.
+ *
+ * This methods controls the message / event processing from an application
+ * context. You must not call start / stop if you use this method.
+ *
+ * \param _number Number of events/messages that will be processed at
+ * maximum before returning.
+ *
+ */
+ virtual void process(int _number = VSOMEIP_ALL) = 0;
+
+ /**
+ *
+ * \brief Get the security mode of the application
+ *
+ * \return security mode
+ */
+ virtual security_mode_e get_security_mode() const = 0;
+
+ /**
*
* \brief Offers a SOME/IP service instance.
*
@@ -181,16 +197,33 @@ public:
* event.
* \param _instance Instance identifier of the interface containing the
* event.
- * \param _event Event identifier of the offered event.
+ * \param _notifier Identifier of the notifier for the offered event.
* \param _eventgroups List of eventgroup identifiers of the eventgroups
* that contain the event.
- * \param _is_field Selector for event or field.
- *
- */
- virtual void offer_event(service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups,
- bool _is_field) = 0;
+ * \param _type Pure event, selective event or field.
+ * \param _cycle Cycle time for periodic events
+ * \param _change_resets_cycle Set to true if a change of the event
+ * payload shall reset the cycle time for periodically sent events
+ * \param _update_on_change Set to false if a change of the event should not
+ * trigger a notification
+ * \param _epsilon_change_func Function to determine whether two event
+ * payloads are considered different
+ * \param _reliability Either RT_UNRELIABLE or RT_RELIABLE. All events
+ * of the same eventgroup are required to be offered with the same
+ * reliability. If set to RT_BOTH remote subscriptions are required to
+ * contain a reliable and unreliable endpoint option to be accepted.
+ * If set to RT_UNKNOWN the event reliability is determined by the service
+ * instance's reliability configuration. This parameter has no effect for
+ * events of local services.
+ */
+ virtual void offer_event(service_t _service, instance_t _instance,
+ event_t _notifier, const std::set<eventgroup_t> &_eventgroups,
+ event_type_e _type = event_type_e::ET_EVENT,
+ std::chrono::milliseconds _cycle =std::chrono::milliseconds::zero(),
+ bool _change_resets_cycle = false,
+ bool _update_on_change = true,
+ const epsilon_change_func_t &_epsilon_change_func = nullptr,
+ reliability_type_e _reliability = reliability_type_e::RT_UNKNOWN) = 0;
/**
*
@@ -228,8 +261,7 @@ public:
*/
virtual void request_service(service_t _service, instance_t _instance,
major_version_t _major = ANY_MAJOR,
- minor_version_t _minor = ANY_MINOR,
- bool _use_exclusive_proxy = false) = 0;
+ minor_version_t _minor = ANY_MINOR) = 0;
/**
*
@@ -264,12 +296,25 @@ public:
* \param _event Event identifier of the event.
* \param _eventgroups List of Eventgroup identifiers of the eventgroups
* that contain the event.
- * \param _is_field Pure event (false) or field (true).
- *
+ * \param _type Pure event, selective event or field.
+ * \param _reliability Either RT_UNRELIABLE or RT_RELIABLE. All events
+ * of the same eventgroup are required to be requested with the same
+ * reliability. If set to RT_BOTH remote subscriptions are only done if
+ * the remote service is offered with an unreliable and reliable endpoint
+ * option. If set to RT_UNKNOWN the event reliability is determined by the
+ * service instance's reliability configuration. This parameter has no
+ * effect for events of local services
+ *
+ * Note: If a vsomeip application registers to an event or field and other
+ * vsomeip application shall be enabled to use events/fields from the same
+ * eventgroup, the application must register all events and fields that
+ * belong to the eventgroup. Otherwise, neither event type nor reliability
+ * type are known which might result in missing events.
*/
virtual void request_event(service_t _service, instance_t _instance,
event_t _event, const std::set<eventgroup_t> &_eventgroups,
- bool _is_field) = 0;
+ event_type_e _type = event_type_e::ET_EVENT,
+ reliability_type_e _reliability = reliability_type_e::RT_UNKNOWN) = 0;
/**
*
* \brief Unregister the application as user of an event or field.
@@ -308,13 +353,11 @@ public:
* eventgroup.
* \param _eventgroup Eventgroup identifier of the eventgroup.
* \param _major Major version number of the service.
- * \param _subscription_type Specifies how the events shall be received.
* \param _event All (Default) or a specific event.
*
*/
virtual void subscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, major_version_t _major = DEFAULT_MAJOR,
- subscription_type_e _subscription_type = subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
event_t _event = ANY_EVENT) = 0;
/**
@@ -347,7 +390,15 @@ public:
*
*/
virtual bool is_available(service_t _service, instance_t _instance,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) const = 0;
+ major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
+
+ typedef std::map<service_t,
+ std::map<instance_t,
+ std::map<major_version_t, minor_version_t >>> available_t;
+
+ virtual bool are_available(available_t &_available,
+ service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
+ major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
/**
*
@@ -359,11 +410,9 @@ public:
* identifier.
*
* \param _message Message object.
- * \param _flush If set to true, the message is immediately sent. Otherwise
- * the message might be deferred and sent together with other messages.
*
*/
- virtual void send(std::shared_ptr<message> _message, bool _flush = true) = 0;
+ virtual void send(std::shared_ptr<message> _message) = 0;
/**
*
@@ -386,7 +435,8 @@ public:
*
*/
virtual void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload) const = 0;
+ event_t _event, std::shared_ptr<payload> _payload,
+ bool _force = false) const = 0;
/**
*
@@ -410,8 +460,8 @@ public:
*
*/
virtual void notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- client_t _client) const = 0;
+ event_t _event, std::shared_ptr<payload> _payload, client_t _client,
+ bool _force = false) const = 0;
/**
*
@@ -510,7 +560,7 @@ public:
*/
virtual void register_availability_handler(service_t _service,
instance_t _instance, availability_handler_t _handler,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0;
+ major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) = 0;
/**
*
@@ -528,7 +578,7 @@ public:
*/
virtual void unregister_availability_handler(service_t _service,
instance_t _instance,
- major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor = DEFAULT_MINOR) = 0;
+ major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) = 0;
/**
*
@@ -545,7 +595,8 @@ public:
* subscription state is to be monitored.
* \param _eventgroup Eventgroup identifier of eventgroup whose
* subscription state is to be monitored.
- * \param _handler Callback that shall be called.
+ * \param _handler Callback that shall be called. The value returned by this
+ * handler decides if the subscription is accepted or not.
*
*/
virtual void register_subscription_handler(service_t _service,
@@ -553,6 +604,32 @@ public:
subscription_handler_t _handler) = 0;
/**
+ *
+ * \brief Registers an async subscription handler.
+ *
+ * A subscription handler is called whenever the subscription state of an
+ * eventgroup changes. The callback is called with the client identifier
+ * and a boolean that indicates whether the client subscribed or
+ * unsubscribed.
+ * This method offers the possibility to asynchronously accept/rejects
+ * subscriptions through a callback.
+ *
+ * \param _service Service identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _instance Instance identifier of service instance whose
+ * subscription state is to be monitored.
+ * \param _eventgroup Eventgroup identifier of eventgroup whose
+ * subscription state is to be monitored.
+ * \param _handler Callback that shall be called. The value passed to the
+ * callback passed as a parameter to this handler decides if the
+ * subscription is accepted or not.
+ *
+ */
+ virtual void register_async_subscription_handler(
+ service_t _service, instance_t _instance, eventgroup_t _eventgroup,
+ async_subscription_handler_t _handler) = 0;
+
+ /**
*
* \brief Unregister a subscription handler.
*
@@ -567,43 +644,6 @@ public:
virtual void unregister_subscription_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup) = 0;
- // [Un]Register handler for subscription errors
- /**
- *
- * \brief Allows for the registration of a subscription error handler.
- *
- * This handler is called whenever a subscription request for an eventgroup
- * was either accepted or rejected. The respective callback is called with
- * ether OK (0x00) or REJECTED (0x07).
- *
- * \param _service Service identifier of service instance whose
- * subscription error state is to be monitored.
- * \param _instance Instance identifier of service instance whose
- * subscription error state is to be monitored.
- * \param _eventgroup Eventgroup identifier of eventgroup whose
- * subscription error state is to be monitored.
- * \param _handler Callback that shall be called.
- *
- */
- virtual void register_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup,
- error_handler_t _handler) = 0;
-
- /**
- *
- * \brief Removes a registered subscription error callback.
- *
- * \param _service Service identifier of service instance whose
- * error callback shall be removed.
- * \param _instance Instance identifier of service instance whose
- * error callback shall be removed.
- * \param _eventgroup Eventgroup identifier of eventgroup whose
- * error callback shall be removed.
- *
- */
- virtual void unregister_subscription_error_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup) = 0;
-
/**
*
* \brief Unregister all registered handlers.
@@ -626,197 +666,6 @@ public:
virtual bool is_routing() const = 0;
/**
- *
- * \brief Offers a SOME/IP event or field.
- *
- * A user application must call this method for each event/field it wants
- * to offer. The event is registered at the vsomeip routing component that
- * enables other applications to subscribe to the event/field as well as
- * to get and set the field value.
- *
- * This version of offer_event adds some additional functionalities:
- * - It is possible to configure a cycle time. The notification message of
- * this event is then resent cyclically.
- * - The parameter _change_resets_cycle is available to control how event
- * notification works in case the data is updated by the application. If
- * set to true, an update of the data immediately leads to a
- * notification. Otherwise, the updated data is sent only after the
- * expiration of the cycle time.
- * - It is possible to specify callback function that can be used to
- * implement a predicate that determines whether or not two event values
- * are considered different. Field notifications are only sent if the
- * predicate evaluates to true (or if a notify method is called with the
- * force flag being set).
- *
- * \param _service Service identifier of the interface containing the
- * event.
- * \param _instance Instance identifier of the interface containing the
- * event.
- * \param _event Event identifier of the offered event.
- * \param _eventgroups List of eventgroup identifiers of the eventgroups
- * that contain the event.
- * \param _is_field Selector for event or field.
- * \param _cycle Sets the cycle time of the event. If nonzero, data is
- * resent cyclically after the cycle time expired.
- * \param _change_resets_cycle Tells if a change immediately leads to
- * a notification.
- * \param _epsilon_change_func Predicate that determines if two given
- * payloads are considered different.
- *
- * Note: The different versions of offer_event exist for compatibility
- * reasons. They will be merged with the next major vsomeip version.
- */
- virtual void offer_event(service_t _service,
- instance_t _instance, event_t _event,
- const std::set<eventgroup_t> &_eventgroups,
- bool _is_field,
- std::chrono::milliseconds _cycle,
- bool _change_resets_cycle,
- const epsilon_change_func_t &_epsilon_change_func) = 0;
-
- /**
- *
- * \brief Fire an event or field notification.
- *
- * The specified event is updated with the specified payload data.
- * Dependent on the type of the event, the payload is distributed to all
- * notified clients (always for events, only if the payload has changed
- * for fields).
- *
- * Note: Prior to using this method, @ref offer_event has to be called by
- * the service provider.
- *
- * \param _service Service identifier of the service that contains the
- * event.
- * \param _instance Instance identifier of the service instance that
- * holds the event.
- * \param _event Event identifier of the event.
- * \param _payload Serialized payload of the event.
- * \param _force Forces the notification to be sent (even if the event
- * is a field and the value did not change).
- *
- * Note: The different versions of notify do exist for compatibility
- * reasons. They will be merged with the next major vsomeip release.
- */
- virtual void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- bool _force) const = 0;
-
- /**
- *
- * \brief Fire an event or field notification.
- *
- * The specified event is updated with the specified payload data.
- * Dependent on the type of the event, the payload is distributed to all
- * notified clients (always for events, only if the payload has changed
- * for fields).
- *
- * Note: Prior to using this method, @ref offer_event has to be called by
- * the service provider.
- *
- * \param _service Service identifier of the service that contains the
- * event.
- * \param _instance Instance identifier of the service instance that
- * holds the event.
- * \param _event Event identifier of the event.
- * \param _payload Serialized payload of the event.
- * \param _client Target client.
- * \param _force Forces the notification to be sent (even if the event
- * is a field and the value did not change).
- *
- * Note: The different versions of notify_one do exist for compatibility
- * reasons. They will be merged with the next major vsomeip release.
- */
- virtual void notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force) const = 0;
-
- typedef std::map<service_t, std::map<instance_t, std::map<major_version_t, minor_version_t >>> available_t;
- /**
- * \brief Returns all available instances that match the given combination
- * of service, instance and version.
- *
- * This method checks the availability of the service instances that
- * match the specified combination of service, instance and version
- * parameters. If at least one matching service instance is available,
- * the method returns true, otherwise it returns false. All available
- * service instances are returned to the caller by filling the
- * _available parameter.
- *
- * \param _available Map that is filled with the available instances.
- * \param _service Service identifier that specifies which service(s)
- * are checked.
- * \param _instance Instance identifier that specifies which instance(s)
- * are checked.
- * \param _major_version Major version(s) of the service instances that
- * are checked
- * \param _minor_version Minor version(s) of the service instance that
- * are checked
- */
- virtual bool are_available(available_t &_available,
- service_t _service = ANY_SERVICE, instance_t _instance = ANY_INSTANCE,
- major_version_t _major = ANY_MAJOR, minor_version_t _minor = ANY_MINOR) const = 0;
-
- /**
- *
- * \brief Fire an event or field notification.
- *
- * The specified event is updated with the specified payload data.
- * Dependent on the type of the event, the payload is distributed to all
- * notified clients (always for events, only if the payload has changed
- * for fields).
- *
- * Note: Prior to using this method, @ref offer_event has to be called by
- * the service provider.
- *
- * \param _service Service identifier of the service that contains the
- * event.
- * \param _instance Instance identifier of the service instance that
- * holds the event.
- * \param _event Event identifier of the event.
- * \param _payload Serialized payload of the event.
- * \param _force Forces the notification to be sent (even if the event
- * is a field and the value did not change).
- * \param _flush Must be set to ensure the event is immediately fired.
- *
- * Note: The different versions of notify do exist for compatibility
- * reasons. They will be merged with the next major vsomeip release.
- */
- virtual void notify(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- bool _force, bool _flush) const = 0;
-
- /**
- *
- * \brief Fire an event or field notification.
- *
- * The specified event is updated with the specified payload data.
- * Dependent on the type of the event, the payload is distributed to all
- * notified clients (always for events, only if the payload has changed
- * for fields).
- *
- * Note: Prior to using this method, @ref offer_event has to be called by
- * the service provider.
- *
- * \param _service Service identifier of the service that contains the
- * event.
- * \param _instance Instance identifier of the service instance that
- * holds the event.
- * \param _event Event identifier of the event.
- * \param _payload Serialized payload of the event.
- * \param _client Target client.
- * \param _force Forces the notification to be sent (even if the event
- * is a field and the value did not change).
- * \param _flush Must be set to ensure the event is immediately fired.
- *
- * Note: The different versions of notify_one do exist for compatibility
- * reasons. They will be merged with the next major vsomeip release.
- */
- virtual void notify_one(service_t _service, instance_t _instance,
- event_t _event, std::shared_ptr<payload> _payload,
- client_t _client, bool _force, bool _flush) const = 0;
-
- /**
* \brief Set the current routing state.
*
* The routing state impacts the behavior of the SOME/IP Service Discovery component. It
@@ -842,7 +691,6 @@ public:
virtual void unsubscribe(service_t _service, instance_t _instance,
eventgroup_t _eventgroup, event_t _event) = 0;
-
/**
*
* \brief Registers a subscription status listener.
@@ -850,8 +698,9 @@ public:
* When registered such a handler it will be called for
* every application::subscribe call.
*
- * This method is intended to replace the application::
- * register_subscription_error_handler call in future releases.
+ * The handler is called whenever a subscription request for an eventgroup
+ * and/or event was either accepted or rejected. The respective callback is
+ * called with either OK (0x00) or REJECTED (0x07).
*
* \param _service Service identifier of the service that is subscribed to.
* \param _instance Instance identifier of the service that is subscribed to.
@@ -859,33 +708,28 @@ public:
* \param _event Event indentifier of the event is subscribed to.
* \param _handler A subscription status handler which will be called by vSomeIP
* as a follow of application::subscribe.
+ * \param _is_selective Flag to enable calling the provided handler if the
+ * subscription is answered with a SUBSCRIBE_NACK.
*/
virtual void register_subscription_status_handler(service_t _service,
instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- subscription_status_handler_t _handler) = 0;
+ subscription_status_handler_t _handler, bool _is_selective = false) = 0;
/**
*
- * \brief Registers a subscription status listener.
- *
- * When registered such a handler it will be called for
- * every application::subscribe call.
- *
- * This method is intended to replace the application::
- * register_subscription_error_handler call in future releases.
+ * \brief Unregisters a subscription status listener.
*
- * \param _service Service identifier of the service that is subscribed to.
- * \param _instance Instance identifier of the service that is subscribed to.
- * \param _eventgroup Eventgroup identifier of the eventgroup is subscribed to.
- * \param _event Event indentifier of the event is subscribed to.
- * \param _handler A subscription status handler which will be called by vSomeIP
- * as a follow of application::subscribe.
- * \param _is_selective Flag to enable calling the provided handler if the
- * subscription is answered with a SUBSCRIBE_NACK.
+ * \param _service Service identifier of the service for which the handler
+ * should be removed.
+ * \param _instance Instance identifier of the service for which the handler
+ * should be removed
+ * \param _eventgroup Eventgroup identifier of the eventgroup for which the
+ * should be removed
+ * \param _event Event identifier of the event for which the handler should
+ * be removed.
*/
- virtual void register_subscription_status_handler(service_t _service,
- instance_t _instance, eventgroup_t _eventgroup, event_t _event,
- subscription_status_handler_t _handler, bool _is_selective) = 0;
+ virtual void unregister_subscription_status_handler(service_t _service,
+ instance_t _instance, eventgroup_t _eventgroup, event_t _event) = 0;
/**
*
@@ -915,7 +759,7 @@ public:
* or scheduling effects, thus it may underrun or overrun by small
* amount.
*
- * \note Only one handler can be active at the time, thus last handler set
+ * \note Only one handler can be active at a time, thus last handler set
* by calling this function will be invoked.
*
* \note To disable calling an active handler, invoke this method again,
@@ -927,67 +771,60 @@ public:
*/
virtual void set_watchdog_handler(watchdog_handler_t _handler, std::chrono::seconds _interval) = 0;
- /**
- *
- * \brief Registers a subscription handler.
- *
- * A subscription handler is called whenever the subscription state of an
- * eventgroup changes. The callback is called with the client identifier
- * and a boolean that indicates whether the client subscribed or
- * unsubscribed.
+ /**
+ * \brief Enables or disables calling of registered acceptance
+ * handlers for given remote info
*
- * \param _service Service identifier of service instance whose
- * subscription state is to be monitored.
- * \param _instance Instance identifier of service instance whose
- * subscription state is to be monitored.
- * \param _eventgroup Eventgroup identifier of eventgroup whose
- * subscription state is to be monitored.
- * \param _handler Callback that shall be called.
+ * This method has only an effect when called on the application acting as
+ * routing manager
*
+ * \param _remote IP and port for which SD acceptance handler should be
+ * called
+ * \param _path Path which indicates need for offer acceptance
+ * \param _enable enable or disable calling of offer acceptance handler
*/
- virtual void register_async_subscription_handler(
- service_t _service, instance_t _instance, eventgroup_t _eventgroup,
- async_subscription_handler_t _handler) = 0;
+ virtual void set_sd_acceptance_required(const remote_info_t& _remote,
+ const std::string& _path,
+ bool _enable) = 0;
/**
- * \brief Enables or disables calling of registered offer acceptance
- * handler for given IP address
+ * \brief Enables or disables calling of registered acceptance
+ * handlers for given remote info
*
* This method has only an effect when called on the application acting as
* routing manager
*
- * \param _address IP address for which offer acceptance handler should be
+ * \param _remotes remote infos for which SD acceptance handler should be
* called
* \param _path Path which indicates need for offer acceptance
* \param _enable enable or disable calling of offer acceptance handler
*/
- virtual void set_offer_acceptance_required(ip_address_t _address,
- const std::string _path,
- bool _enable) = 0;
+ typedef std::map<remote_info_t, std::string> sd_acceptance_map_type_t;
+ virtual void set_sd_acceptance_required(
+ const sd_acceptance_map_type_t& _remotes, bool _enable) = 0;
/**
- * \brief Returns all configured IP addresses which require calling of
- * registered offer acceptance handler
+ * \brief Returns all configured remote info which require calling of
+ * registered service discovery (SD) acceptance handler
*
* This method has only an effect when called on the application acting as
* routing manager
*
- * \return map with known IP addresses requiring offer acceptance handling
+ * \return map with known remotes requiring SD acceptance handling
*/
- typedef std::map<ip_address_t, std::string> offer_acceptance_map_type_t;
- virtual offer_acceptance_map_type_t get_offer_acceptance_required() = 0;
+ virtual sd_acceptance_map_type_t get_sd_acceptance_required() = 0;
/**
* \brief Registers a handler which will be called upon reception of
- * a remote offer with the offering ECU's IP address as parameter
+ * a remote SD message with the sending ECU's IP address and port as
+ * parameter
*
* This method has only an effect when called on the application acting as
* routing manager
*
* \param _handler The handler to be called
*/
- virtual void register_offer_acceptance_handler(
- offer_acceptance_handler_t _handler) = 0;
+ virtual void register_sd_acceptance_handler(sd_acceptance_handler_t _handler) = 0;
/**
* \brief Registers a handler which will be called upon detection of a
@@ -1088,6 +925,6 @@ public:
/** @} */
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_APPLICATION_HPP
+#endif // VSOMEIP_V3_APPLICATION_HPP_
diff --git a/interface/vsomeip/constants.hpp b/interface/vsomeip/constants.hpp
index 9dc33f0..e46e0e7 100644
--- a/interface/vsomeip/constants.hpp
+++ b/interface/vsomeip/constants.hpp
@@ -3,15 +3,15 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_CONSTANTS_HPP
-#define VSOMEIP_CONSTANTS_HPP
+#ifndef VSOMEIP_V3_CONSTANTS_HPP_
+#define VSOMEIP_V3_CONSTANTS_HPP_
#include <string>
#include <vsomeip/primitive_types.hpp>
#include <vsomeip/enumeration_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
const major_version_t DEFAULT_MAJOR = 0x00;
const minor_version_t DEFAULT_MINOR = 0x00000000;
@@ -20,6 +20,7 @@ const ttl_t DEFAULT_TTL = 0xFFFFFF; // "until next reboot"
const std::string DEFAULT_MULTICAST = "224.0.0.0";
const uint16_t DEFAULT_PORT = 30500;
const uint16_t ILLEGAL_PORT = 0xFFFF;
+const uint16_t ANY_PORT = 0;
const uint16_t NO_TRACE_FILTER_EXPRESSION = 0x0000;
@@ -32,12 +33,13 @@ const minor_version_t ANY_MINOR = 0xFFFFFFFF;
const eventgroup_t DEFAULT_EVENTGROUP = 0x0001;
const client_t ILLEGAL_CLIENT = 0x0000;
+const method_t INVALID_METHOD = 0x0000;
const byte_t MAGIC_COOKIE_CLIENT_MESSAGE = 0x00;
const byte_t MAGIC_COOKIE_SERVICE_MESSAGE = 0x80;
const length_t MAGIC_COOKIE_SIZE = 0x00000008;
const request_t MAGIC_COOKIE_REQUEST = 0xDEADBEEF;
-const client_t MAGIC_COOKIE_NETWORK_BYTE_ORDER = 0xADDE;
+const client_t MAGIC_COOKIE_CLIENT = 0xDEAD;
const protocol_version_t MAGIC_COOKIE_PROTOCOL_VERSION = 0x01;
const interface_version_t MAGIC_COOKIE_INTERFACE_VERSION = 0x01;
const message_type_e MAGIC_COOKIE_CLIENT_MESSAGE_TYPE =
@@ -55,9 +57,10 @@ const byte_t SERVICE_COOKIE[] = { 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00,
const event_t ANY_EVENT = 0xFFFF;
const client_t ANY_CLIENT = 0xFFFF;
-const pending_subscription_id_t DEFAULT_SUBSCRIPTION = 0x0;
+const int VSOMEIP_ALL = -1;
+
const pending_security_update_id_t DEFAULT_SECURITY_UPDATE_ID = 0x0;
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CONSTANTS_HPP
+#endif // VSOMEIP_V3_CONSTANTS_HPP_
diff --git a/interface/vsomeip/defines.hpp b/interface/vsomeip/defines.hpp
index 0442fae..e10c453 100644
--- a/interface/vsomeip/defines.hpp
+++ b/interface/vsomeip/defines.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_DEFINES_HPP
-#define VSOMEIP_DEFINES_HPP
+#ifndef VSOMEIP_V3_DEFINES_HPP_
+#define VSOMEIP_V3_DEFINES_HPP_
#define VSOMEIP_PROTOCOL_VERSION 0x1
@@ -38,4 +38,4 @@
#define VSOMEIP_RETURN_CODE_POS 15
#define VSOMEIP_PAYLOAD_POS 16
-#endif // VSOMEIP_DEFINES_HPP
+#endif // VSOMEIP_V3_DEFINES_HPP_
diff --git a/interface/vsomeip/enumeration_types.hpp b/interface/vsomeip/enumeration_types.hpp
index 71ff38a..8f31c0d 100644
--- a/interface/vsomeip/enumeration_types.hpp
+++ b/interface/vsomeip/enumeration_types.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ENUMERATION_TYPES_HPP
-#define VSOMEIP_ENUMERATION_TYPES_HPP
+#ifndef VSOMEIP_V3_ENUMERATION_TYPES_HPP_
+#define VSOMEIP_V3_ENUMERATION_TYPES_HPP_
#include <cstdint>
-namespace vsomeip {
+namespace vsomeip_v3 {
enum class state_type_e : uint8_t {
ST_REGISTERED = 0x0,
@@ -46,14 +46,6 @@ enum class return_code_e : uint8_t {
E_UNKNOWN = 0xFF
};
-enum class subscription_type_e : uint8_t {
- SU_RELIABLE_AND_UNRELIABLE = 0x00,
- SU_PREFER_UNRELIABLE = 0x01,
- SU_PREFER_RELIABLE = 0x02,
- SU_UNRELIABLE = 0x03,
- SU_RELIABLE = 0x04,
-};
-
enum class routing_state_e : uint8_t {
RS_RUNNING = 0x00,
RS_SUSPENDED = 0x01,
@@ -69,6 +61,19 @@ enum class offer_type_e : uint8_t {
OT_ALL = 0x02,
};
+enum class event_type_e : uint8_t {
+ ET_EVENT = 0x00,
+ ET_SELECTIVE_EVENT = 0x01,
+ ET_FIELD = 0x02,
+ ET_UNKNOWN = 0xFF
+};
+
+enum class security_mode_e : uint8_t {
+ SM_OFF = 0x00,
+ SM_ON = 0x01,
+ SM_AUDIT = 0x02
+};
+
enum class security_update_state_e : uint8_t {
SU_SUCCESS = 0x00,
SU_NOT_ALLOWED = 0x01,
@@ -76,6 +81,13 @@ enum class security_update_state_e : uint8_t {
SU_INVALID_FORMAT = 0x03
};
-} // namespace vsomeip
+enum class reliability_type_e : uint8_t {
+ RT_RELIABLE = 0x01,
+ RT_UNRELIABLE = 0x02,
+ RT_BOTH = 0x3, // RT_RELIABLE | RT_UNRELIABLE
+ RT_UNKNOWN = 0xFF
+};
+
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ENUMERATION_TYPES_HPP
+#endif // VSOMEIP_V3_ENUMERATION_TYPES_HPP_
diff --git a/interface/vsomeip/error.hpp b/interface/vsomeip/error.hpp
index 1136957..8415d90 100644
--- a/interface/vsomeip/error.hpp
+++ b/interface/vsomeip/error.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_ERROR_HPP
-#define VSOMEIP_ERROR_HPP
+#ifndef VSOMEIP_V3_ERROR_HPP_
+#define VSOMEIP_V3_ERROR_HPP_
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
enum class error_code_e : uint8_t {
CONFIGURATION_MISSING,
@@ -20,7 +20,7 @@ enum class error_code_e : uint8_t {
extern const char *ERROR_INFO[];
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_ERROR_HPP
+#endif // VSOMEIP_V3_ERROR_HPP_
diff --git a/interface/vsomeip/export.hpp b/interface/vsomeip/export.hpp
index a8577ee..5f460eb 100644
--- a/interface/vsomeip/export.hpp
+++ b/interface/vsomeip/export.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef __EXPORT__HPP__
-#define __EXPORT__HPP__
+#ifndef VSOMEIP_V3_EXPORT_HPP_
+#define VSOMEIP_V3_EXPORT_HPP_
#if _WIN32
#define VSOMEIP_EXPORT __declspec(dllexport)
@@ -27,4 +27,4 @@
#define VSOMEIP_IMPORT_EXPORT_CONFIG
#endif
-#endif
+#endif // VSOMEIP_V3_EXPORT_HPP_
diff --git a/interface/vsomeip/function_types.hpp b/interface/vsomeip/function_types.hpp
index aa086dd..31ef9d5 100644
--- a/interface/vsomeip/function_types.hpp
+++ b/interface/vsomeip/function_types.hpp
@@ -3,13 +3,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_FUNCTION_TYPES_HPP
-#define VSOMEIP_FUNCTION_TYPES_HPP
+#ifndef VSOMEIP_V3_FUNCTION_TYPES_HPP_
+#define VSOMEIP_V3_FUNCTION_TYPES_HPP_
#include <functional>
#include <memory>
-namespace vsomeip {
+namespace vsomeip_v3 {
class payload;
@@ -17,6 +17,6 @@ typedef std::function<
bool (const std::shared_ptr<payload> &,
const std::shared_ptr<payload> &) > epsilon_change_func_t;
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_FUNCTION_TYPES_HPP
+#endif // VSOMEIP_V3_FUNCTION_TYPES_HPP_
diff --git a/interface/vsomeip/handler.hpp b/interface/vsomeip/handler.hpp
index 2fa57a8..2700567 100644
--- a/interface/vsomeip/handler.hpp
+++ b/interface/vsomeip/handler.hpp
@@ -3,26 +3,27 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_HANDLER_HPP
-#define VSOMEIP_HANDLER_HPP
+#ifndef VSOMEIP_V3_HANDLER_HPP_
+#define VSOMEIP_V3_HANDLER_HPP_
#include <functional>
#include <memory>
+#include <tuple>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class message;
typedef std::function< void (state_type_e) > state_handler_t;
typedef std::function< void (const std::shared_ptr< message > &) > message_handler_t;
typedef std::function< void (service_t, instance_t, bool) > availability_handler_t;
-typedef std::function< bool (client_t, bool) > subscription_handler_t;
+typedef std::function< bool (client_t, uid_t, gid_t, bool) > subscription_handler_t;
typedef std::function< void (const uint16_t) > error_handler_t;
typedef std::function< void (const service_t, const instance_t, const eventgroup_t,
const event_t, const uint16_t) > subscription_status_handler_t;
-typedef std::function< void (client_t, bool, std::function< void (const bool) > )> async_subscription_handler_t;
+typedef std::function< void (client_t, uid_t, gid_t, bool, std::function< void (const bool) > )> async_subscription_handler_t;
typedef std::function< void (const std::vector<std::pair<service_t, instance_t>> &_services) > offered_services_handler_t;
typedef std::function< void () > watchdog_handler_t;
@@ -61,12 +62,27 @@ struct ip_address_t {
}
};
-typedef std::function<bool(const ip_address_t&)> offer_acceptance_handler_t;
+
+struct remote_info_t {
+ ip_address_t ip_;
+ std::uint16_t port_;
+ std::uint16_t first_;
+ std::uint16_t last_;
+ bool is_range_;
+
+ bool operator<(const remote_info_t& _other) const {
+ return std::tie(ip_, port_, first_, last_, is_range_) <
+ std::tie(_other.ip_, _other.port_, _other.first_, _other.last_,
+ _other.is_range_);
+ }
+};
+
+typedef std::function<bool(const remote_info_t&)> sd_acceptance_handler_t;
typedef std::function<void(const ip_address_t&)> reboot_notification_handler_t;
typedef std::function<void()> routing_ready_handler_t;
typedef std::function<void(routing_state_e)> routing_state_handler_t;
typedef std::function<void(security_update_state_e)> security_update_handler_t;
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_HANDLER_HPP
+#endif // VSOMEIP_V3_HANDLER_HPP_
diff --git a/interface/vsomeip/internal/deserializable.hpp b/interface/vsomeip/internal/deserializable.hpp
index 5d8ebcc..ae661e5 100644
--- a/interface/vsomeip/internal/deserializable.hpp
+++ b/interface/vsomeip/internal/deserializable.hpp
@@ -1,24 +1,24 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_DESERIALIZABLE_HPP
-#define VSOMEIP_DESERIALIZABLE_HPP
-
-#include <vsomeip/export.hpp>
-
-namespace vsomeip {
-
-class deserializer;
-
-class deserializable {
-public:
- VSOMEIP_EXPORT virtual ~deserializable() {
- }
- VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from) = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERIALIZABLE_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_DESERIALIZABLE_HPP_
+#define VSOMEIP_V3_DESERIALIZABLE_HPP_
+
+#include <vsomeip/export.hpp>
+
+namespace vsomeip_v3 {
+
+class deserializer;
+
+class deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~deserializable() {
+ }
+ VSOMEIP_EXPORT virtual bool deserialize(deserializer *_from) = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SERIALIZABLE_HPP_
diff --git a/implementation/logging/include/logger.hpp b/interface/vsomeip/internal/logger.hpp
index 9204692..bbf8e65 100644
--- a/implementation/logging/include/logger.hpp
+++ b/interface/vsomeip/internal/logger.hpp
@@ -1,48 +1,51 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_LOGGER_HPP
-#define VSOMEIP_LOGGER_HPP
-
-#include <string>
-
-#ifdef _WIN32
-#include <iostream>
-#endif
-
-#include <vsomeip/export.hpp>
-
-#include <boost/log/sources/severity_logger.hpp>
-#include <boost/log/trivial.hpp>
-
-namespace vsomeip {
-
-class VSOMEIP_IMPORT_EXPORT logger {
-public:
- static std::shared_ptr<logger> get();
-
- virtual ~logger() {
- }
-
- virtual boost::log::sources::severity_logger_mt<
- boost::log::trivial::severity_level> & get_internal() = 0;
-};
-
-#define VSOMEIP_FATAL BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::fatal)
-#define VSOMEIP_ERROR BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::error)
-#define VSOMEIP_WARNING BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::warning)
-#define VSOMEIP_INFO BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::info)
-#define VSOMEIP_DEBUG BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::debug)
-#define VSOMEIP_TRACE BOOST_LOG_SEV(vsomeip::logger::get()->get_internal(), \
- boost::log::trivial::severity_level::trace)
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_LOGGER_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_LOGGER_HPP_
+#define VSOMEIP_V3_LOGGER_HPP_
+
+#include <string>
+
+#ifdef _WIN32
+#include <iostream>
+#endif
+
+#include <vsomeip/export.hpp>
+
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/trivial.hpp>
+
+namespace vsomeip_v3 {
+
+class VSOMEIP_IMPORT_EXPORT logger {
+public:
+ static std::shared_ptr<logger> get();
+
+ virtual ~logger() {
+ }
+
+ virtual boost::log::sources::severity_logger_mt<
+ boost::log::trivial::severity_level> & get_internal() = 0;
+};
+
+#define VSOMEIP_LOG_DEFAULT_APPLICATION_ID "VSIP"
+#define VSOMEIP_LOG_DEFAULT_APPLICATION_NAME "vSomeIP application|SysInfra|IPC"
+
+#define VSOMEIP_FATAL BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::fatal)
+#define VSOMEIP_ERROR BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::error)
+#define VSOMEIP_WARNING BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::warning)
+#define VSOMEIP_INFO BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::info)
+#define VSOMEIP_DEBUG BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::debug)
+#define VSOMEIP_TRACE BOOST_LOG_SEV(vsomeip_v3::logger::get()->get_internal(), \
+ boost::log::trivial::severity_level::trace)
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_LOGGER_HPP_
diff --git a/interface/vsomeip/internal/policy_manager.hpp b/interface/vsomeip/internal/policy_manager.hpp
new file mode 100644
index 0000000..45756ec
--- /dev/null
+++ b/interface/vsomeip/internal/policy_manager.hpp
@@ -0,0 +1,38 @@
+// Copyright (C) 2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_POLICY_MANAGER_HPP_
+#define VSOMEIP_V3_POLICY_MANAGER_HPP_
+
+#include <memory>
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace vsomeip_v3 {
+
+struct policy;
+
+class policy_manager {
+public:
+ static std::shared_ptr<policy_manager> get();
+
+ virtual ~policy_manager() {};
+
+ virtual std::shared_ptr<policy> create_policy() const = 0;
+ virtual void print_policy(const std::shared_ptr<policy> &_policy) const = 0;
+
+ virtual bool parse_uid_gid(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid) const = 0;
+ virtual bool parse_policy(const byte_t* &_buffer, uint32_t &_buffer_size,
+ uint32_t &_uid, uint32_t &_gid,
+ const std::shared_ptr<policy> &_policy) const = 0;
+
+ virtual bool is_policy_update_allowed(uint32_t _uid, std::shared_ptr<policy> &_policy) const = 0;
+ virtual bool is_policy_removal_allowed(uint32_t _uid) const = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_POLICY_MANAGER_HPP_
diff --git a/interface/vsomeip/internal/serializable.hpp b/interface/vsomeip/internal/serializable.hpp
index 0791419..52540b8 100644
--- a/interface/vsomeip/internal/serializable.hpp
+++ b/interface/vsomeip/internal/serializable.hpp
@@ -1,30 +1,30 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_SERIALIZABLE_HPP
-#define VSOMEIP_SERIALIZABLE_HPP
-
-#include <vsomeip/export.hpp>
-
-namespace vsomeip {
-
-class serializer;
-
-/**
- * Abstract base class for element that can be serialized.
- */
-class serializable {
-public:
- VSOMEIP_EXPORT virtual ~serializable() {}
-
- /**
- * \brief serialize the content of the object
- */
- VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const = 0;
-};
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_SERIALIZABLE_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_SERIALIZABLE_HPP_
+#define VSOMEIP_V3_SERIALIZABLE_HPP_
+
+#include <vsomeip/export.hpp>
+
+namespace vsomeip_v3 {
+
+class serializer;
+
+/**
+ * Abstract base class for element that can be serialized.
+ */
+class serializable {
+public:
+ VSOMEIP_EXPORT virtual ~serializable() {}
+
+ /**
+ * \brief serialize the content of the object
+ */
+ VSOMEIP_EXPORT virtual bool serialize(serializer *_to) const = 0;
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_SERIALIZABLE_HPP_
diff --git a/interface/vsomeip/message.hpp b/interface/vsomeip/message.hpp
index 4a68a54..0d1c5cc 100644
--- a/interface/vsomeip/message.hpp
+++ b/interface/vsomeip/message.hpp
@@ -3,14 +3,14 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_MESSAGE_HPP
-#define VSOMEIP_MESSAGE_HPP
+#ifndef VSOMEIP_V3_MESSAGE_HPP_
+#define VSOMEIP_V3_MESSAGE_HPP_
#include <memory>
#include <vsomeip/message_base.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class payload;
@@ -43,10 +43,35 @@ public:
* \brief Set the message payload.
*/
virtual void set_payload(std::shared_ptr<payload> _payload) = 0;
+
+ /**
+ * \brief Get e2e protection check result.
+ */
+ VSOMEIP_EXPORT virtual uint8_t get_check_result() const = 0;
+
+ /**
+ * \brief Set e2e protection check result.
+ */
+ VSOMEIP_EXPORT virtual void set_check_result(uint8_t _check_result) = 0;
+
+ /**
+ * \brief Return whether or not the CRC value received is valid.
+ */
+ VSOMEIP_EXPORT virtual bool is_valid_crc() const = 0;
+
+ /**
+ * \brief Return uid of the message sender.
+ */
+ VSOMEIP_EXPORT virtual uid_t get_uid() const = 0;
+
+ /**
+ * \brief Return gid of the message sender.
+ */
+ VSOMEIP_EXPORT virtual gid_t get_gid() const = 0;
};
/** @} */
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_MESSAGE_HPP
+#endif // VSOMEIP_V3_MESSAGE_HPP_
diff --git a/interface/vsomeip/message_base.hpp b/interface/vsomeip/message_base.hpp
index 60c80e6..b6efa8b 100644
--- a/interface/vsomeip/message_base.hpp
+++ b/interface/vsomeip/message_base.hpp
@@ -1,212 +1,200 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_MESSAGE_BASE_HPP
-#define VSOMEIP_MESSAGE_BASE_HPP
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/primitive_types.hpp>
-#include <vsomeip/enumeration_types.hpp>
-
-#include <vsomeip/internal/deserializable.hpp>
-#include <vsomeip/internal/serializable.hpp>
-
-namespace vsomeip {
-
-/**
- *
- * \defgroup vsomeip
- *
- * @{
- *
- */
-
-/**
- * \brief Base class to implement SOME/IP messages.
- *
- * This class implements the SOME/IP message header and connects to the
- * serialzing/deserializing functionalities. The class is inherited by
- * the message classes within ::vsomeip and vsomeip::sd that add the
- * payload representations for regular and Service Discovery messages.
- */
-class message_base
- : public serializable,
- public deserializable {
-public:
- VSOMEIP_EXPORT virtual ~message_base() {};
-
- /**
- * \brief Returns the message identifier.
- *
- * The method returns the message identifier that consists of
- * service identifier and method identifier.
- */
- VSOMEIP_EXPORT virtual message_t get_message() const = 0;
- /**
- * \brief Set the message identifier.
- *
- * The methods sets service identifier and method identifier in
- * a single call.
- *
- * \param _message The new message identifier.
- */
- VSOMEIP_EXPORT virtual void set_message(message_t _message) = 0;
-
- /**
- * \brief Returns the service identifier from the message header.
- */
- VSOMEIP_EXPORT virtual service_t get_service() const = 0;
-
- /**
- * \brief Set the service identifier in the message header.
- */
- VSOMEIP_EXPORT virtual void set_service(service_t _service) = 0;
-
- /**
- * \brief Returns the instance identifier.
- *
- * The instance identifier is _not_ part of the SOME/IP header. It is
- * either derived from the incoming message (local) or from the port
- * that was used to send a message (external).
- */
- VSOMEIP_EXPORT virtual instance_t get_instance() const = 0;
-
- /**
- * \brief Set the instance identifier in the message header.
- *
- * To address the correct service instance, vsomeip uses the instance
- * identifier. For external services it is mapped to a IP address and port
- * combination before the message is sent. For internal messages is
- * transferred as additional data appended to the SOME/IP messages.
- * Therefore, before sending a message, a user application must set the
- * instance identifier.
- */
- VSOMEIP_EXPORT virtual void set_instance(instance_t _instance) = 0;
-
- /**
- * \brief Get the method/event identifier from the message header.
- */
- VSOMEIP_EXPORT virtual method_t get_method() const = 0;
-
- /**
- * \brief Set the method/event identifier in the message header.
- */
- VSOMEIP_EXPORT virtual void set_method(method_t _method) = 0;
-
- /**
- * \brief Get the payload length from the message header.
- */
- VSOMEIP_EXPORT virtual length_t get_length() const = 0;
-
- /**
- * \brief Get the request identifier from the message header.
- *
- * The request identifier consists of the client identifier and the
- * session identifier. As it does really make sense to set it as
- * a whole, setting is not supported.
- */
- VSOMEIP_EXPORT virtual request_t get_request() const = 0;
-
- /**
- * \brief Set the client identifier in the message header.
- */
- VSOMEIP_EXPORT virtual client_t get_client() const = 0;
-
- /**
- * \brief Set the client identifier in the message header.
- *
- * For requests this is automatically done by @ref application::send.
- * For notications this is not needed.
- */
- VSOMEIP_EXPORT virtual void set_client(client_t _client) = 0;
-
- /**
- * \brief Get the session identifier from the message header.
- */
- VSOMEIP_EXPORT virtual session_t get_session() const = 0;
-
- /**
- * \brief Set the session identifier in the message header.
- *
- * For requests this is automatically done by @ref application::send
- * For notifications it is not needed to set the session identifier.
- */
- VSOMEIP_EXPORT virtual void set_session(session_t _session) = 0;
-
- /**
- * \brief Get the protocol version from the message header.
- *
- * As the protocol version is a fixed value for a vsomeip implementation,
- * it cannot be set.
- */
- VSOMEIP_EXPORT virtual protocol_version_t get_protocol_version() const = 0;
-
- /**
- * \brief Get the interface version from the message header.
- */
- VSOMEIP_EXPORT virtual interface_version_t get_interface_version() const = 0;
-
- /**
- * \brief Set the interface version in the message header.
- */
- VSOMEIP_EXPORT virtual void set_interface_version(interface_version_t _version) = 0;
-
- /**
- * \brief Get the message type from the message header.
- */
- VSOMEIP_EXPORT virtual message_type_e get_message_type() const = 0;
-
- /**
- * \brief Set the message type in the message header.
- */
- VSOMEIP_EXPORT virtual void set_message_type(message_type_e _type) = 0;
-
- /**
- * \brief Get the return code from the message header.
- */
- VSOMEIP_EXPORT virtual return_code_e get_return_code() const = 0;
-
- /**
- * \brief Set the return code in the message header.
- */
- VSOMEIP_EXPORT virtual void set_return_code(return_code_e _code) = 0;
-
- /**
- * \brief Return the transport mode that was/will be used to send the message.
- */
- VSOMEIP_EXPORT virtual bool is_reliable() const = 0;
-
- /**
- * \brief Set the transport mode that will be used to send the message.
- */
- VSOMEIP_EXPORT virtual void set_reliable(bool _is_reliable) = 0;
-
- /**
- * \brief Return whether or not the message is an initial event.
- */
- VSOMEIP_EXPORT virtual bool is_initial() const = 0;
-
- /**
- * \brief Set whether or not the message is an initial event.
- */
- VSOMEIP_EXPORT virtual void set_initial(bool _is_initial) = 0;
-
- /**
- * \brief Return whether or not the CRC value received is valid.
- */
- VSOMEIP_EXPORT virtual bool is_valid_crc() const = 0;
-
- /**
- * \brief Set whether or not the CRC value received is valid.
- */
- VSOMEIP_EXPORT virtual void set_is_valid_crc(bool _is_valid_crc) = 0;
-
-};
-
-/** @} */
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_MESSAGE_BASE_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_MESSAGE_BASE_HPP_
+#define VSOMEIP_V3_MESSAGE_BASE_HPP_
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+#include <vsomeip/enumeration_types.hpp>
+
+#include <vsomeip/internal/deserializable.hpp>
+#include <vsomeip/internal/serializable.hpp>
+
+namespace vsomeip_v3 {
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * @{
+ *
+ */
+
+/**
+ * \brief Base class to implement SOME/IP messages.
+ *
+ * This class implements the SOME/IP message header and connects to the
+ * serialzing/deserializing functionalities. The class is inherited by
+ * the message classes within ::vsomeip and vsomeip::sd that add the
+ * payload representations for regular and Service Discovery messages.
+ */
+class message_base
+ : public serializable,
+ public deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~message_base() {};
+
+ /**
+ * \brief Returns the message identifier.
+ *
+ * The method returns the message identifier that consists of
+ * service identifier and method identifier.
+ */
+ VSOMEIP_EXPORT virtual message_t get_message() const = 0;
+ /**
+ * \brief Set the message identifier.
+ *
+ * The methods sets service identifier and method identifier in
+ * a single call.
+ *
+ * \param _message The new message identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_message(message_t _message) = 0;
+
+ /**
+ * \brief Returns the service identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual service_t get_service() const = 0;
+
+ /**
+ * \brief Set the service identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_service(service_t _service) = 0;
+
+ /**
+ * \brief Returns the instance identifier.
+ *
+ * The instance identifier is _not_ part of the SOME/IP header. It is
+ * either derived from the incoming message (local) or from the port
+ * that was used to send a message (external).
+ */
+ VSOMEIP_EXPORT virtual instance_t get_instance() const = 0;
+
+ /**
+ * \brief Set the instance identifier in the message header.
+ *
+ * To address the correct service instance, vsomeip uses the instance
+ * identifier. For external services it is mapped to a IP address and port
+ * combination before the message is sent. For internal messages is
+ * transferred as additional data appended to the SOME/IP messages.
+ * Therefore, before sending a message, a user application must set the
+ * instance identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_instance(instance_t _instance) = 0;
+
+ /**
+ * \brief Get the method/event identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual method_t get_method() const = 0;
+
+ /**
+ * \brief Set the method/event identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_method(method_t _method) = 0;
+
+ /**
+ * \brief Get the payload length from the message header.
+ */
+ VSOMEIP_EXPORT virtual length_t get_length() const = 0;
+
+ /**
+ * \brief Get the request identifier from the message header.
+ *
+ * The request identifier consists of the client identifier and the
+ * session identifier. As it does really make sense to set it as
+ * a whole, setting is not supported.
+ */
+ VSOMEIP_EXPORT virtual request_t get_request() const = 0;
+
+ /**
+ * \brief Set the client identifier in the message header.
+ */
+ VSOMEIP_EXPORT virtual client_t get_client() const = 0;
+
+ /**
+ * \brief Set the client identifier in the message header.
+ *
+ * For requests this is automatically done by @ref application::send.
+ * For notications this is not needed.
+ */
+ VSOMEIP_EXPORT virtual void set_client(client_t _client) = 0;
+
+ /**
+ * \brief Get the session identifier from the message header.
+ */
+ VSOMEIP_EXPORT virtual session_t get_session() const = 0;
+
+ /**
+ * \brief Set the session identifier in the message header.
+ *
+ * For requests this is automatically done by @ref application::send
+ * For notifications it is not needed to set the session identifier.
+ */
+ VSOMEIP_EXPORT virtual void set_session(session_t _session) = 0;
+
+ /**
+ * \brief Get the protocol version from the message header.
+ *
+ * As the protocol version is a fixed value for a vsomeip implementation,
+ * it cannot be set.
+ */
+ VSOMEIP_EXPORT virtual protocol_version_t get_protocol_version() const = 0;
+
+ /**
+ * \brief Get the interface version from the message header.
+ */
+ VSOMEIP_EXPORT virtual interface_version_t get_interface_version() const = 0;
+
+ /**
+ * \brief Set the interface version in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_interface_version(interface_version_t _version) = 0;
+
+ /**
+ * \brief Get the message type from the message header.
+ */
+ VSOMEIP_EXPORT virtual message_type_e get_message_type() const = 0;
+
+ /**
+ * \brief Set the message type in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_message_type(message_type_e _type) = 0;
+
+ /**
+ * \brief Get the return code from the message header.
+ */
+ VSOMEIP_EXPORT virtual return_code_e get_return_code() const = 0;
+
+ /**
+ * \brief Set the return code in the message header.
+ */
+ VSOMEIP_EXPORT virtual void set_return_code(return_code_e _code) = 0;
+
+ /**
+ * \brief Return the transport mode that was/will be used to send the message.
+ */
+ VSOMEIP_EXPORT virtual bool is_reliable() const = 0;
+
+ /**
+ * \brief Set the transport mode that will be used to send the message.
+ */
+ VSOMEIP_EXPORT virtual void set_reliable(bool _is_reliable) = 0;
+
+ /**
+ * \brief Return whether or not the message is an initial event.
+ */
+ VSOMEIP_EXPORT virtual bool is_initial() const = 0;
+
+ /**
+ * \brief Set whether or not the message is an initial event.
+ */
+ VSOMEIP_EXPORT virtual void set_initial(bool _is_initial) = 0;
+
+};
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_MESSAGE_BASE_HPP_
diff --git a/interface/vsomeip/payload.hpp b/interface/vsomeip/payload.hpp
index b9b8f61..3e7e45a 100644
--- a/interface/vsomeip/payload.hpp
+++ b/interface/vsomeip/payload.hpp
@@ -1,106 +1,106 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef VSOMEIP_PAYLOAD_HPP
-#define VSOMEIP_PAYLOAD_HPP
-
-#include <vector>
-
-#include <vsomeip/export.hpp>
-#include <vsomeip/primitive_types.hpp>
-
-#include <vsomeip/internal/deserializable.hpp>
-#include <vsomeip/internal/serializable.hpp>
-
-namespace vsomeip {
-
-/**
- *
- * \defgroup vsomeip
- *
- * @{
- *
- */
-
-/**
- *
- * \brief This class implements an array of bytes to be used as
- * payload for SOME/IP messages.
- *
-*/
-class payload: public serializable, public deserializable {
-public:
- VSOMEIP_EXPORT virtual ~payload() {}
-
- /**
- * \brief Returns true if the given payload is equal to this one.
- *
- * \param _other Payload that shall be compared to this payload.
- */
- VSOMEIP_EXPORT virtual bool operator ==(const payload &_other) = 0;
-
- /**
- * \brief Returns pointer to the payload content
- */
- VSOMEIP_EXPORT virtual byte_t * get_data() = 0;
-
- /**
- * \brief Returns constant pointer to the payload content
- */
- VSOMEIP_EXPORT virtual const byte_t * get_data() const = 0;
-
- /**
- * \brief Copies the given data array to the payload object.
- *
- * The current payload content is replaced by the data provided.
- * The given buffer remains untouched.
- *
- * \param _data Pointer to a data buffer.
- * \param _length Length of the data buffer.
- */
- VSOMEIP_EXPORT virtual void set_data(const byte_t *_data,
- length_t _length) = 0;
-
- /**
- * \brief Copies the given data array to the payload object.
- *
- * The current payload content is replaced by the data provided.
- * The given buffer remains untouched.
- *
- * \param _data Vector containing the data
- */
- VSOMEIP_EXPORT virtual void set_data(
- const std::vector<byte_t> &_data) = 0;
-
- /**
- * \brief Returns the length of the payload content.
- */
- VSOMEIP_EXPORT virtual length_t get_length() const = 0;
-
- /**
- * \brief Set the maximum length of the payload content.
- *
- * This function must be called before directly copying data using the
- * pointer to the internal buffer.
- */
- VSOMEIP_EXPORT virtual void set_capacity(length_t _length) = 0;
-
- /**
- * \brief Moves the given data array to the payload object.
- *
- * The current payload content is replaced by the data provided.
- * The given buffer is owned by the payload object afterwards.
- *
- * \param _data Vector containing the data
- */
- VSOMEIP_EXPORT virtual void set_data(
- std::vector<byte_t> &&_data) = 0;
-};
-
-/** @} */
-
-} // namespace vsomeip
-
-#endif // VSOMEIP_PAYLOAD_HPP
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef VSOMEIP_V3_PAYLOAD_HPP_
+#define VSOMEIP_V3_PAYLOAD_HPP_
+
+#include <vector>
+
+#include <vsomeip/export.hpp>
+#include <vsomeip/primitive_types.hpp>
+
+#include <vsomeip/internal/deserializable.hpp>
+#include <vsomeip/internal/serializable.hpp>
+
+namespace vsomeip_v3 {
+
+/**
+ *
+ * \defgroup vsomeip
+ *
+ * @{
+ *
+ */
+
+/**
+ *
+ * \brief This class implements an array of bytes to be used as
+ * payload for SOME/IP messages.
+ *
+*/
+class payload: public serializable, public deserializable {
+public:
+ VSOMEIP_EXPORT virtual ~payload() {}
+
+ /**
+ * \brief Returns true if the given payload is equal to this one.
+ *
+ * \param _other Payload that shall be compared to this payload.
+ */
+ VSOMEIP_EXPORT virtual bool operator ==(const payload &_other) = 0;
+
+ /**
+ * \brief Returns pointer to the payload content
+ */
+ VSOMEIP_EXPORT virtual byte_t * get_data() = 0;
+
+ /**
+ * \brief Returns constant pointer to the payload content
+ */
+ VSOMEIP_EXPORT virtual const byte_t * get_data() const = 0;
+
+ /**
+ * \brief Copies the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer remains untouched.
+ *
+ * \param _data Pointer to a data buffer.
+ * \param _length Length of the data buffer.
+ */
+ VSOMEIP_EXPORT virtual void set_data(const byte_t *_data,
+ length_t _length) = 0;
+
+ /**
+ * \brief Copies the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer remains untouched.
+ *
+ * \param _data Vector containing the data
+ */
+ VSOMEIP_EXPORT virtual void set_data(
+ const std::vector<byte_t> &_data) = 0;
+
+ /**
+ * \brief Returns the length of the payload content.
+ */
+ VSOMEIP_EXPORT virtual length_t get_length() const = 0;
+
+ /**
+ * \brief Set the maximum length of the payload content.
+ *
+ * This function must be called before directly copying data using the
+ * pointer to the internal buffer.
+ */
+ VSOMEIP_EXPORT virtual void set_capacity(length_t _length) = 0;
+
+ /**
+ * \brief Moves the given data array to the payload object.
+ *
+ * The current payload content is replaced by the data provided.
+ * The given buffer is owned by the payload object afterwards.
+ *
+ * \param _data Vector containing the data
+ */
+ VSOMEIP_EXPORT virtual void set_data(
+ std::vector<byte_t> &&_data) = 0;
+};
+
+/** @} */
+
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_PAYLOAD_HPP_
diff --git a/interface/vsomeip/plugin.hpp b/interface/vsomeip/plugin.hpp
index 4d608f1..dfb6bba 100644
--- a/interface/vsomeip/plugin.hpp
+++ b/interface/vsomeip/plugin.hpp
@@ -3,12 +3,12 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_PLUGIN_HPP
-#define VSOMEIP_PLUGIN_HPP
+#ifndef VSOMEIP_V3_PLUGIN_HPP_
+#define VSOMEIP_V3_PLUGIN_HPP_
#include <memory>
-#if WIN32
+#if _WIN32
#if VSOMEIP_DLL_COMPILATION_PLUGIN
#define VSOMEIP_IMPORT_EXPORT_PLUGIN __declspec(dllexport)
#else
@@ -20,7 +20,7 @@
#define VSOMEIP_PLUGIN_INIT_SYMBOL "vsomeip_plugin_init"
-namespace vsomeip {
+namespace vsomeip_v3 {
enum class plugin_type_e : uint8_t {
APPLICATION_PLUGIN,
@@ -79,11 +79,11 @@ private:
#define VSOMEIP_PLUGIN(class_name) \
extern "C" { \
- VSOMEIP_EXPORT vsomeip::create_plugin_func vsomeip_plugin_init() { \
+ VSOMEIP_EXPORT vsomeip_v3::create_plugin_func vsomeip_plugin_init() { \
return class_name::get_plugin; \
} \
}
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_PLUGIN_HPP
+#endif // VSOMEIP_V3_PLUGIN_HPP_
diff --git a/interface/vsomeip/plugins/application_plugin.hpp b/interface/vsomeip/plugins/application_plugin.hpp
index 3d5cce1..90e3e64 100644
--- a/interface/vsomeip/plugins/application_plugin.hpp
+++ b/interface/vsomeip/plugins/application_plugin.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_APPLICATION_PLUGIN_HPP
-#define VSOMEIP_APPLICATION_PLUGIN_HPP
+#ifndef VSOMEIP_V3_APPLICATION_PLUGIN_HPP_
+#define VSOMEIP_V3_APPLICATION_PLUGIN_HPP_
#include <string>
#include <memory>
@@ -14,7 +14,7 @@
// Version should be incremented on breaking API change
#define VSOMEIP_APPLICATION_PLUGIN_VERSION 1
-namespace vsomeip {
+namespace vsomeip_v3 {
enum class application_plugin_state_e : uint8_t {
STATE_INITIALIZED,
@@ -37,6 +37,6 @@ public:
const application_plugin_state_e _app_state) = 0;
};
-}
+} // namespace vsomeip_v3
-#endif // VSOMEIP_APPLICATION_PLUGIN_HPP
+#endif // VSOMEIP_V3_APPLICATION_PLUGIN_HPP_
diff --git a/interface/vsomeip/plugins/pre_configuration_plugin.hpp b/interface/vsomeip/plugins/pre_configuration_plugin.hpp
index 6155796..6505249 100644
--- a/interface/vsomeip/plugins/pre_configuration_plugin.hpp
+++ b/interface/vsomeip/plugins/pre_configuration_plugin.hpp
@@ -3,15 +3,15 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
-#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+#ifndef VSOMEIP_V3_PRE_CONFIGURATION_PLUGIN_HPP_
+#define VSOMEIP_V3_PRE_CONFIGURATION_PLUGIN_HPP_
#include <vsomeip/export.hpp>
// Version should be incremented on breaking API change
#define VSOMEIP_PRE_CONFIGURATION_PLUGIN_VERSION 1
-namespace vsomeip {
+namespace vsomeip_v3 {
/**
* The pre configuration plug-in can be used to extend configuration load behavior
* via an module/plug-in.
@@ -24,6 +24,7 @@ public:
// vSomeIP will use this path for config loading if such a plug-in is availablel.
virtual std::string get_configuration_path() = 0;
};
-}
-#endif // VSOMEIP_PRE_CONFIGURATION_PLUGIN_HPP
+} // namespace vsomeip_v3
+
+#endif // VSOMEIP_V3_PRE_CONFIGURATION_PLUGIN_HPP_
diff --git a/interface/vsomeip/primitive_types.hpp b/interface/vsomeip/primitive_types.hpp
index 95192eb..f0dd136 100644
--- a/interface/vsomeip/primitive_types.hpp
+++ b/interface/vsomeip/primitive_types.hpp
@@ -3,13 +3,17 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_PRIMITIVE_TYPES_HPP
-#define VSOMEIP_PRIMITIVE_TYPES_HPP
+#ifndef VSOMEIP_V3_PRIMITIVE_TYPES_HPP_
+#define VSOMEIP_V3_PRIMITIVE_TYPES_HPP_
#include <array>
#include <cstdint>
-namespace vsomeip {
+#ifndef _WIN32
+#include <sys/types.h>
+#endif
+
+namespace vsomeip_v3 {
typedef uint32_t message_t;
typedef uint16_t service_t;
@@ -34,6 +38,7 @@ typedef uint8_t protocol_version_t;
typedef uint8_t interface_version_t;
typedef uint8_t byte_t;
+typedef uint16_t diagnosis_t;
// Addresses
typedef std::array<byte_t, 4> ipv4_address_t;
@@ -43,12 +48,18 @@ typedef std::string trace_channel_t;
typedef std::string trace_filter_type_t;
-typedef std::uint16_t pending_subscription_id_t;
-
typedef std::uint32_t pending_remote_offer_id_t;
typedef std::uint32_t pending_security_update_id_t;
-} // namespace vsomeip
+#ifdef _WIN32
+ typedef std::uint32_t uid_t;
+ typedef std::uint32_t gid_t;
+#else
+ typedef ::uid_t uid_t;
+ typedef ::uid_t gid_t;
+#endif
+
+} // namespace vsomeip_v3
-#endif // VSOMEIP_PRIMITIVE_TYPES_HPP
+#endif // VSOMEIP_V3_PRIMITIVE_TYPES_HPP
diff --git a/interface/vsomeip/runtime.hpp b/interface/vsomeip/runtime.hpp
index ae54e19..513847d 100644
--- a/interface/vsomeip/runtime.hpp
+++ b/interface/vsomeip/runtime.hpp
@@ -3,8 +3,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_RUNTIME_HPP
-#define VSOMEIP_RUNTIME_HPP
+#ifndef VSOMEIP_V3_RUNTIME_HPP
+#define VSOMEIP_V3_RUNTIME_HPP
#include <memory>
#include <string>
@@ -13,7 +13,7 @@
#include <vsomeip/export.hpp>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
class application;
class message;
@@ -211,6 +211,6 @@ public:
/** @} */
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_RUNTIME_HPP
+#endif // VSOMEIP_V3_RUNTIME_HPP_
diff --git a/interface/vsomeip/trace.hpp b/interface/vsomeip/trace.hpp
index 85cfd30..cf5b7b9 100644
--- a/interface/vsomeip/trace.hpp
+++ b/interface/vsomeip/trace.hpp
@@ -2,8 +2,9 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef VSOMEIP_TRACE_HPP_
-#define VSOMEIP_TRACE_HPP_
+
+#ifndef VSOMEIP_V3_TRACE_HPP_
+#define VSOMEIP_V3_TRACE_HPP_
#include <memory>
#include <vector>
@@ -11,7 +12,7 @@
#include <vsomeip/constants.hpp>
#include <vsomeip/primitive_types.hpp>
-namespace vsomeip {
+namespace vsomeip_v3 {
/**
* \defgroup vsomeip
*
@@ -153,29 +154,29 @@ public:
*/
class connector {
public:
- /**
- * \brief Get access to the connector.
- *
- * \return Shared pointer to the singleton object.
- */
+ /**
+ * \brief Get access to the connector.
+ *
+ * \return Shared pointer to the singleton object.
+ */
static std::shared_ptr<connector> get();
virtual ~connector() {};
- /**
- * \brief Add a trace channel to the connector.
- *
- * Creates a trace channel with the given identifier and name
- * and adds it to the connector.
- *
- * \param _id Id of the trace channel.
- * \param _name Name of the trace channel
- *
- * \return Shared pointer to the created trace channel or
- * nullptr if the trace channel could not be created because
- * another trace channel with the given identifier does
- * already exist.
- */
+ /**
+ * \brief Add a trace channel to the connector.
+ *
+ * Creates a trace channel with the given identifier and name
+ * and adds it to the connector.
+ *
+ * \param _id Id of the trace channel.
+ * \param _name Name of the trace channel
+ *
+ * \return Shared pointer to the created trace channel or
+ * nullptr if the trace channel could not be created because
+ * another trace channel with the given identifier does
+ * already exist.
+ */
virtual std::shared_ptr<channel> add_channel(
const std::string &_id,
const std::string &_name) = 0;
@@ -203,7 +204,7 @@ public:
* of the default trace channel.
*
* \return Shared pointer to the created trace channel or
- * nullptr if the trace channel does not exist.
+ * nullptr if the trace channel does not exist.
*/
virtual std::shared_ptr<channel> get_channel(
const std::string &_id = VSOMEIP_TC_DEFAULT_CHANNEL_ID) const = 0;
@@ -213,6 +214,6 @@ public:
/** @} */
-} // namespace vsomeip
+} // namespace vsomeip_v3
-#endif // VSOMEIP_CONSTANTS_HPP
+#endif // VSOMEIP_V3_CONSTANTS_HPP_
diff --git a/interface/vsomeip/vsomeip.hpp b/interface/vsomeip/vsomeip.hpp
index 1068b0b..231fa3a 100644
--- a/interface/vsomeip/vsomeip.hpp
+++ b/interface/vsomeip/vsomeip.hpp
@@ -18,4 +18,6 @@
#include <vsomeip/runtime.hpp>
#include <vsomeip/trace.hpp>
+namespace vsomeip = vsomeip_v3;
+
#endif // VSOMEIP_VSOMEIP_HPP
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f8f1d5d..b3cd6a9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -67,18 +67,21 @@ endfunction()
##############################################################################
# configuration-test
##############################################################################
-if(NOT ${TESTS_BAT})
+if(NOT ${TESTS_BAT})
set(TEST_CONFIGURATION configuration-test)
- add_executable(${TEST_CONFIGURATION} configuration_tests/configuration-test.cpp)
+ add_executable(${TEST_CONFIGURATION}
+ configuration_tests/configuration-test.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/plugin/src/plugin_manager_impl.cpp
+ )
target_link_libraries(${TEST_CONFIGURATION}
- vsomeip
- vsomeip-cfg
+ vsomeip3
+ vsomeip3-cfg
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
)
-
+
# The following will make sure that ${TEST_CONFIGURATION_CONFIG_FILE} is copied
# from the config folder into the test folder in the builddirectory
# This makes it possible to call the configuration test within the build directory
@@ -101,7 +104,7 @@ if(NOT ${TESTS_BAT})
add_executable(${TEST_APPLICATION} application_tests/${TEST_APPLICATION}.cpp)
target_link_libraries(${TEST_APPLICATION}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -110,7 +113,7 @@ if(NOT ${TESTS_BAT})
set(TEST_APPLICATION_SINGLE_PROCESS_NAME ${TEST_APPLICATION}_single_process)
add_executable(${TEST_APPLICATION_SINGLE_PROCESS_NAME} application_tests/${TEST_APPLICATION_SINGLE_PROCESS_NAME}.cpp)
target_link_libraries(${TEST_APPLICATION_SINGLE_PROCESS_NAME}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -119,7 +122,7 @@ if(NOT ${TESTS_BAT})
set(TEST_APPLICATION_AVAILABILITY_NAME ${TEST_APPLICATION}_availability)
add_executable(${TEST_APPLICATION_AVAILABILITY_NAME} application_tests/${TEST_APPLICATION_AVAILABILITY_NAME}.cpp)
target_link_libraries(${TEST_APPLICATION_AVAILABILITY_NAME}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -176,7 +179,7 @@ if(NOT ${TESTS_BAT})
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_STARTER}
${TEST_APPLICATION}
)
-
+
set(TEST_APPLICATION_SINGLE_PROCESS_STARTER ${TEST_APPLICATION}_single_process_starter.sh)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/application_tests/${TEST_APPLICATION_SINGLE_PROCESS_STARTER}
${PROJECT_BINARY_DIR}/test/${TEST_APPLICATION_SINGLE_PROCESS_STARTER}
@@ -198,7 +201,7 @@ if(NOT ${TESTS_BAT})
set(TEST_MAGIC_COOKIES_CLIENT ${TEST_MAGIC_COOKIES_NAME}_client)
add_executable(${TEST_MAGIC_COOKIES_CLIENT} magic_cookies_tests/${TEST_MAGIC_COOKIES_CLIENT}.cpp)
target_link_libraries(${TEST_MAGIC_COOKIES_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
@@ -208,7 +211,7 @@ if(NOT ${TESTS_BAT})
set(TEST_MAGIC_COOKIES_SERVICE ${TEST_MAGIC_COOKIES_NAME}_service)
add_executable(${TEST_MAGIC_COOKIES_SERVICE} magic_cookies_tests/${TEST_MAGIC_COOKIES_SERVICE}.cpp)
target_link_libraries(${TEST_MAGIC_COOKIES_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
@@ -268,7 +271,7 @@ if(NOT ${TESTS_BAT})
set(TEST_HEADER_FACTORY header_factory_test)
add_executable(${TEST_HEADER_FACTORY} header_factory_tests/header_factory_test.cpp)
target_link_libraries(${TEST_HEADER_FACTORY}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
@@ -281,7 +284,7 @@ if(NOT ${TESTS_BAT})
set(TEST_HEADER_FACTORY_CLIENT header_factory_test_client)
add_executable(${TEST_HEADER_FACTORY_CLIENT} header_factory_tests/${TEST_HEADER_FACTORY_CLIENT}.cpp)
target_link_libraries(${TEST_HEADER_FACTORY_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
@@ -305,7 +308,7 @@ if(NOT ${TESTS_BAT})
set(TEST_HEADER_FACTORY_SERVICE header_factory_test_service)
add_executable(${TEST_HEADER_FACTORY_SERVICE} header_factory_tests/${TEST_HEADER_FACTORY_SERVICE}.cpp)
target_link_libraries(${TEST_HEADER_FACTORY_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
@@ -343,7 +346,7 @@ if(NOT ${TESTS_BAT})
set(TEST_LOCAL_ROUTING_SERVICE local_routing_test_service)
add_executable(${TEST_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_LOCAL_ROUTING_SERVICE}.cpp)
target_link_libraries(${TEST_LOCAL_ROUTING_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -366,7 +369,7 @@ if(NOT ${TESTS_BAT})
set(TEST_LOCAL_ROUTING_CLIENT local_routing_test_client)
add_executable(${TEST_LOCAL_ROUTING_CLIENT} routing_tests/${TEST_LOCAL_ROUTING_CLIENT}.cpp)
target_link_libraries(${TEST_LOCAL_ROUTING_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -402,7 +405,7 @@ if(NOT ${TESTS_BAT})
set(TEST_EXTERNAL_LOCAL_ROUTING_SERVICE external_local_routing_test_service)
add_executable(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}.cpp)
target_link_libraries(${TEST_EXTERNAL_LOCAL_ROUTING_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -460,7 +463,7 @@ else()
set(TEST_LOCAL_ROUTING_SERVICE local_routing_test_service)
add_executable(${TEST_LOCAL_ROUTING_SERVICE} routing_tests/${TEST_LOCAL_ROUTING_SERVICE}.cpp)
target_link_libraries(${TEST_LOCAL_ROUTING_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -483,7 +486,7 @@ else()
set(TEST_LOCAL_ROUTING_CLIENT local_routing_test_client)
add_executable(${TEST_LOCAL_ROUTING_CLIENT} routing_tests/${TEST_LOCAL_ROUTING_CLIENT}.cpp)
target_link_libraries(${TEST_LOCAL_ROUTING_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -524,7 +527,7 @@ if(NOT ${TESTS_BAT})
set(TEST_RESTART_ROUTING_SERVICE restart_routing_test_service)
add_executable(${TEST_RESTART_ROUTING_SERVICE} restart_routing_tests/${TEST_RESTART_ROUTING_SERVICE}.cpp)
target_link_libraries(${TEST_RESTART_ROUTING_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -551,7 +554,7 @@ if(NOT ${TESTS_BAT})
restart_routing_tests/${TEST_RESTART_ROUTING_CLIENT}.cpp
)
target_link_libraries(${TEST_RESTART_ROUTING_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -601,7 +604,7 @@ if (${TEST_SECURITY})
add_executable(${TEST_SECURITY_SERVICE} security_tests/${TEST_SECURITY_SERVICE}.cpp)
target_link_libraries(${TEST_SECURITY_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -695,7 +698,7 @@ if (${TEST_SECURITY})
security_tests/${TEST_SECURITY_CLIENT}.cpp
)
target_link_libraries(${TEST_SECURITY_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -713,7 +716,7 @@ if(NOT ${TESTS_BAT})
set(TEST_PAYLOAD_SERVICE payload_test_service)
add_executable(${TEST_PAYLOAD_SERVICE} payload_tests/${TEST_PAYLOAD_SERVICE}.cpp)
target_link_libraries(${TEST_PAYLOAD_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -741,7 +744,7 @@ if(NOT ${TESTS_BAT})
payload_tests/stopwatch.cpp
)
target_link_libraries(${TEST_PAYLOAD_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -892,7 +895,7 @@ if(NOT ${TESTS_BAT})
set(TEST_BIG_PAYLOAD_SERVICE big_payload_test_service)
add_executable(${TEST_BIG_PAYLOAD_SERVICE} big_payload_tests/${TEST_BIG_PAYLOAD_SERVICE}.cpp)
target_link_libraries(${TEST_BIG_PAYLOAD_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -901,7 +904,7 @@ if(NOT ${TESTS_BAT})
set(TEST_BIG_PAYLOAD_CLIENT big_payload_test_client)
add_executable(${TEST_BIG_PAYLOAD_CLIENT} big_payload_tests/${TEST_BIG_PAYLOAD_CLIENT}.cpp)
target_link_libraries(${TEST_BIG_PAYLOAD_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1058,6 +1061,27 @@ if(NOT ${TESTS_BAT})
${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_CONFIG_FILE_QUEUE_LIMITED_SPECIFIC}
${TEST_BIG_PAYLOAD_SERVICE}
)
+ # Copy config file for UDP client and service into $BUILDDIR/test
+ set(TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_UDP_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_udp_service.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_SERVICE_UDP_CONFIG_FILE}
+ ${TEST_BIG_PAYLOAD_SERVICE}
+ )
+ set(TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_UDP_CONFIG_FILE ${TEST_BIG_PAYLOAD_NAME}_udp_client.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/conf/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_CLIENT_UDP_CONFIG_FILE}
+ ${TEST_BIG_PAYLOAD_CLIENT}
+ )
# Copy bashscript to start client local to $BUILDDIR/test
set(TEST_LOCAL_BIG_PAYLOAD_CLIENT_START_SCRIPT ${TEST_BIG_PAYLOAD_NAME}_client_local_start.sh)
@@ -1091,6 +1115,7 @@ if(NOT ${TESTS_BAT})
set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_LIMITED_GENERAL big_payload_test_external_limited_general)
set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_QUEUE_LIMITED_GENERAL big_payload_test_external_queue_limited_general)
set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_QUEUE_LIMITED_SPECIFIC big_payload_test_external_queue_limited_specific)
+ set(TEST_EXTERNAL_BIG_PAYLOAD_NAME_UDP big_payload_test_external_udp)
set(TEST_EXTERNAL_BIG_PAYLOAD_STARTER ${TEST_EXTERNAL_BIG_PAYLOAD_NAME}_starter.sh)
copy_to_builddir(${PROJECT_SOURCE_DIR}/test/big_payload_tests/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER}
${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER}
@@ -1121,7 +1146,7 @@ if(NOT ${TESTS_BAT})
set(TEST_CLIENT_ID_SERVICE ${TEST_CLIENT_ID_NAME}_service)
add_executable(${TEST_CLIENT_ID_SERVICE} client_id_tests/${TEST_CLIENT_ID_NAME}_service.cpp)
target_link_libraries(${TEST_CLIENT_ID_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1132,8 +1157,8 @@ if(NOT ${TESTS_BAT})
client_id_tests/${TEST_CLIENT_ID_UTILITY}.cpp
${PROJECT_SOURCE_DIR}/implementation/utility/src/utility.cpp)
target_link_libraries(${TEST_CLIENT_ID_UTILITY}
- vsomeip
- vsomeip-cfg
+ vsomeip3
+ vsomeip3-cfg
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1315,7 +1340,7 @@ if(NOT ${TESTS_BAT})
set(TEST_SUBSCRIBE_NOTIFY_SERVICE ${TEST_SUBSCRIBE_NOTIFY_NAME}_service)
add_executable(${TEST_SUBSCRIBE_NOTIFY_SERVICE} subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_NAME}_service.cpp)
target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1370,6 +1395,30 @@ if(NOT ${TESTS_BAT})
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_master_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_SERVICE}
+ )
+
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_slave_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_SERVICE}
+ )
+
set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE
${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_master.json)
configure_file(
@@ -1418,6 +1467,30 @@ if(NOT ${TESTS_BAT})
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_master_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_SERVICE}
+ )
+
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_slave_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${TEST_SUBSCRIBE_NOTIFY_SERVICE}
+ )
+
set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE
${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_partial_same_ports_master.json)
configure_file(
@@ -1490,27 +1563,27 @@ if(NOT ${TESTS_BAT})
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
- set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE
- ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_master.json)
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_master_udp.json)
configure_file(
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE}.in
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE}
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE}
@ONLY)
copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE}
- ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE}
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE}
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
- set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_CONFIG_FILE
- ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_slave.json)
+ set(TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_UDP_CONFIG_FILE
+ ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_slave_udp.json)
configure_file(
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_CONFIG_FILE}.in
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_CONFIG_FILE}
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/conf/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_UDP_CONFIG_FILE}
@ONLY)
copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_CONFIG_FILE}
- ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_CONFIG_FILE}
+ ${PROJECT_SOURCE_DIR}/test/subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_SLAVE_UDP_CONFIG_FILE}
${TEST_SUBSCRIBE_NOTIFY_SERVICE}
)
@@ -1552,13 +1625,13 @@ if(NOT ${TESTS_BAT})
# subscribe_notify_test_one_event_two_eventgroups
set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME subscribe_notify_test_one_event_two_eventgroups)
-
+
# service
set(TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_service)
add_executable(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}.cpp)
target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1568,7 +1641,7 @@ if(NOT ${TESTS_BAT})
add_executable(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
subscribe_notify_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}.cpp)
target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1631,12 +1704,12 @@ if(NOT ${TESTS_BAT})
set(TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_service)
add_executable(${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE} subscribe_notify_one_tests/${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_service.cpp)
target_link_libraries(${TEST_SUBSCRIBE_NOTIFY_ONE_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
)
-
+
# Copy config files for test into $BUILDDIR/test
set(TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE
${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_master.json)
@@ -1736,7 +1809,7 @@ if(NOT ${TESTS_BAT})
cpu_load_tests/cpu_load_measurer.cpp
)
target_link_libraries(${TEST_CPU_LOAD_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1771,7 +1844,7 @@ if(NOT ${TESTS_BAT})
cpu_load_tests/cpu_load_measurer.cpp
)
target_link_libraries(${TEST_CPU_LOAD_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1820,16 +1893,16 @@ if(NOT ${TESTS_BAT})
set(TEST_INITIAL_EVENT_SERVICE ${TEST_INITIAL_EVENT_NAME}_service)
add_executable(${TEST_INITIAL_EVENT_SERVICE} initial_event_tests/${TEST_INITIAL_EVENT_NAME}_service.cpp)
target_link_libraries(${TEST_INITIAL_EVENT_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
)
-
+
set(TEST_INITIAL_EVENT_CLIENT ${TEST_INITIAL_EVENT_NAME}_client)
add_executable(${TEST_INITIAL_EVENT_CLIENT} initial_event_tests/${TEST_INITIAL_EVENT_NAME}_client.cpp)
target_link_libraries(${TEST_INITIAL_EVENT_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1838,7 +1911,7 @@ if(NOT ${TESTS_BAT})
set(TEST_INITIAL_EVENT_AVAILABILITY_CHECKER ${TEST_INITIAL_EVENT_NAME}_availability_checker)
add_executable(${TEST_INITIAL_EVENT_AVAILABILITY_CHECKER} initial_event_tests/${TEST_INITIAL_EVENT_NAME}_availability_checker.cpp)
target_link_libraries(${TEST_INITIAL_EVENT_AVAILABILITY_CHECKER}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1847,7 +1920,7 @@ if(NOT ${TESTS_BAT})
set(TEST_INITIAL_EVENT_STOP_SERVICE ${TEST_INITIAL_EVENT_NAME}_stop_service)
add_executable(${TEST_INITIAL_EVENT_STOP_SERVICE} initial_event_tests/${TEST_INITIAL_EVENT_NAME}_stop_service.cpp)
target_link_libraries(${TEST_INITIAL_EVENT_STOP_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -1891,6 +1964,19 @@ if(NOT ${TESTS_BAT})
${TEST_INITIAL_EVENT_SERVICE}
)
+ # Copy config files for test into $BUILDDIR/test
+ set(TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE
+ ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_master_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/conf/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${TEST_INITIAL_EVENT_SERVICE}
+ )
+
set(TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_TCP_CONFIG_FILE
${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_slave_tcp.json)
configure_file(
@@ -1903,6 +1989,18 @@ if(NOT ${TESTS_BAT})
${TEST_INITIAL_EVENT_SERVICE}
)
+ set(TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE
+ ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_slave_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/conf/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${TEST_INITIAL_EVENT_SERVICE}
+ )
+
set(TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE
${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_master.json)
configure_file(
@@ -1951,6 +2049,30 @@ if(NOT ${TESTS_BAT})
${TEST_INITIAL_EVENT_SERVICE}
)
+ set(TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE
+ ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_master_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/conf/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE}
+ ${TEST_INITIAL_EVENT_SERVICE}
+ )
+
+ set(TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE
+ ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_slave_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/conf/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/initial_event_tests/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_SLAVE_UDP_CONFIG_FILE}
+ ${TEST_INITIAL_EVENT_SERVICE}
+ )
+
set(TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE
${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_master.json)
configure_file(
@@ -2068,7 +2190,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFER_SERVICE ${TEST_OFFER_NAME}_service)
add_executable(${TEST_OFFER_SERVICE} offer_tests/${TEST_OFFER_NAME}_service.cpp)
target_link_libraries(${TEST_OFFER_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2077,7 +2199,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFER_CLIENT ${TEST_OFFER_NAME}_client)
add_executable(${TEST_OFFER_CLIENT} offer_tests/${TEST_OFFER_NAME}_client.cpp)
target_link_libraries(${TEST_OFFER_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2086,7 +2208,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFER_SERVICE_EXTERNAL ${TEST_OFFER_NAME}_service_external)
add_executable(${TEST_OFFER_SERVICE_EXTERNAL} offer_tests/${TEST_OFFER_NAME}_service_external.cpp)
target_link_libraries(${TEST_OFFER_SERVICE_EXTERNAL}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2105,7 +2227,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFER_BIG_SERVICE ${TEST_OFFER_BIG_NAME}_service)
add_executable(${TEST_OFFER_BIG_SERVICE} offer_tests/${TEST_OFFER_BIG_NAME}_service.cpp)
target_link_libraries(${TEST_OFFER_BIG_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2114,7 +2236,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFER_BIG_CLIENT ${TEST_OFFER_BIG_NAME}_client)
add_executable(${TEST_OFFER_BIG_CLIENT} offer_tests/${TEST_OFFER_BIG_NAME}_client.cpp)
target_link_libraries(${TEST_OFFER_BIG_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2223,7 +2345,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFERED_SERVICES_INFO_SERVICE ${TEST_OFFERED_SERVICES_INFO_NAME}_service)
add_executable(${TEST_OFFERED_SERVICES_INFO_SERVICE} offered_services_info_test/${TEST_OFFERED_SERVICES_INFO_NAME}_service.cpp)
target_link_libraries(${TEST_OFFERED_SERVICES_INFO_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2232,7 +2354,7 @@ if(NOT ${TESTS_BAT})
set(TEST_OFFERED_SERVICES_INFO_CLIENT ${TEST_OFFERED_SERVICES_INFO_NAME}_client)
add_executable(${TEST_OFFERED_SERVICES_INFO_CLIENT} offered_services_info_test/${TEST_OFFERED_SERVICES_INFO_NAME}_client.cpp)
target_link_libraries(${TEST_OFFERED_SERVICES_INFO_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2262,7 +2384,7 @@ if(NOT ${TESTS_BAT})
set(TEST_PENDING_SUBSCRIPTION_SERVICE ${TEST_PENDING_SUBSCRIPTION_NAME}_service)
add_executable(${TEST_PENDING_SUBSCRIPTION_SERVICE} pending_subscription_tests/${TEST_PENDING_SUBSCRIPTION_NAME}_service.cpp)
target_link_libraries(${TEST_PENDING_SUBSCRIPTION_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2286,8 +2408,8 @@ if(NOT ${TESTS_BAT})
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
- vsomeip
- vsomeip-sd
+ vsomeip3
+ vsomeip3-sd
)
# copy starter scripts into builddir
@@ -2322,7 +2444,7 @@ if(NOT ${TESTS_BAT})
set(TEST_MALICIOUS_DATA_SERVICE ${TEST_MALICIOUS_DATA_NAME}_service)
add_executable(${TEST_MALICIOUS_DATA_SERVICE} malicious_data_tests/${TEST_MALICIOUS_DATA_NAME}_service.cpp)
target_link_libraries(${TEST_MALICIOUS_DATA_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2346,8 +2468,8 @@ if(NOT ${TESTS_BAT})
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
- vsomeip
- vsomeip-sd
+ vsomeip3
+ vsomeip3-sd
)
# copy starter scripts into builddir
@@ -2375,132 +2497,6 @@ if(NOT ${TESTS_BAT})
endif()
##############################################################################
-# security_config_plugin_test
-##############################################################################
-if (${TEST_SECURITY})
- if(NOT ${TESTS_BAT})
- set(TEST_SECURITY_CONFIG_PLUGIN_NAME security_config_plugin_test)
- set(TEST_SECURITY_CONFIG_PLUGIN_CLIENT ${TEST_SECURITY_CONFIG_PLUGIN_NAME}_client)
- add_executable(${TEST_SECURITY_CONFIG_PLUGIN_CLIENT}
- security_config_plugin_tests/${TEST_SECURITY_CONFIG_PLUGIN_CLIENT}.cpp
- )
-
- set(TEST_SECURITY_CONFIG_PLUGIN_SERVICE ${TEST_SECURITY_CONFIG_PLUGIN_NAME}_service)
- add_executable(${TEST_SECURITY_CONFIG_PLUGIN_SERVICE}
- security_config_plugin_tests/${TEST_SECURITY_CONFIG_PLUGIN_SERVICE}.cpp
- )
-
- message(STATUS "Using uid: ${TEST_UID}, gid: ${TEST_GID}")
-
- # Copy config file for vsomeipd, client and service into $BUILDDIR/test
- set(TEST_SECURITY_CONFIG_PLUGIN_LOCAL_CONFIG_FILE ${TEST_SECURITY_CONFIG_PLUGIN_NAME}_local.json)
- configure_file(
- ${PROJECT_SOURCE_DIR}/test/security_config_plugin_tests/conf/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_CONFIG_FILE}.in
- ${PROJECT_SOURCE_DIR}/test/security_config_plugin_tests/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_CONFIG_FILE}
- @ONLY)
-
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/security_config_plugin_tests/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_CONFIG_FILE}
- ${PROJECT_BINARY_DIR}/test/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_CONFIG_FILE}
- ${TEST_SECURITY_CONFIG_PLUGIN_CLIENT}
- ${TEST_SECURITY_CONFIG_PLUGIN_SERVICE}
- )
-
-
- # Copy bashscript to start vsomeipd and client into $BUILDDIR/test
- set(TEST_SECURITY_CONFIG_PLUGIN_LOCAL_STARTER ${TEST_SECURITY_CONFIG_PLUGIN_NAME}_local_starter.sh)
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/security_config_plugin_tests/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_STARTER}
- ${PROJECT_BINARY_DIR}/test/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_STARTER}
- ${TEST_SECURITY_CONFIG_PLUGIN_CLIENT}
- ${TEST_SECURITY_CONFIG_PLUGIN_SERVICE}
- )
-
- target_link_libraries(${TEST_SECURITY_CONFIG_PLUGIN_CLIENT}
- vsomeip
- ${Boost_LIBRARIES}
- ${DL_LIBRARY}
- ${TEST_LINK_LIBRARIES}
- )
-
- target_link_libraries(${TEST_SECURITY_CONFIG_PLUGIN_SERVICE}
- vsomeip
- ${Boost_LIBRARIES}
- ${DL_LIBRARY}
- ${TEST_LINK_LIBRARIES}
- )
- endif()
-endif()
-
-#############################################################################
-# debug_diag_job_plugin_test
-##############################################################################
-
-if(NOT ${TESTS_BAT})
- set(TEST_DEBUG_DIAG_JOB_NAME debug_diag_job_plugin_test)
-
- set(TEST_DEBUG_DIAG_JOB_SERVICE ${TEST_DEBUG_DIAG_JOB_NAME}_service)
- add_executable(${TEST_DEBUG_DIAG_JOB_SERVICE} debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_SERVICE}.cpp)
- target_link_libraries(${TEST_DEBUG_DIAG_JOB_SERVICE}
- vsomeip
- ${Boost_LIBRARIES}
- ${DL_LIBRARY}
- ${TEST_LINK_LIBRARIES}
- )
-
- # Copy config file for service into $BUILDDIR/test
- set(TEST_DEBUG_DIAG_JOB_MASTER_CONFIG_FILE ${TEST_DEBUG_DIAG_JOB_NAME}_master.json)
- configure_file(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/conf/${TEST_DEBUG_DIAG_JOB_MASTER_CONFIG_FILE}.in
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_MASTER_CONFIG_FILE}
- @ONLY)
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_MASTER_CONFIG_FILE}
- ${PROJECT_BINARY_DIR}/test/${TEST_DEBUG_DIAG_JOB_MASTER_CONFIG_FILE}
- ${TEST_DEBUG_DIAG_JOB_SERVICE}
- )
-
- # Copy bashscript to start service into $BUILDDIR/test
- set(TEST_DEBUG_DIAG_JOB_MASTER_STARTER ${TEST_DEBUG_DIAG_JOB_NAME}_master_starter.sh)
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_MASTER_STARTER}
- ${PROJECT_BINARY_DIR}/test/${TEST_DEBUG_DIAG_JOB_MASTER_STARTER}
- ${TEST_DEBUG_DIAG_JOB_SERVICE}
- )
-
- set(TEST_DEBUG_DIAG_JOB_CLIENT ${TEST_DEBUG_DIAG_JOB_NAME}_client)
- add_executable(${TEST_DEBUG_DIAG_JOB_CLIENT}
- debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_CLIENT}.cpp
- )
- target_link_libraries(${TEST_DEBUG_DIAG_JOB_CLIENT}
- vsomeip
- ${Boost_LIBRARIES}
- ${DL_LIBRARY}
- ${TEST_LINK_LIBRARIES}
- )
-
- # Copy config file for client into $BUILDDIR/test
- set(TEST_DEBUG_DIAG_JOB_SLAVE_CONFIG_FILE ${TEST_DEBUG_DIAG_JOB_NAME}_slave.json)
- configure_file(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/conf/${TEST_DEBUG_DIAG_JOB_SLAVE_CONFIG_FILE}.in
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_SLAVE_CONFIG_FILE}
- @ONLY)
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_SLAVE_CONFIG_FILE}
- ${PROJECT_BINARY_DIR}/test/${TEST_DEBUG_DIAG_JOB_SLAVE_CONFIG_FILE}
- ${TEST_DEBUG_DIAG_JOB_CLIENT}
- )
-
- # Copy bashscript to start client into $BUILDDIR/test
- set(TEST_DEBUG_DIAG_JOB_SLAVE_STARTER ${TEST_DEBUG_DIAG_JOB_NAME}_slave_starter.sh)
- copy_to_builddir(
- ${PROJECT_SOURCE_DIR}/test/debug_diag_job_plugin_tests/${TEST_DEBUG_DIAG_JOB_SLAVE_STARTER}
- ${PROJECT_BINARY_DIR}/test/${TEST_DEBUG_DIAG_JOB_SLAVE_STARTER}
- ${TEST_DEBUG_DIAG_JOB_CLIENT}
- )
-endif()
-
-##############################################################################
# e2e test
##############################################################################
@@ -2511,7 +2507,7 @@ if(NOT ${TESTS_BAT})
add_executable(${TEST_E2E_SERVICE} e2e_tests/${TEST_E2E_SERVICE}.cpp)
target_link_libraries(${TEST_E2E_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2521,7 +2517,7 @@ if(NOT ${TESTS_BAT})
e2e_tests/${TEST_E2E_CLIENT}.cpp
)
target_link_libraries(${TEST_E2E_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2579,7 +2575,7 @@ if(NOT ${TESTS_BAT})
add_executable(${TEST_EVENT_SERVICE} event_tests/${TEST_EVENT_SERVICE}.cpp)
target_link_libraries(${TEST_EVENT_SERVICE}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2589,7 +2585,7 @@ if(NOT ${TESTS_BAT})
event_tests/${TEST_EVENT_CLIENT}.cpp
)
target_link_libraries(${TEST_EVENT_CLIENT}
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${TEST_LINK_LIBRARIES}
@@ -2646,6 +2642,367 @@ if(NOT ${TESTS_BAT})
endif()
+##############################################################################
+# npdu-test
+##############################################################################
+if(NOT ${TESTS_BAT})
+ set(TEST_NPDU_NAME npdu_test)
+
+ set(TEST_NPDU_DAEMON npdu_test_rmd)
+ set(TEST_NPDU_DAEMON_CLIENT ${TEST_NPDU_DAEMON}_client_side)
+ add_executable(${TEST_NPDU_DAEMON_CLIENT} npdu_tests/${TEST_NPDU_DAEMON}.cpp)
+ set_target_properties(${TEST_NPDU_DAEMON_CLIENT} PROPERTIES COMPILE_FLAGS -DRMD_CLIENT_SIDE)
+ target_link_libraries(${TEST_NPDU_DAEMON_CLIENT}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_DAEMON_SERVICE ${TEST_NPDU_DAEMON}_service_side)
+ add_executable(${TEST_NPDU_DAEMON_SERVICE} npdu_tests/${TEST_NPDU_DAEMON}.cpp)
+ set_target_properties(${TEST_NPDU_DAEMON_SERVICE} PROPERTIES COMPILE_FLAGS -DRMD_SERVICE_SIDE)
+ target_link_libraries(${TEST_NPDU_DAEMON_SERVICE}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ ##############################################################################
+
+ set(TEST_NPDU_SERVICE npdu_test_service)
+
+ set(TEST_NPDU_SERVICE_ONE npdu_test_service_1)
+ add_executable(${TEST_NPDU_SERVICE_ONE} npdu_tests/${TEST_NPDU_SERVICE}.cpp)
+ set_target_properties(${TEST_NPDU_SERVICE_ONE} PROPERTIES COMPILE_FLAGS -DSERVICE_NUMBER=0)
+ target_link_libraries(${TEST_NPDU_SERVICE_ONE}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_SERVICE_TWO npdu_test_service_2)
+ add_executable(${TEST_NPDU_SERVICE_TWO} npdu_tests/${TEST_NPDU_SERVICE}.cpp)
+ set_target_properties(${TEST_NPDU_SERVICE_TWO} PROPERTIES COMPILE_FLAGS -DSERVICE_NUMBER=1)
+ target_link_libraries(${TEST_NPDU_SERVICE_TWO}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_SERVICE_THREE npdu_test_service_3)
+ add_executable(${TEST_NPDU_SERVICE_THREE} npdu_tests/${TEST_NPDU_SERVICE}.cpp)
+ set_target_properties(${TEST_NPDU_SERVICE_THREE} PROPERTIES COMPILE_FLAGS -DSERVICE_NUMBER=2)
+ target_link_libraries(${TEST_NPDU_SERVICE_THREE}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_SERVICE_FOUR npdu_test_service_4)
+ add_executable(${TEST_NPDU_SERVICE_FOUR} npdu_tests/${TEST_NPDU_SERVICE}.cpp)
+ set_target_properties(${TEST_NPDU_SERVICE_FOUR} PROPERTIES COMPILE_FLAGS -DSERVICE_NUMBER=3)
+ target_link_libraries(${TEST_NPDU_SERVICE_FOUR}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ # Copy config file for service w/o npdu into $BUILDDIR/test
+ set(TEST_NPDU_SERVICE_CONFIG_FILE ${TEST_NPDU_SERVICE}_no_npdu.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/conf/${TEST_NPDU_SERVICE_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ ${TEST_NPDU_SERVICE_ONE}
+ )
+
+ # Copy bashscript to start service w/o npdu into $BUILDDIR/test
+ set(TEST_NPDU_SERVICE_START_SCRIPT ${TEST_NPDU_SERVICE}_no_npdu_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_SERVICE_START_SCRIPT}
+ ${TEST_NPDU_SERVICE_ONE}
+ )
+
+ # Copy config file for service with npdu into $BUILDDIR/test
+ set(TEST_NPDU_SERVICE_CONFIG_FILE ${TEST_NPDU_SERVICE}_npdu.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/conf/${TEST_NPDU_SERVICE_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_SERVICE_CONFIG_FILE}
+ ${TEST_NPDU_SERVICE_ONE}
+ )
+
+ # Copy bashscript to start service with npdu into $BUILDDIR/test
+ set(TEST_NPDU_SERVICE_START_SCRIPT ${TEST_NPDU_SERVICE}_npdu_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_SERVICE_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_SERVICE_START_SCRIPT}
+ ${TEST_NPDU_SERVICE_ONE}
+ )
+
+ ##############################################################################
+
+ set(TEST_NPDU_CLIENT npdu_test_client)
+
+ set(TEST_NPDU_CLIENT_ONE npdu_test_client_1)
+ add_executable(${TEST_NPDU_CLIENT_ONE} npdu_tests/${TEST_NPDU_CLIENT}.cpp)
+ target_link_libraries(${TEST_NPDU_CLIENT_ONE}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_CLIENT_TWO npdu_test_client_2)
+ add_executable(${TEST_NPDU_CLIENT_TWO} npdu_tests/${TEST_NPDU_CLIENT}.cpp)
+ target_link_libraries(${TEST_NPDU_CLIENT_TWO}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_CLIENT_THREE npdu_test_client_3)
+ add_executable(${TEST_NPDU_CLIENT_THREE} npdu_tests/${TEST_NPDU_CLIENT}.cpp)
+ target_link_libraries(${TEST_NPDU_CLIENT_THREE}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_NPDU_CLIENT_FOUR npdu_test_client_4)
+ add_executable(${TEST_NPDU_CLIENT_FOUR} npdu_tests/${TEST_NPDU_CLIENT}.cpp)
+ target_link_libraries(${TEST_NPDU_CLIENT_FOUR}
+ vsomeip3
+ vsomeip3-cfg
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ # Copy config files for client w/o npdu into $BUILDDIR/test
+ set(TEST_NPDU_CLIENT_CONFIG_FILE ${TEST_NPDU_CLIENT}_no_npdu.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/conf/${TEST_NPDU_CLIENT_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ ${TEST_NPDU_CLIENT_ONE}
+ )
+
+ # Copy bashscript to start client w/o npdu into $BUILDDIR/test
+ set(TEST_NPDU_CLIENT_START_SCRIPT ${TEST_NPDU_CLIENT}_no_npdu_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_CLIENT_START_SCRIPT}
+ ${TEST_NPDU_CLIENT_ONE}
+ )
+
+ # Copy config file for client with npdu into $BUILDDIR/test
+ set(TEST_NPDU_CLIENT_CONFIG_FILE ${TEST_NPDU_CLIENT}_npdu.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/conf/${TEST_NPDU_CLIENT_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_CLIENT_CONFIG_FILE}
+ ${TEST_NPDU_CLIENT_ONE}
+ )
+
+ # Copy bashscript to start client with npdu into $BUILDDIR/test
+ set(TEST_NPDU_CLIENT_START_SCRIPT ${TEST_NPDU_CLIENT}_npdu_start.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_CLIENT_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_CLIENT_START_SCRIPT}
+ ${TEST_NPDU_CLIENT_ONE}
+ )
+
+ ##############################################################################
+
+ set(TEST_NPDU_STARTER ${TEST_NPDU_NAME}_starter.sh)
+ copy_to_builddir(${PROJECT_SOURCE_DIR}/test/npdu_tests/${TEST_NPDU_STARTER}
+ ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_STARTER}
+ ${TEST_NPDU_DAEMON_CLIENT}
+ )
+endif()
+
+##############################################################################
+# someip tp tests
+##############################################################################
+
+if(NOT ${TESTS_BAT})
+ set(TEST_SOMEIPTP_NAME someip_tp_test)
+ set(TEST_SOMEIPTP_SERVICE ${TEST_SOMEIPTP_NAME}_service)
+
+ add_executable(${TEST_SOMEIPTP_SERVICE} someip_tp_tests/${TEST_SOMEIPTP_SERVICE}.cpp)
+ target_link_libraries(${TEST_SOMEIPTP_SERVICE}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ file(GLOB sd_sources
+ "../implementation/service_discovery/src/*entry*.cpp"
+ "../implementation/service_discovery/src/*option*.cpp"
+ "../implementation/service_discovery/src/*message*.cpp"
+ )
+ set(TEST_SOMEIPTP_CLIENT ${TEST_SOMEIPTP_NAME}_msg_sender)
+ add_executable(${TEST_SOMEIPTP_CLIENT}
+ someip_tp_tests/${TEST_SOMEIPTP_CLIENT}.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/message/src/deserializer.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/message/src/message_impl.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/message/src/payload_impl.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/endpoints/src/tp.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/endpoints/src/tp_reassembler.cpp
+ ${PROJECT_SOURCE_DIR}/implementation/endpoints/src/tp_message.cpp
+ ${sd_sources}
+ )
+
+ target_link_libraries(${TEST_SOMEIPTP_CLIENT}
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ vsomeip3
+ vsomeip3-sd
+ )
+
+ # Copy service config file for external allow tests into $BUILDDIR/test
+ set(TEST_SOMEIPTP_MASTER_CONFIG_FILE ${TEST_SOMEIPTP_NAME}_master.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/conf/${TEST_SOMEIPTP_MASTER_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/${TEST_SOMEIPTP_MASTER_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/${TEST_SOMEIPTP_MASTER_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_CONFIG_FILE}
+ ${TEST_SOMEIPTP_CLIENT}
+ )
+
+ # Copy bashscript to start test (master) into $BUILDDIR/test
+ set(TEST_SOMEIPTP_MASTER_START_SCRIPT ${TEST_SOMEIPTP_NAME}_master_starter.sh)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/conf/${TEST_SOMEIPTP_MASTER_START_SCRIPT}.in
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/${TEST_SOMEIPTP_MASTER_START_SCRIPT}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/someip_tp_tests/${TEST_SOMEIPTP_MASTER_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT}
+ ${TEST_SOMEIPTP_SERVICE}
+ )
+endif()
+
+##############################################################################
+# second IP address tests
+##############################################################################
+
+if(NOT ${TESTS_BAT} AND ${TEST_SECOND_ADDRESS})
+ set(TEST_SECOND_ADDRESS_NAME second_address_test)
+ set(TEST_SECOND_ADDRESS_SERVICE ${TEST_SECOND_ADDRESS_NAME}_service)
+ set(TEST_SECOND_ADDRESS_CLIENT ${TEST_SECOND_ADDRESS_NAME}_client)
+
+ add_executable(${TEST_SECOND_ADDRESS_SERVICE}
+ second_address_tests/${TEST_SECOND_ADDRESS_SERVICE}.cpp
+ )
+ target_link_libraries(${TEST_SECOND_ADDRESS_SERVICE}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ add_executable(${TEST_SECOND_ADDRESS_CLIENT}
+ second_address_tests/${TEST_SECOND_ADDRESS_CLIENT}.cpp
+ )
+ target_link_libraries(${TEST_SECOND_ADDRESS_CLIENT}
+ vsomeip3
+ ${Boost_LIBRARIES}
+ ${DL_LIBRARY}
+ ${TEST_LINK_LIBRARIES}
+ )
+
+ set(TEST_SECOND_ADDRESS_MASTER_SERVICE_UDP_CONFIG_FILE ${TEST_SECOND_ADDRESS_NAME}_master_service_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/conf/${TEST_SECOND_ADDRESS_MASTER_SERVICE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_MASTER_SERVICE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_MASTER_SERVICE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_MASTER_SERVICE_UDP_CONFIG_FILE}
+ ${TEST_SECOND_ADDRESS_SERVICE}
+ )
+
+ set(TEST_SECOND_ADDRESS_SLAVE_CLIENT_CONFIG_FILE ${TEST_SECOND_ADDRESS_NAME}_slave_client.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/conf/${TEST_SECOND_ADDRESS_SLAVE_CLIENT_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_CLIENT_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_SLAVE_CLIENT_CONFIG_FILE}
+ ${TEST_SECOND_ADDRESS_CLIENT}
+ )
+
+ set(TEST_SECOND_ADDRESS_MASTER_CLIENT_CONFIG_FILE ${TEST_SECOND_ADDRESS_NAME}_master_client.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/conf/${TEST_SECOND_ADDRESS_MASTER_CLIENT_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_MASTER_CLIENT_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_MASTER_CLIENT_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_MASTER_CLIENT_CONFIG_FILE}
+ ${TEST_SECOND_ADDRESS_CLIENT}
+ )
+
+ set(TEST_SECOND_ADDRESS_SLAVE_SERVICE_UDP_CONFIG_FILE ${TEST_SECOND_ADDRESS_NAME}_slave_service_udp.json)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/conf/${TEST_SECOND_ADDRESS_SLAVE_SERVICE_UDP_CONFIG_FILE}.in
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_SERVICE_UDP_CONFIG_FILE}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_SERVICE_UDP_CONFIG_FILE}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_SLAVE_SERVICE_UDP_CONFIG_FILE}
+ ${TEST_SECOND_ADDRESS_SERVICE}
+ )
+
+ set(TEST_SECOND_ADDRESS_MASTER_START_SCRIPT ${TEST_SECOND_ADDRESS_NAME}_master_starter.sh)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_MASTER_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_MASTER_START_SCRIPT}
+ ${TEST_SECOND_ADDRESS_SERVICE}
+ )
+
+ set(TEST_SECOND_ADDRESS_SLAVE_START_SCRIPT ${TEST_SECOND_ADDRESS_NAME}_slave_starter.sh)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/conf/${TEST_SECOND_ADDRESS_SLAVE_START_SCRIPT}.in
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_START_SCRIPT}
+ @ONLY)
+ copy_to_builddir(
+ ${PROJECT_SOURCE_DIR}/test/second_address_tests/${TEST_SECOND_ADDRESS_SLAVE_START_SCRIPT}
+ ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_SLAVE_START_SCRIPT}
+ ${TEST_SECOND_ADDRESS_CLIENT}
+ )
+endif()
##############################################################################
# Add for every test a dependency to gtest
@@ -2691,15 +3048,29 @@ if(NOT ${TESTS_BAT})
add_dependencies(${TEST_MALICIOUS_DATA_SERVICE} gtest)
add_dependencies(${TEST_MALICIOUS_DATA_CLIENT} gtest)
if (${TEST_SECURITY})
- add_dependencies(${TEST_SECURITY_CONFIG_PLUGIN_CLIENT} gtest)
- add_dependencies(${TEST_SECURITY_CONFIG_PLUGIN_SERVICE} gtest)
+ add_dependencies(${TEST_SECURITY_SERVICE} gtest)
+ add_dependencies(${TEST_SECURITY_CLIENT} gtest)
endif()
- add_dependencies(${TEST_DEBUG_DIAG_JOB_SERVICE} gtest)
- add_dependencies(${TEST_DEBUG_DIAG_JOB_CLIENT} gtest)
add_dependencies(${TEST_E2E_SERVICE} gtest)
add_dependencies(${TEST_E2E_CLIENT} gtest)
add_dependencies(${TEST_EVENT_SERVICE} gtest)
add_dependencies(${TEST_EVENT_CLIENT} gtest)
+ add_dependencies(${TEST_NPDU_SERVICE_ONE} gtest)
+ add_dependencies(${TEST_NPDU_SERVICE_TWO} gtest)
+ add_dependencies(${TEST_NPDU_SERVICE_THREE} gtest)
+ add_dependencies(${TEST_NPDU_SERVICE_FOUR} gtest)
+ add_dependencies(${TEST_NPDU_CLIENT_ONE} gtest)
+ add_dependencies(${TEST_NPDU_CLIENT_TWO} gtest)
+ add_dependencies(${TEST_NPDU_CLIENT_THREE} gtest)
+ add_dependencies(${TEST_NPDU_CLIENT_FOUR} gtest)
+ add_dependencies(${TEST_NPDU_DAEMON_CLIENT} gtest)
+ add_dependencies(${TEST_NPDU_DAEMON_SERVICE} gtest)
+ add_dependencies(${TEST_SOMEIPTP_CLIENT} gtest)
+ add_dependencies(${TEST_SOMEIPTP_SERVICE} gtest)
+ if(${TEST_SECOND_ADDRESS})
+ add_dependencies(${TEST_SECOND_ADDRESS_CLIENT} gtest)
+ add_dependencies(${TEST_SECOND_ADDRESS_SERVICE} gtest)
+ endif()
else()
add_dependencies(${TEST_LOCAL_ROUTING_SERVICE} gtest)
add_dependencies(${TEST_LOCAL_ROUTING_CLIENT} gtest)
@@ -2749,8 +3120,6 @@ if(NOT ${TESTS_BAT})
if (${TEST_SECURITY})
add_dependencies(build_tests ${TEST_SECURITY_SERVICE})
add_dependencies(build_tests ${TEST_SECURITY_CLIENT})
- add_dependencies(build_tests ${TEST_SECURITY_CONFIG_PLUGIN_CLIENT})
- add_dependencies(build_tests ${TEST_SECURITY_CONFIG_PLUGIN_SERVICE})
endif()
add_dependencies(build_tests ${TEST_OFFERED_SERVICES_INFO_CLIENT})
add_dependencies(build_tests ${TEST_OFFERED_SERVICES_INFO_SERVICE})
@@ -2758,18 +3127,33 @@ if(NOT ${TESTS_BAT})
add_dependencies(build_tests ${TEST_PENDING_SUBSCRIPTION_CLIENT})
add_dependencies(build_tests ${TEST_MALICIOUS_DATA_SERVICE})
add_dependencies(build_tests ${TEST_MALICIOUS_DATA_CLIENT})
- add_dependencies(build_tests ${TEST_DEBUG_DIAG_JOB_SERVICE})
- add_dependencies(build_tests ${TEST_DEBUG_DIAG_JOB_CLIENT})
add_dependencies(build_tests ${TEST_E2E_SERVICE})
add_dependencies(build_tests ${TEST_E2E_CLIENT})
add_dependencies(build_tests ${TEST_EVENT_SERVICE})
add_dependencies(build_tests ${TEST_EVENT_CLIENT})
+ add_dependencies(build_tests ${TEST_NPDU_SERVICE_ONE})
+ add_dependencies(build_tests ${TEST_NPDU_SERVICE_TWO})
+ add_dependencies(build_tests ${TEST_NPDU_SERVICE_THREE})
+ add_dependencies(build_tests ${TEST_NPDU_SERVICE_FOUR})
+ add_dependencies(build_tests ${TEST_NPDU_CLIENT_ONE})
+ add_dependencies(build_tests ${TEST_NPDU_CLIENT_TWO})
+ add_dependencies(build_tests ${TEST_NPDU_CLIENT_THREE})
+ add_dependencies(build_tests ${TEST_NPDU_CLIENT_FOUR})
+ add_dependencies(build_tests ${TEST_NPDU_DAEMON_CLIENT})
+ add_dependencies(build_tests ${TEST_NPDU_DAEMON_SERVICE})
+ add_dependencies(build_tests ${TEST_SOMEIPTP_CLIENT})
+ add_dependencies(build_tests ${TEST_SOMEIPTP_SERVICE})
+ if(${TEST_SECOND_ADDRESS})
+ add_dependencies(build_tests ${TEST_SECOND_ADDRESS_CLIENT})
+ add_dependencies(build_tests ${TEST_SECOND_ADDRESS_SERVICE})
+ endif()
else()
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_SERVICE})
add_dependencies(build_tests ${TEST_LOCAL_ROUTING_CLIENT})
endif()
-
+# some tests require the routingmanagerd
+add_dependencies(build_tests routingmanagerd)
##############################################################################
# Add tests
@@ -2888,6 +3272,11 @@ if(NOT ${TESTS_BAT})
)
set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_QUEUE_LIMITED_SPECIFIC} PROPERTIES TIMEOUT 120)
+ add_test(NAME ${TEST_EXTERNAL_BIG_PAYLOAD_NAME_UDP}
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EXTERNAL_BIG_PAYLOAD_STARTER} UDP
+ )
+ set_tests_properties(${TEST_EXTERNAL_BIG_PAYLOAD_NAME_UDP} PROPERTIES TIMEOUT 120)
+
# client id tests
add_test(NAME ${TEST_CLIENT_ID_NAME}_diff_client_ids_diff_ports
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CLIENT_ID_MASTER_STARTER} ${TEST_CLIENT_ID_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
@@ -2938,55 +3327,39 @@ if(NOT ${TESTS_BAT})
# subscribe notify tests
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} TCP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} TCP_AND_UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} PREFER_UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} PREFER_TCP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} TCP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} TCP_AND_UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} PREFER_UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} PREFER_TCP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_same_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} TCP_AND_UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
-
+
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_UDP_CONFIG_FILE} SAME_SERVICE_ID)
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_autoconfig_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_AUTOCONFIG_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_DIFF_IDS_DIFF_PORTS_AUTOCONFIG_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_NAME}_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_EVENT_TWO_EVENTGROUPS_NAME}_udp
@@ -2999,25 +3372,17 @@ if(NOT ${TESTS_BAT})
# subscribe notify one id tests
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} UDP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} TCP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} TCP_AND_UDP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} PREFER_UDP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SUBSCRIBE_NOTIFY_ONE_MASTER_STARTER} PREFER_TCP ${TEST_SUBSCRIBE_NOTIFY_ONE_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
- set_tests_properties(${TEST_SUBSCRIBE_NOTIFY_ONE_NAME}_diff_client_ids_diff_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
# cpu load tests
add_test(NAME ${TEST_CPU_LOAD_NAME}
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_CPU_LOAD_MASTER_STARTER}
@@ -3026,159 +3391,111 @@ if(NOT ${TESTS_BAT})
# initial event tests
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE})
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE})
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE})
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE})
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_same_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE})
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE} SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_same_service_id_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE} MULTIPLE_EVENTS)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE} MULTIPLE_EVENTS)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_same_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_partial_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_same_service_id_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID MULTIPLE_EVENTS)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID MULTIPLE_EVENTS)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_UDP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_prefer_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_prefer_udp PROPERTIES TIMEOUT 120)
-
- add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_prefer_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} PREFER_TCP ${TEST_INITIAL_EVENT_DIFF_IDS_SAME_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
- set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_same_ports_prefer_tcp PROPERTIES TIMEOUT 120)
-
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_partial_same_ports_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_PARTIAL_SAME_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY SERVICE_OFFERED_TCP_AND_UDP)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_partial_same_ports_both_tcp_and_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_same_service_id_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_SAME_SERVICEID_MASTER_CONFIG_FILE} SAME_SERVICE_ID MULTIPLE_EVENTS SUBSCRIBE_ON_AVAILABILITY)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_subscribe_on_availability_diff_client_ids_diff_ports_same_service_id_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_UDP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_udp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_tcp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_tcp PROPERTIES TIMEOUT 120)
add_test(NAME ${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_both_tcp_and_udp
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} TCP_AND_UDP ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_TCP_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_INITIAL_EVENT_MASTER_STARTER} ${TEST_INITIAL_EVENT_DIFF_IDS_DIFF_PORTS_MASTER_CONFIG_FILE} MULTIPLE_EVENTS SUBSCRIBE_ONLY_ONE)
set_tests_properties(${TEST_INITIAL_EVENT_NAME}_multiple_events_diff_client_ids_diff_ports_partial_subscription_both_tcp_and_udp PROPERTIES TIMEOUT 120)
# offer tests
@@ -3191,12 +3508,12 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_OFFER_BIG_NAME}
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_OFFER_BIG_MASTER_STARTER})
set_tests_properties(${TEST_OFFER_BIG_NAME} PROPERTIES TIMEOUT 360)
-
+
# offered services info tets
add_test(NAME ${TEST_OFFERED_SERVICES_INFO_NAME}_local
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_OFFERED_SERVICES_INFO_LOCAL_STARTER})
- set_tests_properties(${TEST_OFFERED_SERVICES_INFO_NAME}_local PROPERTIES TIMEOUT 180)
-
+ set_tests_properties(${TEST_OFFERED_SERVICES_INFO_NAME}_local PROPERTIES TIMEOUT 180)
+
# Restart-Routing tests
add_test(NAME ${TEST_RESTART_ROUTING_NAME}
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_RESTART_ROUTING_STARTER}
@@ -3212,11 +3529,6 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_SECURITY_NAME}_external_deny
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SECURITY_EXTERNAL_MASTER_START_SCRIPT} security_test_config_client_external_deny.json --deny
)
-
- # security_config_plugin_test
- add_test(NAME ${TEST_SECURITY_CONFIG_PLUGIN_NAME}
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SECURITY_CONFIG_PLUGIN_LOCAL_STARTER})
- set_tests_properties(${TEST_SECURITY_CONFIG_PLUGIN_NAME} PROPERTIES TIMEOUT 180)
endif()
# pending subscriptions test
@@ -3273,10 +3585,14 @@ if(NOT ${TESTS_BAT})
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_MALICIOUS_DATA_MASTER_STARTER} WRONG_HEADER_FIELDS_UDP)
set_tests_properties(${TEST_MALICIOUS_DATA_NAME}_wrong_header_fields_udp PROPERTIES TIMEOUT 180)
- # debug_diag_job_plugin_test
- add_test(NAME ${TEST_DEBUG_DIAG_JOB_NAME}
- COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_DEBUG_DIAG_JOB_MASTER_STARTER})
- set_tests_properties(${TEST_DEBUG_DIAG_JOB_NAME} PROPERTIES TIMEOUT 180)
+ # npdu tests
+ add_test(NAME ${TEST_NPDU_NAME}_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_STARTER} UDP sync)
+ set_tests_properties(${TEST_NPDU_NAME}_udp PROPERTIES TIMEOUT 840)
+
+ add_test(NAME ${TEST_NPDU_NAME}_tcp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_NPDU_STARTER} TCP sync)
+ set_tests_properties(${TEST_NPDU_NAME}_tcp PROPERTIES TIMEOUT 840)
# e2e test
add_test(NAME ${TEST_E2E_NAME}_external
@@ -3299,6 +3615,43 @@ if(NOT ${TESTS_BAT})
add_test(NAME ${TEST_EVENT_NAME}_payload_dynamic_tcp
COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_EVENT_MASTER_START_SCRIPT} PAYLOAD_DYNAMIC TCP)
set_tests_properties(${TEST_EVENT_NAME}_payload_dynamic_tcp PROPERTIES TIMEOUT 180)
+
+ # SOME/IP-TP tests
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_in_sequence
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} IN_SEQUENCE)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_in_sequence PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_mixed
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} MIXED)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_mixed PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_incomplete
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} INCOMPLETE)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_incomplete PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_duplicate
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} DUPLICATE)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_duplicate PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_overlap
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} OVERLAP)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_overlap PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SOMEIPTP_NAME}_overlap_front_back
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SOMEIPTP_MASTER_START_SCRIPT} OVERLAP_FRONT_BACK)
+ set_tests_properties(${TEST_SOMEIPTP_NAME}_overlap_front_back PROPERTIES TIMEOUT 180)
+
+ if(${TEST_SECOND_ADDRESS})
+ add_test(NAME ${TEST_SECOND_ADDRESS_NAME}_second_ip_address_service_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_MASTER_START_SCRIPT} SERVICE UDP
+ )
+ set_tests_properties(${TEST_SECOND_ADDRESS_NAME}_second_ip_address_service_udp PROPERTIES TIMEOUT 180)
+
+ add_test(NAME ${TEST_SECOND_ADDRESS_NAME}_second_ip_address_client_udp
+ COMMAND ${PROJECT_BINARY_DIR}/test/${TEST_SECOND_ADDRESS_MASTER_START_SCRIPT} CLIENT UDP
+ )
+ set_tests_properties(${TEST_SECOND_ADDRESS_NAME}_second_ip_address_client_udp PROPERTIES TIMEOUT 180)
+ endif()
else()
# Routing tests
add_test(NAME ${TEST_LOCAL_ROUTING_NAME}
diff --git a/test/application_tests/application_test.cpp b/test/application_tests/application_test.cpp
index 7862528..e39cf1f 100644
--- a/test/application_tests/application_test.cpp
+++ b/test/application_tests/application_test.cpp
@@ -250,6 +250,8 @@ protected:
void TearDown() {
shutdown_thread_.join();
app_->stop();
+ app_.reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
void on_state(vsomeip::state_type_e _state) {
@@ -283,15 +285,23 @@ protected:
void send_shutdown_message() {
{
std::unique_lock<std::mutex> its_lock(mutex_);
- while(!is_registered_) {
- cv_.wait(its_lock);
+ while (!is_registered_) {
+ if (std::cv_status::timeout
+ == cv_.wait_for(its_lock, std::chrono::seconds(10))) {
+ ADD_FAILURE()<< "Application wasn't registered in time!";
+ is_registered_ = true;
+ }
}
app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID);
app_->offer_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID);
- while(!is_available_) {
- cv_.wait(its_lock);
+ while (!is_available_) {
+ if (std::cv_status::timeout
+ == cv_.wait_for(its_lock, std::chrono::seconds(10))) {
+ ADD_FAILURE()<< "Service didn't become available in time!";
+ is_available_ = true;
+ }
}
}
@@ -316,6 +326,7 @@ protected:
void SetUp() {
is_registered_ = false;
is_available_ = false;
+ exception_method_called_ = false;
app_ = runtime::get()->create_application("application_test");
if (!app_->init()) {
@@ -352,6 +363,8 @@ protected:
void TearDown() {
shutdown_thread_.join();
app_->stop();
+ app_.reset();
+ std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
void on_state(vsomeip::state_type_e _state) {
@@ -385,6 +398,11 @@ protected:
void on_message_exception(const std::shared_ptr<message>& _request)
{
(void)_request;
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ exception_method_called_ = true;
+ cv_.notify_one();
+ }
throw std::invalid_argument("something went terribly wrong");
}
@@ -409,7 +427,13 @@ protected:
r->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
r->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN+1);
app_->send(r);
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+ {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!exception_method_called_) {
+ cv_.wait(its_lock);
+ }
+ }
//shutdown test
@@ -421,6 +445,7 @@ protected:
bool is_registered_;
bool is_available_;
+ bool exception_method_called_;
std::shared_ptr<application> app_;
std::condition_variable cv_;
std::mutex mutex_;
diff --git a/test/application_tests/application_test_client.cpp b/test/application_tests/application_test_client.cpp
index 25f7c09..30d0084 100644
--- a/test/application_tests/application_test_client.cpp
+++ b/test/application_tests/application_test_client.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "application_test_globals.hpp"
@@ -26,7 +26,6 @@ public:
application_test_client(struct application_test::service_info _service_info) :
service_info_(_service_info),
app_(vsomeip::runtime::get()->create_application("client")),
- service_available_(false),
wait_until_registered_(true),
wait_until_service_available_(true),
wait_for_stop_(true),
@@ -164,12 +163,14 @@ public:
<< " responses. Delta: " << sent_requests_ - received_responses_;
std::uint32_t counter(0);
if (check) {
- while(sent_requests_ < received_responses_) {
+ while(sent_requests_ == 0 || sent_requests_ < received_responses_) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if(++counter > 50) {
break;
}
}
+ EXPECT_GT(sent_requests_, 0u);
+ EXPECT_GT(received_responses_, 0u);
EXPECT_EQ(sent_requests_, received_responses_);
}
stop_condition_.notify_one();
@@ -178,7 +179,6 @@ public:
private:
struct application_test::service_info service_info_;
std::shared_ptr<vsomeip::application> app_;
- bool service_available_;
bool wait_until_registered_;
bool wait_until_service_available_;
diff --git a/test/application_tests/application_test_client_availability.cpp b/test/application_tests/application_test_client_availability.cpp
index 5148d58..16fe87b 100644
--- a/test/application_tests/application_test_client_availability.cpp
+++ b/test/application_tests/application_test_client_availability.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "application_test_globals.hpp"
diff --git a/test/application_tests/application_test_daemon.cpp b/test/application_tests/application_test_daemon.cpp
index 43876ea..2f0b244 100644
--- a/test/application_tests/application_test_daemon.cpp
+++ b/test/application_tests/application_test_daemon.cpp
@@ -7,7 +7,7 @@
#include <future>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
class application_test_daemon {
public:
diff --git a/test/application_tests/application_test_service.cpp b/test/application_tests/application_test_service.cpp
index 0064fd3..77d40cd 100644
--- a/test/application_tests/application_test_service.cpp
+++ b/test/application_tests/application_test_service.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "application_test_globals.hpp"
@@ -25,11 +25,10 @@ class application_test_service {
public:
application_test_service(struct application_test::service_info _service_info) :
service_info_(_service_info),
- // service with number 1 uses "vsomeipd" as application name
+ // service with number 1 uses "routingmanagerd" as application name
// this way the same json file can be reused for all local tests
- // including the ones with vsomeipd
+ // including the ones with routingmanagerd
app_(vsomeip::runtime::get()->create_application("service")),
- counter_(0),
wait_until_registered_(true),
stop_called_(false),
offer_thread_(std::bind(&application_test_service::run, this)) {
@@ -119,7 +118,6 @@ public:
private:
struct application_test::service_info service_info_;
std::shared_ptr<vsomeip::application> app_;
- std::uint32_t counter_;
bool wait_until_registered_;
std::mutex mutex_;
diff --git a/test/application_tests/application_test_single_process.cpp b/test/application_tests/application_test_single_process.cpp
index 1d0d4a0..b4497a7 100644
--- a/test/application_tests/application_test_single_process.cpp
+++ b/test/application_tests/application_test_single_process.cpp
@@ -11,14 +11,14 @@
TEST(someip_application_test_single_process, notify_increasing_counter)
{
// start application acting as daemon (rm_stub)
- application_test_daemon its_daemon;
+ auto its_daemon = std::make_shared<application_test_daemon>();
// start receiver service (rm_proxy)
application_test_service its_receiver(application_test::service);
// stop the daemon (rm_stub goes away)
- its_daemon.stop();
-
+ its_daemon->stop();
+ its_daemon.reset();
// restart client which tries to communicate with service multiple times
// thus it will always be the new routing manager
for (int var = 0; var < 10; ++var) {
diff --git a/test/application_tests/application_test_starter.sh b/test/application_tests/application_test_starter.sh
index 3efc1b4..bb17515 100755
--- a/test/application_tests/application_test_starter.sh
+++ b/test/application_tests/application_test_starter.sh
@@ -25,12 +25,12 @@ fi
cat <<End-of-message
*******************************************************************************
*******************************************************************************
-** Now running same tests with vsomeipd
+** Now running same tests with routingmanagerd
*******************************************************************************
*******************************************************************************
End-of-message
export VSOMEIP_CONFIGURATION=application_test_no_dispatch_threads_daemon.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
./application_test
if [ $? -ne 0 ]
@@ -42,7 +42,7 @@ kill $DAEMON_PID
wait $DAEMON_PID
export VSOMEIP_CONFIGURATION=application_test_daemon.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
./application_test
if [ $? -ne 0 ]
diff --git a/test/application_tests/conf/application_test_daemon.json.in b/test/application_tests/conf/application_test_daemon.json.in
index c84adf5..f7fd3dc 100644
--- a/test/application_tests/conf/application_test_daemon.json.in
+++ b/test/application_tests/conf/application_test_daemon.json.in
@@ -27,7 +27,7 @@
"reliable":"30503"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in b/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
index 8dec80e..8c7622a 100644
--- a/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
+++ b/test/application_tests/conf/application_test_no_dispatch_threads_daemon.json.in
@@ -26,7 +26,7 @@
"reliable":"30503"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/big_payload_tests/big_payload_test_client.cpp b/test/big_payload_tests/big_payload_test_client.cpp
index 23a7241..48ee6c2 100644
--- a/test/big_payload_tests/big_payload_test_client.cpp
+++ b/test/big_payload_tests/big_payload_test_client.cpp
@@ -10,7 +10,6 @@ big_payload_test_client::big_payload_test_client(
bool _use_tcp, big_payload_test::test_mode _test_mode) :
app_(vsomeip::runtime::get()->create_application("big_payload_test_client")),
request_(vsomeip::runtime::get()->create_request(_use_tcp)),
- running_(true),
blocked_(false),
is_available_(false),
test_mode_(_test_mode),
@@ -37,6 +36,9 @@ big_payload_test_client::big_payload_test_client(
case big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC:
service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_QUEUE_LIMITED_SPECIFIC;
break;
+ case big_payload_test::test_mode::UDP:
+ service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_UDP;
+ break;
default:
service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID;
break;
@@ -81,7 +83,10 @@ void big_payload_test_client::stop()
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
- ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4);
+ EXPECT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4);
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(3000));
+ EXPECT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_);
}
app_->clear_all_handler();
app_->stop();
@@ -93,9 +98,11 @@ void big_payload_test_client::join_sender_thread(){
|| test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
- ASSERT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4);
+ EXPECT_EQ(number_of_acknowledged_messages_, number_of_messages_to_send_ / 4);
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ EXPECT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_);
} else {
- ASSERT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_);
+ EXPECT_EQ(number_of_sent_messages_, number_of_acknowledged_messages_);
}
}
@@ -145,6 +152,8 @@ void big_payload_test_client::on_message(const std::shared_ptr<vsomeip::message>
if(test_mode_ == big_payload_test::test_mode::RANDOM) {
ASSERT_LT(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE_RANDOM);
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ EXPECT_EQ(big_payload_test::BIG_PAYLOAD_SIZE_UDP, _response->get_payload()->get_length());
} else {
ASSERT_EQ(_response->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE);
}
@@ -200,7 +209,7 @@ void big_payload_test_client::run()
for (unsigned int i = 0; i < number_of_messages_to_send_; i++)
{
if (test_mode_ == big_payload_test::test_mode::RANDOM) {
- unsigned int datasize(std::rand() % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM);
+ unsigned int datasize(static_cast<unsigned int>(std::rand()) % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM);
its_payload_data.assign(datasize, big_payload_test::DATA_CLIENT_TO_SERVICE);
} else if (test_mode_ == big_payload_test::test_mode::LIMITED
|| test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
@@ -214,13 +223,16 @@ void big_payload_test_client::run()
its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
big_payload_test::DATA_CLIENT_TO_SERVICE);
}
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE_UDP,
+ big_payload_test::DATA_CLIENT_TO_SERVICE);
} else {
its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
big_payload_test::DATA_CLIENT_TO_SERVICE);
}
its_payload->set_data(its_payload_data);
request_->set_payload(its_payload);
- app_->send(request_, true);
+ app_->send(request_);
if (test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
@@ -244,10 +256,10 @@ void big_payload_test_client::run()
|| test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
- ASSERT_EQ(number_of_messages_to_send_ / 4,
+ EXPECT_EQ(number_of_messages_to_send_ / 4,
number_of_acknowledged_messages_);
} else {
- ASSERT_EQ(number_of_sent_messages_,
+ EXPECT_EQ(number_of_sent_messages_,
number_of_acknowledged_messages_);
}
}
@@ -259,7 +271,7 @@ static big_payload_test::test_mode test_mode(big_payload_test::test_mode::UNKNOW
TEST(someip_big_payload_test, send_ten_messages_to_service)
{
- bool use_tcp = true;
+ bool use_tcp = (test_mode != big_payload_test::test_mode::UDP);
big_payload_test_client test_client_(use_tcp, test_mode);
if (test_client_.init()) {
test_client_.start();
@@ -282,6 +294,8 @@ int main(int argc, char** argv)
test_mode = big_payload_test::test_mode::QUEUE_LIMITED_GENERAL;
} else if (std::string("QUEUELIMITEDSPECIFIC") == std::string(argv[1])) {
test_mode = big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC;
+ } else if (std::string("UDP") == std::string(argv[1])) {
+ test_mode = big_payload_test::test_mode::UDP;
}
}
return RUN_ALL_TESTS();
diff --git a/test/big_payload_tests/big_payload_test_client.hpp b/test/big_payload_tests/big_payload_test_client.hpp
index fb03a8e..bb81fdc 100644
--- a/test/big_payload_tests/big_payload_test_client.hpp
+++ b/test/big_payload_tests/big_payload_test_client.hpp
@@ -17,7 +17,7 @@
#include <atomic>
#include "big_payload_test_globals.hpp"
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
class big_payload_test_client
{
@@ -39,7 +39,6 @@ private:
std::shared_ptr<vsomeip::message> request_;
std::mutex mutex_;
std::condition_variable condition_;
- bool running_;
bool blocked_;
bool is_available_;
big_payload_test::test_mode test_mode_;
diff --git a/test/big_payload_tests/big_payload_test_external_starter.sh b/test/big_payload_tests/big_payload_test_external_starter.sh
index 6c04a3d..aa2f1a5 100755
--- a/test/big_payload_tests/big_payload_test_external_starter.sh
+++ b/test/big_payload_tests/big_payload_test_external_starter.sh
@@ -10,9 +10,9 @@
# the testcase simply executes this script. This script then runs client
# and service and checks that both exit successfully.
-if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" && $1 != "QUEUELIMITEDGENERAL" && $1 != "QUEUELIMITEDSPECIFIC" ]]
+if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" && $1 != "QUEUELIMITEDGENERAL" && $1 != "QUEUELIMITEDSPECIFIC" && $1 != "UDP" ]]
then
- echo "The only allowed parameter to this script is RANDOM or LIMITED or LIMITEDGENERAL."
+ echo "The only allowed parameter to this script is RANDOM or LIMITED, LIMITEDGENERAL, QUEUELIMITEDGENERAL, QUEUELIMITEDSPECIFIC or UDP"
echo "Like $0 RANDOM"
exit 1
fi
@@ -28,6 +28,8 @@ elif [[ $# -gt 0 && $1 == "QUEUELIMITEDGENERAL" ]]; then
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client_queue_limited_general.json
elif [[ $# -gt 0 && $1 == "QUEUELIMITEDSPECIFIC" ]]; then
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client_queue_limited_specific.json
+elif [[ $# -gt 0 && $1 == "UDP" ]]; then
+ export VSOMEIP_CONFIGURATION=big_payload_test_udp_client.json
else
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_client.json
fi
@@ -37,15 +39,15 @@ BIG_PAYLOAD_TEST_PID=$!
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting big payload test on slave LXC"
if [[ $# -gt 0 ]]; then
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./big_payload_test_service_external_start.sh $1\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./big_payload_test_service_external_start.sh $1\"" &
else
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_TARGET_DIR/vsomeip/test; ./big_payload_test_service_external_start.sh"' &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./big_payload_test_service_external_start.sh"' &
fi
elif [ ! -z "$USE_DOCKER" ]; then
if [[ $# -gt 0 ]]; then
- docker run --name bpts --cap-add=NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./big_payload_test_service_external_start.sh $1" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./big_payload_test_service_external_start.sh $1" &
else
- docker run --name bpts --cap-add=NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./big_payload_test_service_external_start.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./big_payload_test_service_external_start.sh" &
fi
else
cat <<End-of-message
@@ -71,15 +73,5 @@ do
wait $job || ((FAIL+=1))
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker wait bpts
- docker rm bpts
-fi
-
# Check if client and server both exited successfully
-if [ $FAIL -eq 0 ]
-then
- exit 0
-else
- exit 1
-fi
+exit $FAIL
diff --git a/test/big_payload_tests/big_payload_test_globals.hpp b/test/big_payload_tests/big_payload_test_globals.hpp
index 5488259..187ff4a 100644
--- a/test/big_payload_tests/big_payload_test_globals.hpp
+++ b/test/big_payload_tests/big_payload_test_globals.hpp
@@ -10,6 +10,7 @@
namespace big_payload_test {
constexpr std::uint32_t BIG_PAYLOAD_SIZE = 1024*600;
+ constexpr std::uint32_t BIG_PAYLOAD_SIZE_UDP = 1024*30;
constexpr std::uint32_t BIG_PAYLOAD_SIZE_RANDOM = 1024*1024*10;
constexpr vsomeip::byte_t DATA_SERVICE_TO_CLIENT = 0xAA;
constexpr vsomeip::byte_t DATA_CLIENT_TO_SERVICE = 0xFF;
@@ -23,6 +24,7 @@ namespace big_payload_test {
constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_LIMITED_GENERAL = 0x1237;
constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_QUEUE_LIMITED_GENERAL = 0x1238;
constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_QUEUE_LIMITED_SPECIFIC = 0x1239;
+ constexpr vsomeip::service_t TEST_SERVICE_SERVICE_ID_UDP = 0x1240;
constexpr vsomeip::service_t TEST_SERVICE_INSTANCE_ID = 0x1;
constexpr vsomeip::method_t TEST_SERVICE_METHOD_ID = 0x8421;
@@ -33,6 +35,7 @@ namespace big_payload_test {
LIMITED_GENERAL,
QUEUE_LIMITED_GENERAL,
QUEUE_LIMITED_SPECIFIC,
+ UDP,
UNKNOWN
};
}
diff --git a/test/big_payload_tests/big_payload_test_local.json b/test/big_payload_tests/big_payload_test_local.json
index aa7b3ea..983dea6 100644
--- a/test/big_payload_tests/big_payload_test_local.json
+++ b/test/big_payload_tests/big_payload_test_local.json
@@ -15,11 +15,13 @@
[
{
"name":"big_payload_test_service",
- "id":"0x1277"
+ "id":"0x1277",
+ "max_dispatchers" : "0"
},
{
"name":"big_payload_test_client",
- "id":"0x1344"
+ "id":"0x1344",
+ "max_dispatchers" : "0"
}
],
"services":
diff --git a/test/big_payload_tests/big_payload_test_local_limited.json b/test/big_payload_tests/big_payload_test_local_limited.json
index a711df1..4e8c666 100644
--- a/test/big_payload_tests/big_payload_test_local_limited.json
+++ b/test/big_payload_tests/big_payload_test_local_limited.json
@@ -15,11 +15,13 @@
[
{
"name":"big_payload_test_service",
- "id":"0x1277"
+ "id":"0x1277",
+ "max_dispatchers" : "0"
},
{
"name":"big_payload_test_client",
- "id":"0x1344"
+ "id":"0x1344",
+ "max_dispatchers" : "0"
}
],
"services":
diff --git a/test/big_payload_tests/big_payload_test_local_queue_limited.json b/test/big_payload_tests/big_payload_test_local_queue_limited.json
index eac38b2..9700309 100644
--- a/test/big_payload_tests/big_payload_test_local_queue_limited.json
+++ b/test/big_payload_tests/big_payload_test_local_queue_limited.json
@@ -15,11 +15,13 @@
[
{
"name":"big_payload_test_service",
- "id":"0x1277"
+ "id":"0x1277",
+ "max_dispatchers" : "0"
},
{
"name":"big_payload_test_client",
- "id":"0x1344"
+ "id":"0x1344",
+ "max_dispatchers" : "0"
}
],
"services":
@@ -29,7 +31,7 @@
"instance":"0x5678"
}
],
- "endpoint-queue-limit-local" : "614430",
+ "endpoint-queue-limit-local" : "614429",
"routing":"big_payload_test_service",
"service-discovery":
{
diff --git a/test/big_payload_tests/big_payload_test_local_random.json b/test/big_payload_tests/big_payload_test_local_random.json
index b49683e..0cf2081 100644
--- a/test/big_payload_tests/big_payload_test_local_random.json
+++ b/test/big_payload_tests/big_payload_test_local_random.json
@@ -16,12 +16,12 @@
{
"name":"big_payload_test_service",
"id":"0x1277",
- "max_dispatch_time" : "5000"
+ "max_dispatchers" : "0"
},
{
"name":"big_payload_test_client",
"id":"0x1344",
- "max_dispatch_time" : "5000"
+ "max_dispatchers" : "0"
}
],
"services":
diff --git a/test/big_payload_tests/big_payload_test_service.cpp b/test/big_payload_tests/big_payload_test_service.cpp
index a6868cf..89fe838 100644
--- a/test/big_payload_tests/big_payload_test_service.cpp
+++ b/test/big_payload_tests/big_payload_test_service.cpp
@@ -36,6 +36,10 @@ big_payload_test_service::big_payload_test_service(big_payload_test::test_mode _
expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES / 2;
service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_QUEUE_LIMITED_SPECIFIC;
break;
+ case big_payload_test::test_mode::UDP:
+ expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES;
+ service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID_UDP;
+ break;
default:
expected_messages_ = big_payload_test::BIG_PAYLOAD_TEST_NUMBER_MESSAGES;
service_id_ = big_payload_test::TEST_SERVICE_SERVICE_ID;
@@ -122,68 +126,13 @@ void big_payload_test_service::on_message(const std::shared_ptr<vsomeip::message
<< std::setw(4) << std::setfill('0') << std::hex
<< _request->get_session() << "] size: " << std::dec
<< _request->get_payload()->get_length();
-
- static vsomeip::session_t last_session(0);
- ASSERT_GT(_request->get_session(), last_session);
- last_session = _request->get_session();
- if (test_mode_ == big_payload_test::test_mode::RANDOM) {
- ASSERT_LT(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE_RANDOM);
- } else {
- ASSERT_EQ(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE);
- }
- bool check(true);
- vsomeip::length_t len = _request->get_payload()->get_length();
- vsomeip::byte_t* datap = _request->get_payload()->get_data();
- for(unsigned int i = 0; i < len; ++i) {
- check = check && datap[i] == big_payload_test::DATA_CLIENT_TO_SERVICE;
- }
- if(!check) {
- GTEST_FATAL_FAILURE_("wrong data transmitted");
- }
-
- number_of_received_messages_++;
-
- // send response
- std::shared_ptr<vsomeip::message> its_response =
- vsomeip::runtime::get()->create_response(_request);
-
- std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get()
- ->create_payload();
- std::vector<vsomeip::byte_t> its_payload_data;
- if (test_mode_ == big_payload_test::test_mode::RANDOM) {
- its_payload_data.assign(std::rand() % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM,
- big_payload_test::DATA_SERVICE_TO_CLIENT);
- } else if (test_mode_ == big_payload_test::test_mode::LIMITED
- || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
- || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
- || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
- if (number_of_received_messages_ % 2) {
- // try to send to big response for half of the received messsages.
- // this way the client will only get replies for a fourth of his sent
- // requests as he tries to sent to big data for every second request
- // as well
- its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE + 1,
- big_payload_test::DATA_SERVICE_TO_CLIENT);
- } else {
- its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
- big_payload_test::DATA_SERVICE_TO_CLIENT);
- }
- } else {
- its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
- big_payload_test::DATA_SERVICE_TO_CLIENT);
- }
-
- its_payload->set_data(its_payload_data);
- its_response->set_payload(its_payload);
-
- app_->send(its_response, true);
-
- if(number_of_received_messages_ == expected_messages_) {
- ASSERT_EQ(expected_messages_, number_of_received_messages_);
+ {
std::lock_guard<std::mutex> its_lock(mutex_);
- blocked_ = true;
+ incoming_requests_.push(_request);
condition_.notify_one();
}
+
+
}
void big_payload_test_service::run()
@@ -198,16 +147,87 @@ void big_payload_test_service::run()
// wait for shutdown
blocked_ = false;
- while (!blocked_) {
- condition_.wait(its_lock);
+ while (!blocked_ || !incoming_requests_.empty()) {
+ if (incoming_requests_.empty()) {
+ condition_.wait(its_lock);
+ }
+ auto _request = incoming_requests_.front();
+ incoming_requests_.pop();
+ number_of_received_messages_++;
+ its_lock.unlock();
+
+ static vsomeip::session_t last_session(0);
+ ASSERT_GT(_request->get_session(), last_session);
+ last_session = _request->get_session();
+ if (test_mode_ == big_payload_test::test_mode::RANDOM) {
+ EXPECT_LT(_request->get_payload()->get_length(), big_payload_test::BIG_PAYLOAD_SIZE_RANDOM);
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ EXPECT_EQ(big_payload_test::BIG_PAYLOAD_SIZE_UDP, _request->get_payload()->get_length());
+ } else {
+ EXPECT_EQ(big_payload_test::BIG_PAYLOAD_SIZE, _request->get_payload()->get_length());
+ }
+ bool check(true);
+ vsomeip::length_t len = _request->get_payload()->get_length();
+ vsomeip::byte_t* datap = _request->get_payload()->get_data();
+ for(unsigned int i = 0; i < len; ++i) {
+ check = check && datap[i] == big_payload_test::DATA_CLIENT_TO_SERVICE;
+ }
+ if(!check) {
+ GTEST_FATAL_FAILURE_("wrong data transmitted");
+ }
+
+ // send response
+ std::shared_ptr<vsomeip::message> its_response =
+ vsomeip::runtime::get()->create_response(_request);
+
+ std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get()
+ ->create_payload();
+ std::vector<vsomeip::byte_t> its_payload_data;
+ if (test_mode_ == big_payload_test::test_mode::RANDOM) {
+ its_payload_data.assign(static_cast<unsigned int>(std::rand()) % big_payload_test::BIG_PAYLOAD_SIZE_RANDOM,
+ big_payload_test::DATA_SERVICE_TO_CLIENT);
+ } else if (test_mode_ == big_payload_test::test_mode::LIMITED
+ || test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
+ || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
+ || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
+ if (number_of_received_messages_ % 2) {
+ // try to send to big response for half of the received messsages.
+ // this way the client will only get replies for a fourth of his sent
+ // requests as he tries to sent to big data for every second request
+ // as well
+ its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE + 1,
+ big_payload_test::DATA_SERVICE_TO_CLIENT);
+ } else {
+ its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
+ big_payload_test::DATA_SERVICE_TO_CLIENT);
+ }
+ } else if (test_mode_ == big_payload_test::test_mode::UDP) {
+ its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE_UDP,
+ big_payload_test::DATA_SERVICE_TO_CLIENT);
+ } else {
+ its_payload_data.assign(big_payload_test::BIG_PAYLOAD_SIZE,
+ big_payload_test::DATA_SERVICE_TO_CLIENT);
+ }
+
+ its_payload->set_data(its_payload_data);
+ its_response->set_payload(its_payload);
+
+ app_->send(its_response);
+
+ if(number_of_received_messages_ == expected_messages_) {
+ ASSERT_EQ(expected_messages_, number_of_received_messages_);
+ blocked_ = true;
+ }
+ its_lock.lock();
}
}
std::this_thread::sleep_for(std::chrono::seconds(3));
if (test_mode_ == big_payload_test::test_mode::LIMITED
|| test_mode_ == big_payload_test::test_mode::LIMITED_GENERAL
|| test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_GENERAL
- || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC) {
- ASSERT_EQ(number_of_received_messages_, expected_messages_);
+ || test_mode_ == big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC
+ || test_mode_ == big_payload_test::test_mode::UDP) {
+ EXPECT_EQ(expected_messages_, number_of_received_messages_);
}
stop();
}
@@ -239,6 +259,8 @@ int main(int argc, char** argv)
test_mode = big_payload_test::test_mode::QUEUE_LIMITED_GENERAL;
} else if (std::string("QUEUELIMITEDSPECIFIC") == std::string(argv[1])) {
test_mode = big_payload_test::test_mode::QUEUE_LIMITED_SPECIFIC;
+ } else if (std::string("UDP") == std::string(argv[1])) {
+ test_mode = big_payload_test::test_mode::UDP;
}
}
return RUN_ALL_TESTS();
diff --git a/test/big_payload_tests/big_payload_test_service.hpp b/test/big_payload_tests/big_payload_test_service.hpp
index 8db42f7..fcb5e9e 100644
--- a/test/big_payload_tests/big_payload_test_service.hpp
+++ b/test/big_payload_tests/big_payload_test_service.hpp
@@ -13,9 +13,10 @@
#include <mutex>
#include <condition_variable>
#include <functional>
+#include <queue>
#include "big_payload_test_globals.hpp"
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
class big_payload_test_service
@@ -43,6 +44,7 @@ private:
std::thread offer_thread_;
std::uint32_t expected_messages_;
vsomeip::service_t service_id_;
+ std::queue<std::shared_ptr<vsomeip::message>> incoming_requests_;
};
#endif /* BIGPAYLOADTESTSERVICE_HPP_ */
diff --git a/test/big_payload_tests/big_payload_test_service_external_start.sh b/test/big_payload_tests/big_payload_test_service_external_start.sh
index de3224c..ac8dd60 100755
--- a/test/big_payload_tests/big_payload_test_service_external_start.sh
+++ b/test/big_payload_tests/big_payload_test_service_external_start.sh
@@ -4,9 +4,9 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" && $1 != "QUEUELIMITEDGENERAL" && $1 != "QUEUELIMITEDSPECIFIC" ]]
+if [[ $# -gt 0 && $1 != "RANDOM" && $1 != "LIMITED" && $1 != "LIMITEDGENERAL" && $1 != "QUEUELIMITEDGENERAL" && $1 != "QUEUELIMITEDSPECIFIC" && $1 != "UDP" ]]
then
- echo "The only allowed parameter to this script is RANDOM, LIMITED, LIMITEDGENERAL, QUEUELIMITEDGENERAL or QUEUELIMITEDSPECIFIC"
+ echo "The only allowed parameter to this script is RANDOM, LIMITED, LIMITEDGENERAL, QUEUELIMITEDGENERAL, QUEUELIMITEDSPECIFIC or UDP"
echo "Like $0 RANDOM"
exit 1
fi
@@ -20,6 +20,8 @@ elif [[ $# -gt 0 && $1 == "QUEUELIMITEDGENERAL" ]]; then
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service_queue_limited_general.json
elif [[ $# -gt 0 && $1 == "QUEUELIMITEDSPECIFIC" ]]; then
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service_queue_limited_specific.json
+elif [[ $# -gt 0 && $1 == "UDP" ]]; then
+ export VSOMEIP_CONFIGURATION=big_payload_test_udp_service.json
else
export VSOMEIP_CONFIGURATION=big_payload_test_tcp_service.json
fi
diff --git a/test/big_payload_tests/big_payload_test_udp_client.json b/test/big_payload_tests/big_payload_test_udp_client.json
new file mode 100644
index 0000000..d499638
--- /dev/null
+++ b/test/big_payload_tests/big_payload_test_udp_client.json
@@ -0,0 +1,44 @@
+{
+ "unicast":"10.0.3.1",
+ "netmask":"255.255.255.0",
+ "logging":
+ {
+ "level":"info",
+ "console":"true",
+ "file":
+ {
+ "enable":"true",
+ "path":"/var/log/vsomeip.log"
+ },
+ "dlt":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"big_payload_test_client",
+ "id":"0x1343",
+ "max_dispatchers" : "0"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1240",
+ "instance":"0x01",
+ "unicast":"10.0.3.2",
+ "unreliable": "30509",
+ "someip-tp" : {
+ "client-to-service" : [ "0x8421" ]
+ }
+ }
+ ],
+ "max-payload-size-reliable":"614400",
+ "routing":"big_payload_test_client",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.244.224.245",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/big_payload_tests/big_payload_test_udp_service.json b/test/big_payload_tests/big_payload_test_udp_service.json
new file mode 100644
index 0000000..886ed4b
--- /dev/null
+++ b/test/big_payload_tests/big_payload_test_udp_service.json
@@ -0,0 +1,41 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"debug",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"big_payload_test_service",
+ "id":"0x1277",
+ "max_dispatchers" : "0"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1240",
+ "instance":"0x01",
+ "unreliable": "30509",
+ "someip-tp" : {
+ "service-to-client" : [ "0x8421" ]
+ }
+ }
+ ],
+ "routing":"big_payload_test_service",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.244.224.245",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/big_payload_tests/conf/big_payload_test_udp_client.json.in b/test/big_payload_tests/conf/big_payload_test_udp_client.json.in
new file mode 100644
index 0000000..5a7ee36
--- /dev/null
+++ b/test/big_payload_tests/conf/big_payload_test_udp_client.json.in
@@ -0,0 +1,44 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "netmask":"255.255.255.0",
+ "logging":
+ {
+ "level":"info",
+ "console":"true",
+ "file":
+ {
+ "enable":"true",
+ "path":"/var/log/vsomeip.log"
+ },
+ "dlt":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"big_payload_test_client",
+ "id":"0x1343",
+ "max_dispatchers" : "0"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1240",
+ "instance":"0x01",
+ "unicast":"@TEST_IP_SLAVE@",
+ "unreliable": "30509",
+ "someip-tp" : {
+ "client-to-service" : [ "0x8421" ]
+ }
+ }
+ ],
+ "max-payload-size-reliable":"614400",
+ "routing":"big_payload_test_client",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.244.224.245",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/big_payload_tests/conf/big_payload_test_udp_service.json.in b/test/big_payload_tests/conf/big_payload_test_udp_service.json.in
new file mode 100644
index 0000000..7f71a05
--- /dev/null
+++ b/test/big_payload_tests/conf/big_payload_test_udp_service.json.in
@@ -0,0 +1,41 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "logging":
+ {
+ "level":"debug",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"big_payload_test_service",
+ "id":"0x1277",
+ "max_dispatchers" : "0"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1240",
+ "instance":"0x01",
+ "unreliable": "30509",
+ "someip-tp" : {
+ "service-to-client" : [ "0x8421" ]
+ }
+ }
+ ],
+ "routing":"big_payload_test_service",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.244.224.245",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/client_id_tests/client_id_test_master_starter.sh b/test/client_id_tests/client_id_test_master_starter.sh
index c0b2a0b..eea65af 100755
--- a/test/client_id_tests/client_id_test_master_starter.sh
+++ b/test/client_id_tests/client_id_test_master_starter.sh
@@ -42,9 +42,9 @@ sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting client id test on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./client_id_test_slave_starter.sh $CLIENT_JSON_FILE" &
else
cat <<End-of-message
*******************************************************************************
@@ -71,11 +71,6 @@ do
fi
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop citms
- docker rm citms
-fi
-
# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/client_id_tests/client_id_test_service.cpp b/test/client_id_tests/client_id_test_service.cpp
index 9306bad..b9bb0a1 100644
--- a/test/client_id_tests/client_id_test_service.cpp
+++ b/test/client_id_tests/client_id_test_service.cpp
@@ -15,7 +15,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "client_id_test_globals.hpp"
@@ -248,7 +248,7 @@ static int service_number;
TEST(someip_client_id_test, send_ten_messages_to_service)
{
client_id_test_service its_sample(
- client_id_test::service_infos[service_number]);
+ client_id_test::service_infos[static_cast<size_t>(service_number)]);
}
#ifndef _WIN32
diff --git a/test/client_id_tests/client_id_test_utility.cpp b/test/client_id_tests/client_id_test_utility.cpp
index e7f9770..189bb65 100644
--- a/test/client_id_tests/client_id_test_utility.cpp
+++ b/test/client_id_tests/client_id_test_utility.cpp
@@ -5,18 +5,19 @@
#include <gtest/gtest.h>
-#include <unistd.h> // for access()
-#include <sstream>
-
-#include <vsomeip/constants.hpp>
+#include <thread>
+#include <future>
+#include <cstring>
+#include <vsomeip/vsomeip.hpp>
#include "../../implementation/utility/include/utility.hpp"
#include "../../implementation/configuration/include/configuration.hpp"
-#include "../../implementation/plugin/include/plugin_manager.hpp"
+#include "../../implementation/configuration/include/configuration_plugin.hpp"
+#include "../../implementation/plugin/include/plugin_manager_impl.hpp"
using namespace vsomeip;
-static const std::string APPLICATION_NAME_ROUTING_MANAGER = "vsomeipd";
+static const std::string APPLICATION_NAME_ROUTING_MANAGER = "routingmanagerd";
static const std::string APPLICATION_NAME_NOT_PREDEFINED = "test-application-name";
@@ -46,50 +47,53 @@ public:
auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
if (its_plugin) {
- configuration_ = std::dynamic_pointer_cast<vsomeip::configuration>(its_plugin);
+ auto its_config_plugin = std::dynamic_pointer_cast<vsomeip::configuration_plugin>(its_plugin);
+ if (its_config_plugin) {
+ configuration_ = its_config_plugin->get_configuration(APPLICATION_NAME_ROUTING_MANAGER);
+ }
}
}
protected:
virtual void SetUp() {
- unlink(std::string("/dev/shm").append(utility::get_shm_name(configuration_)).c_str());
- ASSERT_FALSE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
ASSERT_TRUE(static_cast<bool>(configuration_));
configuration_->load(APPLICATION_NAME_ROUTING_MANAGER);
diagnosis_mask_ = configuration_->get_diagnosis_mask();
diagnosis_ = configuration_->get_diagnosis_address();
// calculate all client IDs based on mask
- client_id_base_ = static_cast<client_t>((diagnosis_ << 8) & diagnosis_mask_);
- CLIENT_ID_ROUTING_MANAGER = client_id_base_ | 0x1;
+ client_id_base_ = static_cast<client_t>(diagnosis_ << 8);
+ CLIENT_ID_ROUTING_MANAGER =
+ static_cast<client_t>((configuration_->get_diagnosis_address()
+ << 8) & configuration_->get_diagnosis_mask());
APPLICATION_IN_CLIENT_ID = static_cast<client_t>(client_id_base_ | 0x11);
APPLICATION_IN_CLIENT_ID_TWO = static_cast<client_t>(client_id_base_ | 0x12);
- utility::auto_configuration_init(configuration_);
- EXPECT_TRUE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
+ app_ = vsomeip::runtime::get()->create_application(APPLICATION_NAME_ROUTING_MANAGER);
+ EXPECT_TRUE(app_->init());
+ EXPECT_EQ(CLIENT_ID_ROUTING_MANAGER, app_->get_client());
+
+ rm_impl_thread_ = std::thread([&](){
+ app_->start();
+ });
+ // ensure clean preconditions
+ utility::reset_client_ids();
+ // required as there are two static versions of the utility class in this
+ // test, one in the test itself and one in libvsomeip...
client_id_routing_manager_ = utility::request_client_id(
- configuration_, APPLICATION_NAME_ROUTING_MANAGER, 0x0);
- EXPECT_EQ(client_id_base_ | 0x1, client_id_routing_manager_);
- EXPECT_TRUE(utility::is_routing_manager_host(client_id_routing_manager_));
+ configuration_, APPLICATION_NAME_ROUTING_MANAGER, static_cast<client_t>(
+ (configuration_->get_diagnosis_address() << 8)
+ & configuration_->get_diagnosis_mask()));
+ EXPECT_EQ(CLIENT_ID_ROUTING_MANAGER, client_id_routing_manager_);
}
virtual void TearDown() {
- utility::auto_configuration_exit(client_id_routing_manager_, configuration_);
- EXPECT_FALSE(file_exist(std::string("/dev/shm").append(utility::get_shm_name(configuration_))));
- }
-
- bool file_exist(const std::string &_path) {
- const int ret = ::access(_path.c_str(), F_OK);
- if (ret == -1 && errno == ENOENT) {
- return false;
- } else if (ret == -1) {
- std::stringstream its_stream;
- its_stream << "file_exists (" << _path << "): ";
- std::perror(its_stream.str().c_str());
- return false;
- } else {
- return true;
+ app_->stop();
+ if (rm_impl_thread_.joinable()) {
+ rm_impl_thread_.join();
}
+ app_.reset();
+ utility::release_client_id(client_id_routing_manager_);
}
protected:
@@ -98,388 +102,304 @@ protected:
std::uint16_t diagnosis_;
std::uint16_t diagnosis_mask_;
client_t client_id_base_;
+ std::shared_ptr<vsomeip::application> app_;
+ std::thread rm_impl_thread_;
};
-TEST_F(client_id_utility_test, request_release_client_id) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id);
+class app_wrapper {
+public:
+ app_wrapper(const std::string& _name) :
+ app_(vsomeip::runtime::get()->create_application(_name)),
+ client_(VSOMEIP_CLIENT_UNSET) {
+ EXPECT_TRUE(app_->init());
+ app_->register_state_handler(
+ std::bind(&app_wrapper::on_state, this, std::placeholders::_1));
+ app_thread_ = std::thread([&](){ app_->start(); });
+ }
+
+ ~app_wrapper() {
+ app_->stop();
+ if (app_thread_.joinable()) {
+ app_thread_.join();
+ }
+ app_.reset();
+ }
+
+ void on_state(const vsomeip::state_type_e& _state) {
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ client_ = app_->get_client();
+ registered_.set_value();
+ }
+ };
+
+ client_t get_client() {
+ if (std::future_status::timeout
+ == registered_.get_future().wait_for(
+ std::chrono::seconds(11))) {
+ ADD_FAILURE()<< __LINE__ << " application wasn't registered within time";
+ }
+ return client_;
+ }
+
+ std::shared_ptr<vsomeip::application> get_app() {
+ return app_;
+ }
- utility::release_client_id(its_client_id);
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ std::promise<void> registered_;
+ std::thread app_thread_;
+ vsomeip::client_t client_;
+};
+
+TEST_F(client_id_utility_test, request_release_client_id) {
+ app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
}
TEST_F(client_id_utility_test, request_client_id_twice) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id);
-
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x3, its_client_id_2);
+ app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
+ app_wrapper app2(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x2, app2.get_client());
}
-TEST_F(client_id_utility_test, release_unknown_client_id) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id);
+TEST_F(client_id_utility_test, ensure_sequential_ascending_client_id_allocation) {
+ app_wrapper app(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x1, app.get_client());
- utility::release_client_id(0x4711);
- utility::release_client_id(its_client_id);
+ auto app2 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
+ client_t app2_client = app2->get_client();
+ EXPECT_EQ(client_id_base_ | 0x2, app2_client);
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x3, its_client_id_2);
- utility::release_client_id(its_client_id_2);
-}
+ app2.reset();
-TEST_F(client_id_utility_test, release_client_id_twice)
-{
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id);
+ auto app3 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
+ client_t app3_client = app3->get_client();
+ EXPECT_EQ(client_id_base_ | 0x3, app3_client);
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id);
+ EXPECT_GT(app3_client, app2_client);
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x3, its_client_id_2);
- utility::release_client_id(its_client_id_2);
}
TEST_F(client_id_utility_test, ensure_preconfigured_client_ids_not_used_for_autoconfig)
{
// request client ids until 10 over the preconfigured one
- const std::uint16_t limit = static_cast<std::uint16_t>((APPLICATION_IN_CLIENT_ID & ~diagnosis_mask_) + 10u);
+ const std::uint16_t limit =
+ static_cast<std::uint16_t>((APPLICATION_IN_CLIENT_ID
+ & ~diagnosis_mask_) + std::uint16_t(10));
+
+ std::vector<std::shared_ptr<app_wrapper>> its_apps;
+ its_apps.reserve(limit);
- std::vector<client_t> its_client_ids;
for (int i = 0; i < limit; i++ ) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- its_client_ids.push_back(its_client_id);
- EXPECT_NE(APPLICATION_IN_CLIENT_ID, its_client_id);
- } else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
- << static_cast<std::uint32_t>(i);
- }
+ its_apps.emplace_back(
+ std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i)));
}
-
- // release all
- for (const client_t c : its_client_ids) {
- utility::release_client_id(c);
+ for (const auto& a : its_apps) {
+ EXPECT_NE(APPLICATION_IN_CLIENT_ID, a->get_client());
}
-}
-
-TEST_F(client_id_utility_test,
- ensure_preconfigured_client_ids_in_diagnosis_range_dont_influence_autoconfig_client_ids)
-{
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id);
-
- client_t its_client_id2 = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID);
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id2);
-
- client_t its_client_id3 = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME_TWO, APPLICATION_IN_CLIENT_ID_TWO);
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID_TWO, its_client_id3);
-
-
- client_t its_client_id4 = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x3, its_client_id4);
-
- client_t its_client_id5 = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(client_id_base_ | 0x4, its_client_id5);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id2);
- utility::release_client_id(its_client_id3);
- utility::release_client_id(its_client_id4);
- utility::release_client_id(its_client_id5);
+ its_apps.clear();
}
TEST_F(client_id_utility_test,
request_predefined_client_id_in_diagnosis_range) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID);
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id);
-
- utility::release_client_id(its_client_id);
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
+ EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
}
TEST_F(client_id_utility_test,
request_predefined_client_id_in_diagnosis_range_twice) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID);
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id);
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
+ EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_2);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
+ // preconfigured is already taken -> autogenerated ID should be returned
+ auto app2 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
+ EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
}
TEST_F(client_id_utility_test,
- request_different_client_id_with_predefined_app_name_in_diagnosis_range) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, static_cast<client_t>(APPLICATION_IN_CLIENT_ID + 1u));
- // has to get predefined client id although other was requested
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID, its_client_id);
-
- // predefined in json is now already used and requested should be assigned
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, static_cast<client_t>(APPLICATION_IN_CLIENT_ID + 1u));
- EXPECT_EQ(APPLICATION_IN_CLIENT_ID + 1u, its_client_id_2);
-
- client_t its_client_id_3 = utility::request_client_id(configuration_,
- APPLICATION_IN_NAME, APPLICATION_IN_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_3);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
- utility::release_client_id(its_client_id_3);
+ request_predefined_client_id_outside_diagnosis_range_high) {
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
+ // we should get the client ID defined in the json file
+ EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, app1->get_client());
}
TEST_F(client_id_utility_test,
- request_predefined_client_id_outside_diagnosis_range_low) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID);
- EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id);
+ request_client_id_with_predefined_app_name_outside_diagnosis_range_high_multiple) {
- utility::release_client_id(its_client_id);
-}
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
+ // we should get the client ID defined in the json file
+ EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, app1->get_client());
-TEST_F(client_id_utility_test,
- request_predefined_client_id_outside_diagnosis_range_low_twice) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID);
- EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id);
+ // preconfigured is already taken -> autogenerated ID should be returned
+ auto app2 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
+ EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_2);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
+ auto app3 = std::make_shared<app_wrapper>(APPLICATION_OUT_HIGH_NAME);
+ EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
}
TEST_F(client_id_utility_test,
- request_different_client_id_with_predefined_app_name_outside_diagnosis_range_low) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID + 1u);
- // has to get predefined client id although other was requested
- EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, its_client_id);
-
- // predefined in json is now already used and requested should be assigned
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID + 1u);
- EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID + 1u, its_client_id_2);
-
- client_t its_client_id_3 = utility::request_client_id(configuration_,
- APPLICATION_OUT_LOW_NAME, APPLICATION_OUT_LOW_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_3);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
- utility::release_client_id(its_client_id_3);
+ request_predefined_client_id_outside_diagnosis_range_low) {
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
+ // we should get the client ID defined in the json file
+ EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, app1->get_client());
}
TEST_F(client_id_utility_test,
- request_predefined_client_id_outside_diagnosis_range_high) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID);
- EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id);
+ request_predefined_client_id_outside_diagnosis_range_low_multiple) {
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
+ // we should get the client ID defined in the json file
+ EXPECT_EQ(APPLICATION_OUT_LOW_CLIENT_ID, app1->get_client());
- utility::release_client_id(its_client_id);
+ // preconfigured is already taken -> autogenerated ID should be returned
+ auto app2 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
+ EXPECT_EQ(client_id_base_ | 0x1, app2->get_client());
+
+ auto app3 = std::make_shared<app_wrapper>(APPLICATION_OUT_LOW_NAME);
+ EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
}
TEST_F(client_id_utility_test,
- request_predefined_client_id_outside_diagnosis_range_high_twice) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID);
- EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id);
+ ensure_preconfigured_client_ids_in_diagnosis_range_dont_influence_autoconfig_client_ids)
+{
+ auto app0 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x1, app0->get_client());
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_2);
+ auto app1 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME);
+ EXPECT_EQ(APPLICATION_IN_CLIENT_ID, app1->get_client());
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
-}
+ auto app2 = std::make_shared<app_wrapper>(APPLICATION_IN_NAME_TWO);
+ EXPECT_EQ(APPLICATION_IN_CLIENT_ID_TWO, app2->get_client());
-TEST_F(client_id_utility_test,
- request_different_client_id_with_predefined_app_name_outside_diagnosis_range_high) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID + 1u);
- // has to get predefined client id although other was requested
- EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID, its_client_id);
-
- // predefined in json is now already used and requested should be assigned
- client_t its_client_id_2 = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID + 1u);
- EXPECT_EQ(APPLICATION_OUT_HIGH_CLIENT_ID + 1u, its_client_id_2);
-
- client_t its_client_id_3 = utility::request_client_id(configuration_,
- APPLICATION_OUT_HIGH_NAME, APPLICATION_OUT_HIGH_CLIENT_ID);
- EXPECT_EQ(client_id_base_ | 0x2, its_client_id_3);
-
- utility::release_client_id(its_client_id);
- utility::release_client_id(its_client_id_2);
- utility::release_client_id(its_client_id_3);
-}
+ auto app3 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x2, app3->get_client());
+ auto app4 = std::make_shared<app_wrapper>(APPLICATION_NAME_NOT_PREDEFINED);
+ EXPECT_EQ(client_id_base_ | 0x3, app4->get_client());
+}
TEST_F(client_id_utility_test, exhaust_client_id_range_sequential) {
- std::vector<client_t> its_client_ids;
+ std::vector<vsomeip::client_t> its_clients;
std::uint16_t its_max_clients(0);
for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
}
- const std::uint16_t max_possible_clients = its_max_clients;
- // -1 for the routing manager, -2 as two predefined client IDs are present
- // in the json file which aren't assigned via autoconfiguration
- const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 3u);
+ // -2 as two predefined client IDs are present in the json file which
+ // aren't assigned via autoconfiguration
+ const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(its_max_clients - 2u);
// acquire maximum amount of client IDs
- for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- if (i > 0) {
- EXPECT_LT(its_client_ids.back(), its_client_id);
+ for (int var = 0; var < 2; ++var) {
+ for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
+ const vsomeip::client_t its_client =
+ vsomeip::utility::request_client_id(configuration_,
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ if (its_client != VSOMEIP_CLIENT_UNSET) {
+ if (i > 0) {
+ EXPECT_LT(its_clients.back(), its_client);
+ }
+ its_clients.push_back(its_client);
+ } else {
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
+ << static_cast<std::uint32_t>(i);
}
- its_client_ids.push_back(its_client_id);
- } else {
- ADD_FAILURE()<< "Received ILLEGAL_CLIENT "
- << static_cast<std::uint32_t>(i);
}
- }
-
- // check limit is reached
- client_t its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
-
- // release all
- for (const client_t c : its_client_ids) {
- utility::release_client_id(c);
- }
- its_client_ids.clear();
- its_illegal_client_id = 0xFFFF;
-
- // One more time!
-
- // acquire maximum amount of client IDs
- for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- its_client_ids.push_back(its_client_id);
- } else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
- << static_cast<std::uint32_t>(i);
- }
- }
-
- // check limit is reached
- its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
-
- // release all
- for (const client_t c : its_client_ids) {
- utility::release_client_id(c);
+ // check limit is reached
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
+ configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max",
+ VSOMEIP_CLIENT_UNSET));
+ for (const auto c : its_clients) {
+ utility::release_client_id(c);
+ }
}
}
TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented) {
- std::vector<client_t> its_client_ids;
+ std::vector<client_t> its_clients;
- // -1 for the routing manager, -2 as two predefined client IDs are present
- // in the json file which aren't assigned via autoconfiguration
+ // -2 as two predefined client IDs are present in the json file which
+ // aren't assigned via autoconfiguration
std::uint16_t its_max_clients(0);
for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
}
- const std::uint16_t max_possible_clients = its_max_clients;
- const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 3u);
-
- // acquire maximum amount of client IDs
- for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- if (i > 0) {
- EXPECT_LT(its_client_ids.back(), its_client_id);
+ const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(its_max_clients - 2u);
+
+ for (int var = 0; var < 2; ++var) {
+ // acquire maximum amount of client IDs
+ for (std::uint16_t i = 0; i < max_allowed_clients; i++) {
+ const vsomeip::client_t its_client =
+ vsomeip::utility::request_client_id(configuration_,
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ if (its_client != VSOMEIP_CLIENT_UNSET) {
+ if ((var == 0 && i > 0) ||
+ (var == 1 && i > 1) // special case as in the 1st run the last assigned client ID was 63fe
+ // due to the releases. In the 2nd run the first client ID therefore will be 63ff
+ ) {
+ EXPECT_LT(its_clients.back(), its_client);
+ }
+ its_clients.push_back(its_client);
+ } else {
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
+ << static_cast<std::uint32_t>(i);
}
- its_client_ids.push_back(its_client_id);
- } else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
- << static_cast<std::uint32_t>(i);
}
- }
- // check limit is reached
- client_t its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
-
- // release every second requested client ID
- std::vector<client_t> its_released_client_ids;
- for (size_t i = 0; i < its_client_ids.size(); i++ ) {
- if (i % 2) {
- its_released_client_ids.push_back(its_client_ids[i]);
- utility::release_client_id(its_client_ids[i]);
+ // check limit is reached
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
+ configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max",
+ VSOMEIP_CLIENT_UNSET));
+
+ // release every second requested client ID
+ std::vector<client_t> its_released_client_ids;
+ for (size_t i = 0; i < its_clients.size(); i++ ) {
+ if (i % 2) {
+ its_released_client_ids.push_back(its_clients[i]);
+ utility::release_client_id(its_clients[i]);
+ }
}
- }
- for (const client_t c : its_released_client_ids) {
- for (auto it = its_client_ids.begin(); it != its_client_ids.end(); ) {
- if (*it == c) {
- it = its_client_ids.erase(it);
- } else {
- ++it;
+ for (const client_t c : its_released_client_ids) {
+ for (auto it = its_clients.begin(); it != its_clients.end(); ) {
+ if (*it == c) {
+ it = its_clients.erase(it);
+ } else {
+ ++it;
+ }
}
}
- }
- // acquire client IDs up to the maximum allowed amount again
- for (std::uint16_t i = 0; i < its_released_client_ids.size(); i++) {
- client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- if (i > 0) {
- EXPECT_LT(its_client_ids.back(), its_client_id);
+ // acquire client IDs up to the maximum allowed amount again
+ for (std::uint16_t i = 0; i < its_released_client_ids.size(); i++) {
+ const vsomeip::client_t its_client =
+ vsomeip::utility::request_client_id(configuration_,
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ if (its_client != VSOMEIP_CLIENT_UNSET) {
+ if (i > 0) {
+ EXPECT_LT(its_clients.back(), its_client);
+ }
+ its_clients.push_back(its_client);
+ } else {
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
+ << static_cast<std::uint32_t>(i);
}
- its_client_ids.push_back(its_client_id);
- } else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
- << static_cast<std::uint32_t>(i);
}
- }
- // check limit is reached
- its_illegal_client_id = 0xFFFF;
- its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
+ // check limit is reached
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, vsomeip::utility::request_client_id(
+ configuration_, APPLICATION_NAME_NOT_PREDEFINED + "max2",
+ VSOMEIP_CLIENT_UNSET));
- // release all
- for (const client_t c : its_client_ids) {
- utility::release_client_id(c);
+ // release all
+ for (const auto c : its_clients) {
+ utility::release_client_id(c);
+ }
+ its_clients.clear();
}
}
@@ -496,23 +416,29 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
for (int var = 0; var < __builtin_popcount(static_cast<std::uint16_t>(~diagnosis_mask_)); ++var) {
its_max_clients = static_cast<std::uint16_t>(its_max_clients | (1 << var));
}
+ const std::uint16_t its_diagnosis_mask = configuration_->get_diagnosis_mask();
+ const std::uint16_t its_client_mask = static_cast<std::uint16_t>(~its_diagnosis_mask);
+ const client_t its_masked_diagnosis_address = static_cast<client_t>(
+ (configuration_->get_diagnosis_address() << 8) & its_diagnosis_mask);
+ const client_t its_biggest_client = its_masked_diagnosis_address | its_client_mask;
+
const std::uint16_t max_possible_clients = its_max_clients;
const std::uint16_t intermediate_release = 3;
- const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 3u);
-
+ const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 2u);
// acquire (almost) maximum amount of client IDs
for (std::uint16_t i = 0; i < max_allowed_clients - intermediate_release; i++) {
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
+ if (its_client_id != VSOMEIP_CLIENT_UNSET) {
if (i > 0) {
EXPECT_LT(its_client_ids.back(), its_client_id);
}
its_client_ids.push_back(its_client_id);
} else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
<< static_cast<std::uint32_t>(i);
}
}
@@ -528,13 +454,15 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
// acquire some more client IDs, these should be bigger than the already acquired
for (std::uint16_t i = 0; i < intermediate_release; i++) {
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i)
+ + "intermediate",
+ VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
+ if (its_client_id != VSOMEIP_CLIENT_UNSET) {
EXPECT_LT(its_client_ids.back(), its_client_id);
its_client_ids.push_back(its_client_id);
} else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
<< static_cast<std::uint32_t>(i);
}
}
@@ -542,9 +470,10 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
// check correct wrap around of client IDs
for (std::uint16_t i = 0; i < intermediate_release; i++) {
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
+ if (its_client_id != VSOMEIP_CLIENT_UNSET) {
if (i == 0) {
EXPECT_GT(its_client_ids.back(), its_client_id);
} else {
@@ -552,15 +481,15 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
}
its_client_ids.push_back(its_client_id);
} else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
<< static_cast<std::uint32_t>(i);
}
}
// check limit is reached
client_t its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
// release every second requested client ID
std::vector<client_t> its_released_client_ids;
@@ -583,15 +512,16 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
// acquire client IDs up to the maximum allowed amount again
for (std::uint16_t i = 0; i < its_released_client_ids.size(); i++) {
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
- if (i > 0) {
+ APPLICATION_NAME_NOT_PREDEFINED + std::to_string(i),
+ VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
+ if (its_client_id != VSOMEIP_CLIENT_UNSET) {
+ if (i > 0 && its_client_ids.back() != its_biggest_client) {
EXPECT_LT(its_client_ids.back(), its_client_id);
}
its_client_ids.push_back(its_client_id);
} else {
- ADD_FAILURE() << "Received ILLEGAL_CLIENT "
+ ADD_FAILURE() << "Received VSOMEIP_CLIENT_UNSET "
<< static_cast<std::uint32_t>(i);
}
}
@@ -599,8 +529,8 @@ TEST_F(client_id_utility_test, exhaust_client_id_range_fragmented_extended) {
// check limit is reached
its_illegal_client_id = 0xFFFF;
its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
// release all
for (const client_t c : its_client_ids) {
@@ -617,20 +547,20 @@ TEST_F(client_id_utility_test, request_released_client_id_after_maximum_client_i
const std::uint16_t max_possible_clients = its_max_clients;
// -1 for the routing manager, -2 as two predefined client IDs are present
// in the json file which aren't assigned via autoconfiguration
- const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 3u);
+ const std::uint16_t max_allowed_clients = static_cast<std::uint16_t>(max_possible_clients - 2u);
// acquire (almost) maximum amount of client IDs
for (std::uint16_t i = 0; i < max_allowed_clients - 1; i++) {
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
- if (its_client_id != ILLEGAL_CLIENT) {
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
+ if (its_client_id != VSOMEIP_CLIENT_UNSET) {
if (i > 0) {
EXPECT_LT(its_client_ids.back(), its_client_id);
}
its_client_ids.push_back(its_client_id);
} else {
- ADD_FAILURE()<< "Received ILLEGAL_CLIENT "
+ ADD_FAILURE()<< "Received VSOMEIP_CLIENT_UNSET "
<< static_cast<std::uint32_t>(i);
}
}
@@ -640,27 +570,27 @@ TEST_F(client_id_utility_test, request_released_client_id_after_maximum_client_i
// requesting an ID should return the maximum possible ID
client_t its_max_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_max_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_max_client_id);
its_client_ids.push_back(its_max_client_id);
// requesting an ID should work as we have released one before
client_t its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
its_client_ids.push_back(its_client_id);
// requesting an ID should not work as all IDs are in use now
client_t its_illegal_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_EQ(ILLEGAL_CLIENT, its_illegal_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_EQ(VSOMEIP_CLIENT_UNSET, its_illegal_client_id);
// release another ID
utility::release_client_id(its_client_ids[5]);
its_client_id = utility::request_client_id(configuration_,
- APPLICATION_NAME_NOT_PREDEFINED, 0x0);
- EXPECT_NE(ILLEGAL_CLIENT, its_client_id);
+ APPLICATION_NAME_NOT_PREDEFINED, VSOMEIP_CLIENT_UNSET);
+ EXPECT_NE(VSOMEIP_CLIENT_UNSET, its_client_id);
its_client_ids.push_back(its_client_id);
// release all
diff --git a/test/client_id_tests/client_id_test_utility.json b/test/client_id_tests/client_id_test_utility.json
index e928b05..e07eb9a 100644
--- a/test/client_id_tests/client_id_test_utility.json
+++ b/test/client_id_tests/client_id_test_utility.json
@@ -31,5 +31,5 @@
"id":"0x7411"
}
],
- "routing":"vsomeipd"
+ "routing":"routingmanagerd"
}
diff --git a/test/client_id_tests/client_id_test_utility_discontinuous_masked_511.json b/test/client_id_tests/client_id_test_utility_discontinuous_masked_511.json
index 4195bad..af3dfd6 100644
--- a/test/client_id_tests/client_id_test_utility_discontinuous_masked_511.json
+++ b/test/client_id_tests/client_id_test_utility_discontinuous_masked_511.json
@@ -32,5 +32,5 @@
"id":"0x7411"
}
],
- "routing":"vsomeipd"
+ "routing":"routingmanagerd"
}
diff --git a/test/client_id_tests/client_id_test_utility_masked_127.json b/test/client_id_tests/client_id_test_utility_masked_127.json
index c7c255b..8aa5135 100644
--- a/test/client_id_tests/client_id_test_utility_masked_127.json
+++ b/test/client_id_tests/client_id_test_utility_masked_127.json
@@ -32,5 +32,5 @@
"id":"0x7411"
}
],
- "routing":"vsomeipd"
+ "routing":"routingmanagerd"
}
diff --git a/test/client_id_tests/client_id_test_utility_masked_4095.json b/test/client_id_tests/client_id_test_utility_masked_4095.json
index dfc42c0..8604435 100644
--- a/test/client_id_tests/client_id_test_utility_masked_4095.json
+++ b/test/client_id_tests/client_id_test_utility_masked_4095.json
@@ -11,7 +11,7 @@
},
"dlt":"false"
},
- "diagnosis":"0x63",
+ "diagnosis":"0x60",
"diagnosis_mask":"0xF000",
"applications":
[
@@ -32,5 +32,5 @@
"id":"0x7411"
}
],
- "routing":"vsomeipd"
+ "routing":"routingmanagerd"
}
diff --git a/test/client_id_tests/client_id_test_utility_masked_511.json b/test/client_id_tests/client_id_test_utility_masked_511.json
index 274a5e0..a57d382 100644
--- a/test/client_id_tests/client_id_test_utility_masked_511.json
+++ b/test/client_id_tests/client_id_test_utility_masked_511.json
@@ -11,7 +11,7 @@
},
"dlt":"false"
},
- "diagnosis":"0x63",
+ "diagnosis":"0x62",
"diagnosis_mask":"0xFE00",
"applications":
[
@@ -32,5 +32,5 @@
"id":"0x7411"
}
],
- "routing":"vsomeipd"
+ "routing":"routingmanagerd"
}
diff --git a/test/configuration_tests/configuration-test-deprecated.json b/test/configuration_tests/configuration-test-deprecated.json
index ecbe43b..f9b23d8 100644
--- a/test/configuration_tests/configuration-test-deprecated.json
+++ b/test/configuration_tests/configuration-test-deprecated.json
@@ -306,7 +306,6 @@
"policies" :
[
{
- "client" : "0x1277",
"credentials" : { "uid" : "1000", "gid" : "1000" },
"allow" :
{
@@ -328,7 +327,7 @@
}
},
{
- "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "credentials" : { "uid" : "2000", "gid" : "2000" },
"allow" :
{
"requests":
@@ -364,7 +363,7 @@
}
},
{
- "client" : { "first" : "0x1443", "last" : "0x1446" },
+ "credentials" : { "uid" : "4000", "gid" : "4000" },
"deny" :
{
"requests":
@@ -397,19 +396,19 @@
}
},
{
- "client" : "0x1550",
+ "credentials" : { "uid" : "5000", "gid" : "5000" },
"deny" :
{
}
},
{
- "client" : "0x1660",
+ "credentials" : { "uid" : "6000", "gid" : "6000" },
"allow" :
{
}
},
{
- "client" : "0x1770",
+ "credentials" : { "uid" : "7000", "gid" : "7000" },
"deny" :
{
"requests":
@@ -427,7 +426,7 @@
}
},
{
- "client" : "0x1880",
+ "credentials" : { "uid" : "8000", "gid" : "8000" },
"allow" :
{
"requests":
@@ -443,6 +442,23 @@
}
]
}
+ },
+ {
+ "credentials" : {
+ "allow": [
+ {
+ "uid": [
+ "9000"
+ ],
+ "gid": [
+ "9000"
+ ]
+ }
+ ]
+ },
+ "deny" :
+ {
+ }
}
]
},
diff --git a/test/configuration_tests/configuration-test.cpp b/test/configuration_tests/configuration-test.cpp
index c84af38..558cd4e 100644
--- a/test/configuration_tests/configuration-test.cpp
+++ b/test/configuration_tests/configuration-test.cpp
@@ -10,13 +10,15 @@
#include <vsomeip/constants.hpp>
#include <vsomeip/plugins/application_plugin.hpp>
-
+#include <vsomeip/internal/logger.hpp>
#include "../implementation/configuration/include/configuration.hpp"
-#include "../implementation/configuration/include/configuration_impl.hpp"
-#include "../implementation/logging/include/logger.hpp"
-#include "../implementation/configuration/include/policy.hpp"
-#include "../implementation/plugin/include/plugin_manager.hpp"
+#include "../../implementation/plugin/include/plugin_manager_impl.hpp"
+#include "../../implementation/configuration/include/configuration_impl.hpp"
+#include "../../implementation/configuration/include/configuration_plugin.hpp"
+#include "../../implementation/security/include/security_impl.hpp"
+
+namespace vsomeip = vsomeip_v3;
#define CONFIGURATION_FILE "configuration-test.json"
#define DEPRECATED_CONFIGURATION_FILE "configuration-test-deprecated.json"
@@ -125,23 +127,34 @@ void check_file(const std::string &_config_file,
const std::string &_expected_protocol,
const std::string &_expected_multicast,
uint16_t _expected_port,
- int32_t _expected_initial_delay_min,
- int32_t _expected_initial_delay_max,
+ uint32_t _expected_initial_delay_min,
+ uint32_t _expected_initial_delay_max,
int32_t _expected_repetitions_base_delay,
uint8_t _expected_repetitions_max,
vsomeip::ttl_t _expected_ttl,
vsomeip::ttl_t _expected_cyclic_offer_delay,
vsomeip::ttl_t _expected_request_response_delay) {
- // 0. Create configuration object
+
+ // 0. Set environment variable to config file and load it
+#ifndef _WIN32
+ setenv("VSOMEIP_CONFIGURATION", _config_file.c_str(), 1);
+#else
+ _putenv_s("VSOMEIP_CONFIGURATION", _config_file.c_str()
+#endif
+
+ // 1. Create configuration object
std::shared_ptr<vsomeip::configuration> its_configuration;
- auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
+ auto its_plugin = vsomeip::plugin_manager_impl::get()->get_plugin(
vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
if (its_plugin) {
- its_configuration = std::dynamic_pointer_cast<vsomeip::configuration>(its_plugin);
+ auto its_configuration_plugin
+ = std::dynamic_pointer_cast<vsomeip::configuration_plugin>(its_plugin);
+ if (its_configuration_plugin)
+ its_configuration = its_configuration_plugin->get_configuration(EXPECTED_ROUTING_MANAGER_HOST);
}
- // 1. Did we get a configuration object?
+ // 2. Did we get a configuration object?
if (0 == its_configuration) {
ADD_FAILURE() << "No configuration object. "
"Either memory overflow or loading error detected!";
@@ -154,14 +167,6 @@ void check_file(const std::string &_config_file,
new vsomeip::cfg::configuration_impl(its_copied_config);
delete its_new_config;
- // 2. Set environment variable to config file and load it
-#ifndef _WIN32
- setenv("VSOMEIP_CONFIGURATION", _config_file.c_str(), 1);
-#else
- _putenv_s("VSOMEIP_CONFIGURATION", _config_file.c_str()
-#endif
- its_configuration->load(EXPECTED_ROUTING_MANAGER_HOST);
-
its_configuration->set_configuration_path("/my/test/path");
// 3. Check host address
@@ -309,13 +314,13 @@ void check_file(const std::string &_config_file,
std::map<vsomeip::plugin_type_e, std::set<std::string>> its_plugins =
its_configuration->get_plugins(EXPECTED_ROUTING_MANAGER_HOST);
EXPECT_EQ(1u, its_plugins.size());
- for (const auto plugin : its_plugins) {
+ for (const auto& plugin : its_plugins) {
EXPECT_EQ(vsomeip::plugin_type_e::APPLICATION_PLUGIN, plugin.first);
- for (auto its_library : plugin.second)
+ for (const auto& its_library : plugin.second)
EXPECT_EQ(std::string("libtestlibraryname.so." + std::to_string(VSOMEIP_APPLICATION_PLUGIN_VERSION)), its_library);
}
EXPECT_EQ(vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, its_plugin->get_plugin_type());
- EXPECT_EQ("vsomeip cfg plugin", its_plugin->get_plugin_name());
+ EXPECT_EQ("vsomeip-configuration-plugin", its_plugin->get_plugin_name());
EXPECT_EQ(1u, its_plugin->get_plugin_version());
@@ -511,100 +516,102 @@ void check_file(const std::string &_config_file,
// client is not the routing manager
EXPECT_TRUE(its_configuration->check_routing_credentials(0x7777, 0x888, 0x999));
- EXPECT_TRUE(its_configuration->is_security_enabled());
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1277, 0x1234, 0x5678));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1277, 0x1235, 0x5678));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1277, 0x1236, 0x5678));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1277, 0x1236, 0x5676));
-
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1277, 0x1236, 0x5679));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1277, 0x1234, 0x5679));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1277, 0x1233, 0x5679));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1266, 0x1233, 0x5679));
+ auto its_security = vsomeip::security_impl::get();
+ EXPECT_TRUE(its_security->is_enabled());
+ EXPECT_TRUE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1234, 0x5678));
+ EXPECT_TRUE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1235, 0x5678));
+ EXPECT_TRUE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1236, 0x5678));
+ EXPECT_TRUE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1236, 0x5676));
+
+ EXPECT_FALSE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1236, 0x5679));
+ EXPECT_FALSE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1234, 0x5679));
+ EXPECT_FALSE(its_security->is_offer_allowed(1000, 1000, 0x1277, 0x1233, 0x5679));
+ EXPECT_FALSE(its_security->is_offer_allowed(1001, 1001, 0x1266, 0x1233, 0x5679));
// explicitly denied offers
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1234, 0x5678));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1235, 0x5678));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1234, 0x5679));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1300, 0x1));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1300, 0x2));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1236, 0x5678));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1236, 0x5675));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1236, 0x5676));
- EXPECT_FALSE(its_configuration->is_offer_allowed(0x1443, 0x1236, 0x5677));
- EXPECT_TRUE(its_configuration->is_offer_allowed(0x1443, 0x1236, 0x5679));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1234, 0x5678));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1235, 0x5678));
+ EXPECT_TRUE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1234, 0x5679));
+ EXPECT_TRUE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1300, 0x1));
+ EXPECT_TRUE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1300, 0x2));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1236, 0x5678));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1236, 0x5675));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1236, 0x5676));
+ EXPECT_FALSE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1236, 0x5677));
+ EXPECT_TRUE(its_security->is_offer_allowed(4000, 4000, 0x1443, 0x1236, 0x5679));
// explicitly allowed requests of methods / events
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5678, 0x0001));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5678, 0x8002));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1346, 0x1234, 0x5688, 0x8002));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5699, 0x8006));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5699, 0x8001));
-
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1347, 0x1234, 0x5678, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1342, 0x1234, 0x5678, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5677, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5700, 0x0001));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5699, 0x8007));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1234, 0x5700, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1230, 0x5678, 0x0001));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1230, 0x5678, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5678, 0x0002));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1446, 0x1234, 0x5678, 0xFFFF));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5679, 0x0003));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5679, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5699, 0x9001));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1443, 0x1234, 0x5699, 0x9006));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1442, 0x1234, 0x5678, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1447, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5678, 0x0001));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5678, 0x8002));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1346, 0x1234, 0x5688, 0x8002));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5699, 0x8006));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5699, 0x8001));
+
+ EXPECT_FALSE(its_security->is_client_allowed(2001, 2001, 0x1347, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(2001, 2001, 0x1342, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5677, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5700, 0x0001));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5699, 0x8007));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1234, 0x5700, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1230, 0x5678, 0x0001));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1230, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(4000, 4000, 0x1443, 0x1234, 0x5678, 0x0002));
+ EXPECT_FALSE(its_security->is_client_allowed(4000, 4000, 0x1446, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_TRUE(its_security->is_client_allowed(4000, 4000, 0x1443, 0x1234, 0x5679, 0x0003));
+ EXPECT_FALSE(its_security->is_client_allowed(4000, 4000, 0x1443, 0x1234, 0x5679, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(4000, 4000, 0x1443, 0x1234, 0x5699, 0x9001));
+ EXPECT_FALSE(its_security->is_client_allowed(4000, 4000, 0x1443, 0x1234, 0x5699, 0x9006));
+ EXPECT_FALSE(its_security->is_client_allowed(4001, 4001, 0x1442, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(4001, 4001, 0x1447, 0x1234, 0x5678, 0xFFFF));
// check that any method ID is allowed
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1237, 0x5678, 0x0001));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1237, 0x5678, 0xFFFF));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1237, 0x5678, 0x0001));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1237, 0x5678, 0xFFFF));
// check that any instance ID is allowed but only one method ID
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1343, 0x1238, 0x0004, 0x0001));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1343, 0x1238, 0x0004, 0x0002));
+ EXPECT_TRUE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1238, 0x0004, 0x0001));
+ EXPECT_FALSE(its_security->is_client_allowed(2000, 2000, 0x1343, 0x1238, 0x0004, 0x0002));
// DENY NOTHING policy
// check that ANY_METHOD is allowed in a "deny nothing" policy
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1550, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_TRUE(its_security->is_client_allowed(5000, 5000, 0x1550, 0x1234, 0x5678, 0xFFFF));
// check that specific method ID is allowed in a "deny nothing" policy
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1550, 0x1234, 0x5678, 0x0001));
+ EXPECT_TRUE(its_security->is_client_allowed(5000, 5000, 0x1550, 0x1234, 0x5678, 0x0001));
// ALLOW NOTHING policy
// check that ANY_METHOD is denied in a "allow nothing" policy
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1660, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(6000, 6000, 0x1660, 0x1234, 0x5678, 0xFFFF));
// check that specific method ID is denied in a "allow nothing" policy
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1660, 0x1234, 0x5678, 0x0001));
+ EXPECT_FALSE(its_security->is_client_allowed(6000, 6000, 0x1660, 0x1234, 0x5678, 0x0001));
// DENY only one service instance and ANY_METHOD (0x01 - 0xFFFF) policy
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1770, 0x1234, 0x5678, 0xFFFF));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1770, 0x1234, 0x5678, 0x0001));
+ EXPECT_FALSE(its_security->is_client_allowed(7000, 7000, 0x1770, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_FALSE(its_security->is_client_allowed(7000, 7000, 0x1770, 0x1234, 0x5678, 0x0001));
// allow only one service instance and ANY_METHOD policy
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1880, 0x1234, 0x5678, 0xFFFF));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1880, 0x1234, 0x5678, 0x0001));
+ EXPECT_TRUE(its_security->is_client_allowed(8000, 8000, 0x1880, 0x1234, 0x5678, 0xFFFF));
+ EXPECT_TRUE(its_security->is_client_allowed(8000, 8000, 0x1880, 0x1234, 0x5678, 0x0001));
// check request service
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1550, 0x1234, 0x5678, 0x00, true));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1660, 0x1234, 0x5678, 0x00, true));
- EXPECT_FALSE(its_configuration->is_client_allowed(0x1770, 0x1234, 0x5678, 0x00, true));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1770, 0x2222, 0x5678, 0x00, true));
- EXPECT_TRUE(its_configuration->is_client_allowed(0x1880, 0x1234, 0x5678, 0x00, true));
+ EXPECT_TRUE(its_security->is_client_allowed(5000, 5000, 0x1550, 0x1234, 0x5678, 0x00, true));
+ EXPECT_FALSE(its_security->is_client_allowed(6000, 6000, 0x1660, 0x1234, 0x5678, 0x00, true));
+ EXPECT_FALSE(its_security->is_client_allowed(7000, 7000, 0x1770, 0x1234, 0x5678, 0x00, true));
+ EXPECT_TRUE(its_security->is_client_allowed(7000, 7000, 0x1770, 0x2222, 0x5678, 0x00, true));
+ EXPECT_TRUE(its_security->is_client_allowed(8000, 8000, 0x1880, 0x1234, 0x5678, 0x00, true));
- EXPECT_TRUE(its_configuration->check_credentials(0x1277, 1000, 1000));
- EXPECT_FALSE(its_configuration->check_credentials(0x1277, 1001, 1001));
- EXPECT_FALSE(its_configuration->check_credentials(0x1278, 1000, 1000));
+ EXPECT_TRUE(its_security->check_credentials(0x1277, 1000, 1000));
+ EXPECT_FALSE(its_security->check_credentials(0x1277, 1001, 1001));
+ EXPECT_TRUE(its_security->check_credentials(0x1278, 1000, 1000));
+ EXPECT_TRUE(its_security->check_credentials(0x1278, 9000, 9000));
// Security update / removal whitelist
- EXPECT_TRUE(its_configuration->is_policy_removal_allowed(1000));
- EXPECT_TRUE(its_configuration->is_policy_removal_allowed(1001));
- EXPECT_TRUE(its_configuration->is_policy_removal_allowed(1008));
- EXPECT_TRUE(its_configuration->is_policy_removal_allowed(2000));
- EXPECT_TRUE(its_configuration->is_policy_removal_allowed(3000));
+ EXPECT_TRUE(its_security->is_policy_removal_allowed(1000));
+ EXPECT_TRUE(its_security->is_policy_removal_allowed(1001));
+ EXPECT_TRUE(its_security->is_policy_removal_allowed(1008));
+ EXPECT_TRUE(its_security->is_policy_removal_allowed(2000));
+ EXPECT_TRUE(its_security->is_policy_removal_allowed(3000));
- EXPECT_FALSE(its_configuration->is_policy_removal_allowed(2001));
- EXPECT_FALSE(its_configuration->is_policy_removal_allowed(3001));
+ EXPECT_FALSE(its_security->is_policy_removal_allowed(2001));
+ EXPECT_FALSE(its_security->is_policy_removal_allowed(3001));
// create a valid policy object that is on whitelist and test is_policy_update_allowed method
std::shared_ptr<vsomeip::policy> _policy(std::make_shared<vsomeip::policy>());
@@ -637,22 +644,22 @@ void check_file(const std::string &_config_file,
_policy->services_.insert(
std::make_pair(its_service_id, its_instance_method_ranges));
- EXPECT_TRUE(its_configuration->is_policy_update_allowed(1000, _policy));
+ EXPECT_TRUE(its_security->is_policy_update_allowed(1000, _policy));
// test valid policy that holds a single service id which is whitelisted
its_service_id = 0x7800;
_policy->services_.insert(
std::make_pair(its_service_id, its_instance_method_ranges));
- EXPECT_TRUE(its_configuration->is_policy_update_allowed(1000, _policy));
+ EXPECT_TRUE(its_security->is_policy_update_allowed(1000, _policy));
// test invalid UID which is not whitelisted
- EXPECT_FALSE(its_configuration->is_policy_update_allowed(2002, _policy));
+ EXPECT_FALSE(its_security->is_policy_update_allowed(2002, _policy));
// test invalid policy that additionally holds a service id which is not whitelisted
its_service_id = 0x8888;
_policy->services_.insert(
std::make_pair(its_service_id, its_instance_method_ranges));
- EXPECT_FALSE(its_configuration->is_policy_update_allowed(1000, _policy));
+ EXPECT_FALSE(its_security->is_policy_update_allowed(1000, _policy));
// TCP connection setting:
// max TCP connect time / max allowed number of aborted TCP endpoint restarts until forced restart
@@ -665,8 +672,8 @@ void check_file(const std::string &_config_file,
uint16_t port = its_configuration->get_sd_port();
std::string multicast = its_configuration->get_sd_multicast();
- int32_t initial_delay_min = its_configuration->get_sd_initial_delay_min();
- int32_t initial_delay_max = its_configuration->get_sd_initial_delay_max();
+ uint32_t initial_delay_min = its_configuration->get_sd_initial_delay_min();
+ uint32_t initial_delay_max = its_configuration->get_sd_initial_delay_max();
int32_t repetitions_base_delay = its_configuration->get_sd_repetitions_base_delay();
uint8_t repetitions_max = its_configuration->get_sd_repetitions_max();
vsomeip::ttl_t ttl = its_configuration->get_sd_ttl();
@@ -678,16 +685,16 @@ void check_file(const std::string &_config_file,
EXPECT_TRUE(check<std::string>(multicast, _expected_multicast, "SD MULTICAST"));
EXPECT_TRUE(check<uint16_t>(port, _expected_port, "SD PORT"));
- EXPECT_TRUE(check<int32_t>(initial_delay_min, _expected_initial_delay_min, "SD INITIAL DELAY MIN"));
- EXPECT_TRUE(check<int32_t>(initial_delay_max, _expected_initial_delay_max, "SD INITIAL DELAY MAX"));
+ EXPECT_TRUE(check<uint32_t>(initial_delay_min, _expected_initial_delay_min, "SD INITIAL DELAY MIN"));
+ EXPECT_TRUE(check<uint32_t>(initial_delay_max, _expected_initial_delay_max, "SD INITIAL DELAY MAX"));
EXPECT_TRUE(check<int32_t>(repetitions_base_delay, _expected_repetitions_base_delay, "SD REPETITION BASE DELAY"));
EXPECT_TRUE(check<uint8_t>(repetitions_max,_expected_repetitions_max, "SD REPETITION MAX"));
EXPECT_TRUE(check<vsomeip::ttl_t>(ttl, _expected_ttl, "SD TTL"));
- EXPECT_TRUE(check<int32_t>(cyclic_offer_delay, _expected_cyclic_offer_delay, "SD CYCLIC OFFER DELAY"));
- EXPECT_TRUE(check<int32_t>(request_response_delay, _expected_request_response_delay, "SD RESPONSE REQUEST DELAY"));
+ EXPECT_TRUE(check<int32_t>(cyclic_offer_delay, static_cast<int32_t>(_expected_cyclic_offer_delay), "SD CYCLIC OFFER DELAY"));
+ EXPECT_TRUE(check<int32_t>(request_response_delay, static_cast<int32_t>(_expected_request_response_delay), "SD RESPONSE REQUEST DELAY"));
EXPECT_EQ(1000u, its_configuration->get_sd_offer_debounce_time());
- ASSERT_TRUE(vsomeip::plugin_manager::get()->unload_plugin(vsomeip::plugin_type_e::CONFIGURATION_PLUGIN));
+ ASSERT_TRUE(vsomeip::plugin_manager_impl::get()->unload_plugin(vsomeip::plugin_type_e::CONFIGURATION_PLUGIN));
}
TEST(configuration_test, check_config_file) {
diff --git a/test/configuration_tests/configuration-test.json b/test/configuration_tests/configuration-test.json
index d1ac335..70c34e3 100644
--- a/test/configuration_tests/configuration-test.json
+++ b/test/configuration_tests/configuration-test.json
@@ -24,9 +24,9 @@
"permissions-uds" : "0222"
},
"supports_selective_broadcasts" :
- {
- "address" : "160.160.160.160"
- },
+ [
+ "160.160.160.160"
+ ],
"tracing" :
{
"enable" : "true",
@@ -100,10 +100,12 @@
"plugins" :
[
{
- "application_plugin" : "testlibraryname"
+ "name" : "testlibraryname",
+ "type" : "application_plugin"
},
{
- "intentionally_wrong_plugin" : "wrong"
+ "name" : "wrongtestlibraryname",
+ "type" : "intentionally_wrong_plugin"
}
]
},
@@ -293,7 +295,6 @@
"policies" :
[
{
- "client" : "0x1277",
"credentials" : { "uid" : "1000", "gid" : "1000" },
"allow" :
{
@@ -315,7 +316,7 @@
}
},
{
- "client" : { "first" : "0x1343", "last" : "0x1346" },
+ "credentials" : { "uid" : "2000", "gid" : "2000" },
"allow" :
{
"requests":
@@ -351,7 +352,7 @@
}
},
{
- "client" : { "first" : "0x1443", "last" : "0x1446" },
+ "credentials" : { "uid" : "4000", "gid" : "4000" },
"deny" :
{
"requests":
@@ -384,19 +385,19 @@
}
},
{
- "client" : "0x1550",
+ "credentials" : { "uid" : "5000", "gid" : "5000" },
"deny" :
{
}
},
{
- "client" : "0x1660",
+ "credentials" : { "uid" : "6000", "gid" : "6000" },
"allow" :
{
}
},
{
- "client" : "0x1770",
+ "credentials" : { "uid" : "7000", "gid" : "7000" },
"deny" :
{
"requests":
@@ -414,7 +415,7 @@
}
},
{
- "client" : "0x1880",
+ "credentials" : { "uid" : "8000", "gid" : "8000" },
"allow" :
{
"requests":
@@ -430,6 +431,23 @@
}
]
}
+ },
+ {
+ "credentials" : {
+ "allow": [
+ {
+ "uid": [
+ "9000"
+ ],
+ "gid": [
+ "9000"
+ ]
+ }
+ ]
+ },
+ "deny" :
+ {
+ }
}
]
},
diff --git a/test/cpu_load_tests/conf/cpu_load_test_client_master.json.in b/test/cpu_load_tests/conf/cpu_load_test_client_master.json.in
index d623758..ec9dcd7 100644
--- a/test/cpu_load_tests/conf/cpu_load_test_client_master.json.in
+++ b/test/cpu_load_tests/conf/cpu_load_test_client_master.json.in
@@ -21,6 +21,12 @@
"id" : "0x2222"
}
],
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "cpu_load_test_client",
"service-discovery" :
{
diff --git a/test/cpu_load_tests/conf/cpu_load_test_client_slave.json.in b/test/cpu_load_tests/conf/cpu_load_test_client_slave.json.in
index 36de379..4da82f4 100644
--- a/test/cpu_load_tests/conf/cpu_load_test_client_slave.json.in
+++ b/test/cpu_load_tests/conf/cpu_load_test_client_slave.json.in
@@ -21,6 +21,12 @@
"id" : "0x2222"
}
],
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "cpu_load_test_client",
"service-discovery" :
{
diff --git a/test/cpu_load_tests/conf/cpu_load_test_service_master.json.in b/test/cpu_load_tests/conf/cpu_load_test_service_master.json.in
index d836650..da34e22 100644
--- a/test/cpu_load_tests/conf/cpu_load_test_service_master.json.in
+++ b/test/cpu_load_tests/conf/cpu_load_test_service_master.json.in
@@ -34,7 +34,12 @@
}
}
],
-
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "cpu_load_test_service",
"service-discovery" :
{
diff --git a/test/cpu_load_tests/conf/cpu_load_test_service_slave.json.in b/test/cpu_load_tests/conf/cpu_load_test_service_slave.json.in
index 78e1909..389aea0 100644
--- a/test/cpu_load_tests/conf/cpu_load_test_service_slave.json.in
+++ b/test/cpu_load_tests/conf/cpu_load_test_service_slave.json.in
@@ -34,7 +34,12 @@
}
}
],
-
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "cpu_load_test_service",
"service-discovery" :
{
diff --git a/test/cpu_load_tests/cpu_load_measurer.cpp b/test/cpu_load_tests/cpu_load_measurer.cpp
index 2261d22..d4360b3 100644
--- a/test/cpu_load_tests/cpu_load_measurer.cpp
+++ b/test/cpu_load_tests/cpu_load_measurer.cpp
@@ -113,7 +113,8 @@ std::uint64_t cpu_load_measurer::read_proc_pid_stat() {
exit(1);
}
std::fclose(f);
- return utime + stime + cutime + cstime;
+ return utime + stime + static_cast<std::uint64_t>(cutime) +
+ static_cast<std::uint64_t>(cstime);
}
std::uint64_t cpu_load_measurer::read_proc_stat(std::uint64_t* _idle) {
diff --git a/test/cpu_load_tests/cpu_load_test_client.cpp b/test/cpu_load_tests/cpu_load_test_client.cpp
index 94fd98b..6cc0571 100644
--- a/test/cpu_load_tests/cpu_load_test_client.cpp
+++ b/test/cpu_load_tests/cpu_load_test_client.cpp
@@ -17,7 +17,7 @@
#include <atomic>
#include "cpu_load_test_globals.hpp"
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "cpu_load_measurer.hpp"
// for getpid
@@ -212,14 +212,14 @@ private:
void send_messages_sync(std::unique_lock<std::mutex>& lk, std::uint32_t _messages_to_send) {
- cpu_load_measurer c(::getpid());
+ cpu_load_measurer c(static_cast<std::uint32_t>(::getpid()));
send_service_start_measuring(true);
c.start();
for (number_of_sent_messages_ = 0;
number_of_sent_messages_ < _messages_to_send;
number_of_sent_messages_++, number_of_sent_messages_total_++)
{
- app_->send(request_, true);
+ app_->send(request_);
// wait until the send messages has been acknowledged
while(wait_for_all_msg_acknowledged_) {
all_msg_acknowledged_cv_.wait(lk);
@@ -237,14 +237,14 @@ private:
}
void send_messages_async(std::unique_lock<std::mutex>& lk, std::uint32_t _messages_to_send) {
- cpu_load_measurer c(::getpid());
+ cpu_load_measurer c(static_cast<std::uint32_t>(::getpid()));
send_service_start_measuring(true);
c.start();
for (number_of_sent_messages_ = 0;
number_of_sent_messages_ < _messages_to_send;
number_of_sent_messages_++, number_of_sent_messages_total_++)
{
- app_->send(request_, true);
+ app_->send(request_);
if((number_of_sent_messages_+1) % sliding_window_size_ == 0)
{
// wait until all send messages have been acknowledged
diff --git a/test/cpu_load_tests/cpu_load_test_master_starter.sh b/test/cpu_load_tests/cpu_load_test_master_starter.sh
index 50bf007..d4c96be 100755
--- a/test/cpu_load_tests/cpu_load_test_master_starter.sh
+++ b/test/cpu_load_tests/cpu_load_test_master_starter.sh
@@ -19,9 +19,9 @@ sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting cpu load test on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_TARGET_DIR/vsomeip/test; ./cpu_load_test_slave_starter.sh"' &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP 'bash -ci "set -m; cd \$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./cpu_load_test_slave_starter.sh"' &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name cltms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./cpu_load_test_slave_starter.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./cpu_load_test_slave_starter.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -66,11 +66,6 @@ do
wait $job || FAIL=$(($FAIL+1))
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop cltms
- docker rm cltms
-fi
-
# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/cpu_load_tests/cpu_load_test_service.cpp b/test/cpu_load_tests/cpu_load_test_service.cpp
index 6d21752..35e6c1e 100644
--- a/test/cpu_load_tests/cpu_load_test_service.cpp
+++ b/test/cpu_load_tests/cpu_load_test_service.cpp
@@ -15,7 +15,7 @@
#include <cmath> // for isfinite
#include "cpu_load_test_globals.hpp"
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "cpu_load_measurer.hpp"
// for getpid
@@ -31,7 +31,7 @@ public:
blocked_(false),
number_of_received_messages_(0),
number_of_received_messages_total_(0),
- load_measurer_(::getpid()),
+ load_measurer_(static_cast<std::uint32_t>(::getpid())),
offer_thread_(std::bind(&cpu_load_test_service::run, this))
{
}
@@ -118,7 +118,7 @@ public:
number_of_received_messages_++;
number_of_received_messages_total_++;
// send response
- app_->send(vsomeip::runtime::get()->create_response(_request), true);
+ app_->send(vsomeip::runtime::get()->create_response(_request));
}
void on_message_start_measuring(const std::shared_ptr<vsomeip::message>& _request)
diff --git a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_client.cpp b/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_client.cpp
deleted file mode 100644
index a3e6e5e..0000000
--- a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_client.cpp
+++ /dev/null
@@ -1,748 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <chrono>
-#include <condition_variable>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <thread>
-#include <map>
-#include <algorithm>
-#include <cstring>
-
-#include <gtest/gtest.h>
-
-#ifndef _WIN32
-#include <signal.h>
-#endif
-
-#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-
-#include "../debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp"
-class debug_diag_job_plugin_test_client;
-static debug_diag_job_plugin_test_client* the_client;
-extern "C" void signal_handler(int _signum);
-
-
-enum class debug_diag_job_app_error_type_e : std::uint32_t {
- ET_UNKNOWN = 0,
- ET_OK = 256,
- ET_OUT_OF_RANGE = 257,
- ET_E_COMMUNICATION_ERROR = 576,
-};
-
-class debug_diag_job_plugin_test_client {
-public:
- debug_diag_job_plugin_test_client(
- std::array<debug_diag_job_plugin_test::service_info, 3> _service_infos_local,
- std::array<debug_diag_job_plugin_test::service_info, 3> _service_infos_remote) :
- service_infos_local_(_service_infos_local),
- service_infos_remote_(_service_infos_remote),
- app_(vsomeip::runtime::get()->create_application()),
- wait_until_registered_(true),
- wait_until_remote_services_available_(true),
- wait_until_debug_diag_job_service_available_(true),
- wait_until_local_services_available_(true),
- wait_until_local_services_unavailable_(true),
- wait_until_notifications_received_(true),
- wait_until_responses_received_(true),
- wait_until_debug_diag_job_response_received_(true),
- wait_for_stop_(true),
- last_response_(debug_diag_job_app_error_type_e::ET_UNKNOWN),
- stop_thread_(std::bind(&debug_diag_job_plugin_test_client::wait_for_stop, this)),
- run_thread_(std::bind(&debug_diag_job_plugin_test_client::run, this)) {
- if (!app_->init()) {
- ADD_FAILURE() << "Couldn't initialize application";
- return;
- }
-
- // register signal handler
- the_client = this;
- struct sigaction sa_new, sa_old;
- sa_new.sa_handler = signal_handler;
- sa_new.sa_flags = 0;
- sigemptyset(&sa_new.sa_mask);
- ::sigaction(SIGUSR1, &sa_new, &sa_old);
- ::sigaction(SIGINT, &sa_new, &sa_old);
- ::sigaction(SIGTERM, &sa_new, &sa_old);
- ::sigaction(SIGABRT, &sa_new, &sa_old);
-
- app_->register_state_handler(
- std::bind(&debug_diag_job_plugin_test_client::on_state, this,
- std::placeholders::_1));
-
- app_->register_message_handler(vsomeip::ANY_SERVICE,
- vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
- std::bind(&debug_diag_job_plugin_test_client::on_message, this,
- std::placeholders::_1));
-
- for (const auto& serviceinfos : {service_infos_remote_, service_infos_local_}) {
- for (const auto& serviceinfo : serviceinfos) {
- if (serviceinfo.service_id == 0xFFFF && serviceinfo.instance_id == 0xFFFF) {
- continue;
- }
- service_infos_.push_back(serviceinfo);
- }
- }
-
- // register availability for all other services and request their event.
- for (const auto& i : service_infos_) {
- app_->register_availability_handler(i.service_id, i.instance_id,
- std::bind(&debug_diag_job_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3));
- app_->request_service(i.service_id, i.instance_id);
-
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(i.eventgroup_id);
- app_->request_event(i.service_id, i.instance_id,
- static_cast<vsomeip::event_t>(i.event_id),
- its_eventgroups, true);
-
- other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false;
-
- app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id);
- other_services_received_notification_[std::make_pair(i.service_id, i.event_id)] = 0;
- other_services_received_response_[std::make_pair(i.service_id, i.instance_id)] = 0;
- }
-
- for (const auto& si : service_infos_local_) {
- if (si.service_id == 0xFFFF && si.instance_id == 0xFFFF) {
- continue;
- }
- other_local_services_available_[std::make_pair(si.service_id, si.instance_id)] = false;
- other_local_services_received_notification_[std::make_pair(si.service_id, si.event_id)] = 0;
- }
-
- for (const auto& si : service_infos_remote_) {
- if (si.service_id == 0xFFFF && si.instance_id == 0xFFFF) {
- continue;
- }
- other_remote_services_available_[std::make_pair(si.service_id, si.instance_id)] = false;
- other_remote_services_received_notification_[std::make_pair(si.service_id, si.event_id)] = 0;
- }
- app_->register_availability_handler(
- debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id,
- debug_diag_job_plugin_test::debug_diag_job_serviceinfo.instance_id,
- std::bind(&debug_diag_job_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3));
- app_->request_service(
- debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id,
- debug_diag_job_plugin_test::debug_diag_job_serviceinfo.instance_id,
- 0x1, vsomeip::ANY_MINOR);
-
- app_->start();
- }
-
- ~debug_diag_job_plugin_test_client() {
- run_thread_.join();
- stop_thread_.join();
-
- }
-
- void on_state(vsomeip::state_type_e _state) {
- VSOMEIP_INFO << "Application " << app_->get_name() << " is "
- << (_state == vsomeip::state_type_e::ST_REGISTERED ?
- "registered." : "deregistered.");
-
- if (_state == vsomeip::state_type_e::ST_REGISTERED) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_registered_ = false;
- condition_.notify_one();
- }
- }
-
- void on_availability(vsomeip::service_t _service,
- vsomeip::instance_t _instance, bool _is_available) {
- if(_is_available) {
- for (auto available_map : {&other_services_available_,
- &other_local_services_available_,
- &other_remote_services_available_}) {
- auto its_service = available_map->find(std::make_pair(_service, _instance));
- if (its_service != available_map->end()) {
- if (its_service->second != _is_available) {
- its_service->second = true;
- VSOMEIP_DEBUG << "Service ["
- << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
- << "] is available.";
- }
- }
- }
-
- if (std::all_of(other_remote_services_available_.cbegin(),
- other_remote_services_available_.cend(),
- [](const std::map<std::pair<vsomeip::service_t,
- vsomeip::instance_t>, bool>::value_type& v) {
- return v.second;})) {
- VSOMEIP_INFO << " all remote services are available.";
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_remote_services_available_ = false;
- condition_.notify_one();
- }
-
- if (_service == debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id &&
- _instance == debug_diag_job_plugin_test::debug_diag_job_serviceinfo.instance_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_debug_diag_job_service_available_ = false;
- condition_.notify_one();
- }
-
- if (std::all_of(other_local_services_available_.cbegin(),
- other_local_services_available_.cend(),
- [](const std::map<std::pair<vsomeip::service_t,
- vsomeip::instance_t>, bool>::value_type& v) {
- return v.second;})) {
- VSOMEIP_INFO << "all local services are available.";
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_local_services_available_ = false;
- condition_.notify_one();
- }
-
- if (std::all_of(other_services_available_.cbegin(),
- other_services_available_.cend(),
- [](const std::map<std::pair<vsomeip::service_t,
- vsomeip::instance_t>, bool>::value_type& v) {
- return v.second;})) {
- VSOMEIP_INFO << "all local and remote services are available.";
- }
- } else {
- bool was_available_before(false);
- auto its_service = other_local_services_available_.find(std::make_pair(_service, _instance));
- if (its_service != other_local_services_available_.end()) {
- if (its_service->second) {
- its_service->second = false;
- VSOMEIP_DEBUG << "Service ["
- << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
- << "] is not available anymore.";
- was_available_before = true;
- }
- }
- if (was_available_before) {
- if (std::all_of(other_local_services_available_.cbegin(),
- other_local_services_available_.cend(),
- [](const std::map<std::pair<vsomeip::service_t,
- vsomeip::instance_t>, bool>::value_type& v) {
- return !v.second;})) {
- VSOMEIP_INFO << "all local services are not available anymore.";
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_local_services_unavailable_ = false;
- condition_.notify_one();
- }
- }
- }
- }
-
- void on_message(const std::shared_ptr<vsomeip::message> &_message) {
- if (_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
-
- other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())]++;
-
- VSOMEIP_DEBUG
- << "Received a notification with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _message->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_session() << "] from Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method() <<"] (now have: "
- << std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())] << ")";
-
- std::shared_ptr<vsomeip::payload> its_payload(_message->get_payload());
- EXPECT_EQ(2u, its_payload->get_length());
- EXPECT_EQ((_message->get_service() & 0xFF00 ) >> 8, its_payload->get_data()[0]);
- EXPECT_EQ((_message->get_service() & 0xFF), its_payload->get_data()[1]);
- bool notify = all_notifications_received();
-
- if(notify) {
- for (auto &os : other_local_services_received_notification_) {
- os.second = 0;
- }
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_notifications_received_ = false;
- condition_.notify_one();
- }
- } else if (_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE &&
- _message->get_service() != debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id) {
- other_services_received_response_[std::make_pair(_message->get_service(),
- _message->get_instance())]++;
- VSOMEIP_INFO
- << "Received a response with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _message->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_session() << "] from Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method() <<"] (now have: "
- << std::dec << other_services_received_response_[std::make_pair(_message->get_service(),
- _message->get_instance())] << ")";
- if (std::all_of(other_services_received_response_.begin(),
- other_services_received_response_.end(),
- [&](const std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, std::uint32_t>::value_type& v) {
- return v.second > 0;
- })) {
- VSOMEIP_INFO << "received responses of all services!";
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_responses_received_ = false;
- condition_.notify_one();
- }
- } else if (_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE &&
- _message->get_service() == debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_debug_diag_job_response_received_ = false;
- last_response_ = debug_diag_job_app_error_type_e::ET_UNKNOWN;
- auto its_payload = _message->get_payload();
- if (its_payload && its_payload->get_length() > 3) {
-
- last_response_ = static_cast<debug_diag_job_app_error_type_e>(
- (its_payload->get_data()[0] << 24) |
- (its_payload->get_data()[1] << 16) |
- (its_payload->get_data()[2] << 8) |
- (its_payload->get_data()[3]));
- }
- condition_.notify_one();
- }
- }
-
- bool all_notifications_received() {
- return std::all_of(
- other_services_received_notification_.cbegin(),
- other_services_received_notification_.cend(),
- [&](const std::map<std::pair<vsomeip::service_t,
- vsomeip::method_t>, std::uint32_t>::value_type& v)
- {
- if (v.second == debug_diag_job_plugin_test::notifications_to_send) {
- return true;
- } else {
- if (v.second >= debug_diag_job_plugin_test::notifications_to_send) {
- VSOMEIP_WARNING
- << " Received multiple initial events from service/instance: "
- << std::setw(4) << std::setfill('0') << std::hex << v.first.first
- << "."
- << std::setw(4) << std::setfill('0') << std::hex << v.first.second
- << " number of received events: " << v.second
- << ". This is caused by StopSubscribe/Subscribe messages and/or"
- << " service offered via UDP and TCP";
- return false;
- } else {
- return false;
- }
- }
- }
- );
- }
-
- void handle_signal(int _signum) {
- VSOMEIP_DEBUG << "Catched signal, going down ("
- << std::dec <<_signum << ")";
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
- wait_for_stop_ = false;
- stop_condition_.notify_one();
- }
-
- void wait_for_stop() {
- {
- std::unique_lock<std::mutex> its_lock(stop_mutex_);
- while (wait_for_stop_) {
- stop_condition_.wait(its_lock);
- }
- VSOMEIP_INFO << "going down";
- }
- for (const auto& i : service_infos_) {
- if (i.service_id == 0xFFFF && i.instance_id == 0xFFFF) {
- continue;
- }
- app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
- app_->release_event(i.service_id, i.instance_id, i.event_id);
- app_->release_service(i.service_id, i.instance_id);
- }
- app_->clear_all_handler();
- app_->stop();
- }
-
- void call_debug_diag_job(bool _offer) {
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
- its_request->set_service(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id);
- its_request->set_instance(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.instance_id);
- if (_offer) {
- its_request->set_method(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.method_id);
- std::vector<vsomeip::byte_t> its_payload;
- for (int i =0; i<8; i++) { // handletype and size placeholder
- its_payload.push_back(0x0);
- }
- // insert valid entries
- for (const auto& si : service_infos_local_) {
- if (si.service_id == 0xFFFF && si.instance_id == 0xFFFF) {
- continue;
- }
- for (auto reliable : {false, true}) { // ensure to offer service reliable and unreliable
- // service
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.service_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.service_id & 0xFF));
- // instance
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.instance_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.instance_id & 0xFF));
- // port (use event id as port)
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.event_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.event_id & 0xFF));
- // reliable
- its_payload.push_back(reliable);
- // magic_cookies_enabled
- its_payload.push_back(reliable);
- }
- }
-
- std::size_t its_size = its_payload.size() - 8;
- its_payload[4] = vsomeip::byte_t(its_size >> 24 & 0xFF);
- its_payload[5] = vsomeip::byte_t(its_size >> 16 & 0xFF);
- its_payload[6] = vsomeip::byte_t(its_size >> 8 & 0xFF);
- its_payload[7] = vsomeip::byte_t(its_size & 0xFF);
-
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- } else {
- its_request->set_method(debug_diag_job_plugin_test::debug_diag_job_serviceinfo_reset.method_id);
- }
- std::unique_lock<std::mutex> its_lock(mutex_);
- app_->send(its_request);
- while(wait_until_debug_diag_job_response_received_) {
- condition_.wait(its_lock);
- }
- EXPECT_EQ(debug_diag_job_app_error_type_e::ET_OK, last_response_);
- wait_until_debug_diag_job_response_received_ = true;
-
- }
-
- void call_debug_diag_job_wrong_message(bool _offer) {
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
- its_request->set_service(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.service_id);
- its_request->set_instance(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.instance_id);
- if (_offer) {
- its_request->set_method(debug_diag_job_plugin_test::debug_diag_job_serviceinfo.method_id);
- } else {
- its_request->set_method(debug_diag_job_plugin_test::debug_diag_job_serviceinfo_reset.method_id);
- }
- std::vector<vsomeip::byte_t> its_payload;
- for (int i =0; i<8; i++) { // handletype and size placeholder
- its_payload.push_back(0x0);
- }
- // insert valid entries
- for (const auto& si : service_infos_local_) {
- if (si.service_id == 0xFFFF && si.instance_id == 0xFFFF) {
- continue;
- }
- for (auto reliable : {false, true}) { // ensure to offer service reliable and unreliable
- // service
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.service_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.service_id & 0xFF));
- // instance
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.instance_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.instance_id & 0xFF));
- // port (use event id as port)
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.event_id >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(si.event_id & 0xFF));
- // reliable
- its_payload.push_back(reliable);
- // magic_cookies_enabled
- its_payload.push_back(reliable);
- }
- }
-
- // insert invalid entry
- // service
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xAAAA >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xAAAA & 0xFF));
- // instance
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xBBBB >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xBBBB & 0xFF));
- // port
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xCCCC >> 8));
- its_payload.push_back(static_cast<vsomeip::byte_t>(0xCCCC & 0xFF));
- // reliable
- its_payload.push_back(0x1);
- // magic_cookies_enabled
- its_payload.push_back(0x1);
-
- for (int var = 0; var < 12; ++var) { // insert invalid data covered by size
- its_payload.push_back(0xdd);
- }
-
- std::size_t its_size = its_payload.size() - 8;
- its_payload[4] = vsomeip::byte_t(its_size >> 24 & 0xFF);
- its_payload[5] = vsomeip::byte_t(its_size >> 16 & 0xFF);
- its_payload[6] = vsomeip::byte_t(its_size >> 8 & 0xFF);
- its_payload[7] = vsomeip::byte_t(its_size & 0xFF);
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
-
- auto send_request_and_wait_for_reply = [&](
- const std::shared_ptr<vsomeip::message>& _request,
- debug_diag_job_app_error_type_e _expected_response) {
- std::unique_lock<std::mutex> its_lock(mutex_);
- app_->send(_request);
- while(wait_until_debug_diag_job_response_received_) {
- condition_.wait(its_lock);
- }
- EXPECT_EQ(_expected_response, last_response_);
- wait_until_debug_diag_job_response_received_ = true;
- };
-
- send_request_and_wait_for_reply(its_request, debug_diag_job_app_error_type_e::ET_OUT_OF_RANGE);
-
- // send a request w/o payload
- its_payload.clear();
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- send_request_and_wait_for_reply(its_request, debug_diag_job_app_error_type_e::ET_OUT_OF_RANGE);
-
-
-
- // send a request with to few data and a too big size field
- its_payload.clear();
- its_payload.push_back(0x0); // handle
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x11); // size
- its_payload.push_back(0x22);
- its_payload.push_back(0x33);
- its_payload.push_back(0x44);
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- send_request_and_wait_for_reply(its_request, debug_diag_job_app_error_type_e::ET_OUT_OF_RANGE);
-
-
- // send a request with to few data and a size of zero field
- its_payload.clear();
- its_payload.push_back(0x0); // handle
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0); // size
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- send_request_and_wait_for_reply(its_request, debug_diag_job_app_error_type_e::ET_OUT_OF_RANGE);
-
- // send a request with valid size and data but additional data at the end
- its_payload.clear();
- its_payload.push_back(0x0); // handle
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0); // size
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0x0);
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
- its_payload.push_back(0xDD); // data
-
- its_size = its_payload.size() - 8;
- its_payload[4] = vsomeip::byte_t(its_size >> 24 & 0xFF);
- its_payload[5] = vsomeip::byte_t(its_size >> 16 & 0xFF);
- its_payload[6] = vsomeip::byte_t(its_size >> 8 & 0xFF);
- its_payload[7] = vsomeip::byte_t(its_size & 0xFF);
-
- its_payload.push_back(0xDD); // data
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- send_request_and_wait_for_reply(its_request, debug_diag_job_app_error_type_e::ET_OUT_OF_RANGE);
- }
-
- void call_shutdown_method() {
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
-
- auto send_request = [&](const debug_diag_job_plugin_test::service_info& _info) {
- if (_info.service_id == 0xFFFF && _info.instance_id == 0xFFFF) {
- return;
- }
- its_request->set_service(_info.service_id);
- its_request->set_instance(_info.instance_id);
- its_request->set_method(_info.method_id);
- app_->send(its_request);
- };
- // insert valid entries
- for (const auto& si : service_infos_local_) {
- send_request(si);
- }
- for (const auto& si : service_infos_remote_) {
- send_request(si);
- }
- }
-
- void run() {
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_registered_) {
- condition_.wait(its_lock);
- }
- }
- // wait until remote services are available
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_remote_services_available_) {
- condition_.wait(its_lock);
- }
- wait_until_remote_services_available_ = true;
- VSOMEIP_WARNING << "Remote services available";
- }
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_debug_diag_job_service_available_) {
- condition_.wait(its_lock);
- }
- wait_until_debug_diag_job_service_available_ = true;
- VSOMEIP_WARNING << "debug diag job service available";
- }
- // trigger offering of local services
- call_debug_diag_job(true);
- call_debug_diag_job(true);
- VSOMEIP_WARNING << "Calling debug_diag_job_service (offer)";
- // wait until local services are available as well
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_local_services_available_) {
- condition_.wait(its_lock);
- }
- wait_until_local_services_available_ = true;
- VSOMEIP_WARNING << "local services available";
- }
-
- // check that from all services events were received
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_notifications_received_) {
- condition_.wait(its_lock);
- }
- wait_until_notifications_received_ = true;
- VSOMEIP_WARNING << "notifications received";
- }
-
- // tigger stop offering of local services
- call_debug_diag_job(false);
- VSOMEIP_WARNING << "Calling debug_diag_job_service (stop offer)";
- // wait until local services are unavailable
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_local_services_unavailable_) {
- condition_.wait(its_lock);
- }
- wait_until_local_services_unavailable_ = true;
- VSOMEIP_WARNING << "local services unavailable";
- }
-
- // trigger offering of local services
- VSOMEIP_WARNING << "Calling debug_diag_job_service (offer)";
- call_debug_diag_job_wrong_message(true);
- // wait until local services are available as well again
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_local_services_available_) {
- condition_.wait(its_lock);
- }
- wait_until_local_services_available_ = true;
- VSOMEIP_WARNING << "local services available";
- }
- VSOMEIP_WARNING << "Calling shutdown method";
- call_shutdown_method();
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_responses_received_) {
- if (std::cv_status::timeout ==
- condition_.wait_for(its_lock, std::chrono::seconds(10))) {
- ADD_FAILURE() << "Didn't receive shutdown responses within time";
- wait_until_responses_received_ = false;
- } else {
- VSOMEIP_WARNING << "received shutdown method responses";
- }
- }
- wait_until_responses_received_ = true;
- }
- {
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
- wait_for_stop_ = false;
- stop_condition_.notify_one();
- }
- }
-
-private:
- std::array<debug_diag_job_plugin_test::service_info, 3> service_infos_local_;
- std::array<debug_diag_job_plugin_test::service_info, 3> service_infos_remote_;
- std::vector<debug_diag_job_plugin_test::service_info> service_infos_;
- std::shared_ptr<vsomeip::application> app_;
- std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
- std::map<std::pair<vsomeip::service_t, vsomeip::event_t>, std::uint32_t> other_services_received_notification_;
-
- std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_remote_services_available_;
- std::map<std::pair<vsomeip::service_t, vsomeip::event_t>, std::uint32_t> other_remote_services_received_notification_;
-
- std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_local_services_available_;
- std::map<std::pair<vsomeip::service_t, vsomeip::event_t>, std::uint32_t> other_local_services_received_notification_;
-
- std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, std::uint32_t> other_services_received_response_;
-
- bool wait_until_registered_;
- bool wait_until_remote_services_available_;
- bool wait_until_debug_diag_job_service_available_;
- bool wait_until_local_services_available_;
- bool wait_until_local_services_unavailable_;
- bool wait_until_notifications_received_;
- bool wait_until_responses_received_;
- bool wait_until_debug_diag_job_response_received_;
- std::mutex mutex_;
- std::condition_variable condition_;
-
- bool wait_for_stop_;
-
- debug_diag_job_app_error_type_e last_response_;
- std::mutex stop_mutex_;
- std::condition_variable stop_condition_;
- std::thread stop_thread_;
-
- std::thread run_thread_;
-};
-
-extern "C" void signal_handler(int signum) {
- the_client->handle_signal(signum);
-}
-
-TEST(someip_debug_diag_job_plugin_test, remotely_enable_offering_of_local_services)
-{
- debug_diag_job_plugin_test_client its_sample(
- debug_diag_job_plugin_test::service_infos_local,
- debug_diag_job_plugin_test::service_infos_remote);
-}
-
-#ifndef _WIN32
-int main(int argc, char** argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-#endif
diff --git a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp b/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp
deleted file mode 100644
index eff3aa0..0000000
--- a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef DEBUG_DIAG_JOB_PLUGIN_TEST_GLOBALS_HPP_
-#define DEBUG_DIAG_JOB_PLUGIN_TEST_GLOBALS_HPP_
-
-namespace debug_diag_job_plugin_test {
-
-struct service_info {
- vsomeip::service_t service_id;
- vsomeip::instance_t instance_id;
- vsomeip::method_t method_id;
- vsomeip::event_t event_id;
- vsomeip::eventgroup_t eventgroup_id;
-};
-
-static constexpr std::array<service_info, 3> service_infos_remote = {{
- // placeholder to be consistent w/ client ids, service ids, app names
- { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
- { 0x1010, 0x1, 0x1010, 0x8111, 0x1 },
- { 0x2020, 0x1, 0x2020, 0x8222, 0x2 }
-}};
-
-static constexpr std::array<service_info, 3> service_infos_local = {{
- // placeholder to be consistent w/ client ids, service ids, app names
- { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF },
- { 0x3030, 0x1, 0x3030, 0x8333, 0x1 },
- { 0x4040, 0x1, 0x4040, 0x8444, 0x2 }
-}};
-
-static constexpr service_info debug_diag_job_serviceinfo = { 0xfea3, 0x80, 0x1, 0x0, 0x0 };
-static constexpr service_info debug_diag_job_serviceinfo_reset = { 0xfea3, 0x80, 0x2, 0x0, 0x0 };
-
-static constexpr int notifications_to_send = 1;
-}
-
-#endif /* DEBUG_DIAG_JOB_PLUGIN_TEST_GLOBALS_HPP_ */
diff --git a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_master_starter.sh b/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_master_starter.sh
deleted file mode 100755
index 82963fb..0000000
--- a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_master_starter.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Purpose: This script is needed to start the services with
-# one command. This is necessary as ctest - which is used to run the
-# tests - isn't able to start multiple binaries for one testcase. Therefore
-# the testcase simply executes this script. This script then runs the services
-# and checks that all exit successfully.
-
-export VSOMEIP_CONFIGURATION=debug_diag_job_plugin_test_master.json
-# start daemon
-export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(readlink -f ../plugins/mgu)
-../daemon/./vsomeipd &
-PID_VSOMEIPD=$!
-# Start the services
-# Array for service pids
-SERVICE_PIDS=()
-./debug_diag_job_plugin_test_service 1 &
-SERVICE_PIDS+=($!)
-./debug_diag_job_plugin_test_service 2 &
-SERVICE_PIDS+=($!)
-
-print_starter_message () {
-
-if [ ! -z "$USE_LXC_TEST" ]; then
- echo "starting initial event test on slave LXC with params $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $REMAINING_OPTIONS"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./debug_diag_job_plugin_test_slave_starter.sh\"" &
-elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name ietms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./debug_diag_job_plugin_test_slave_starter.sh" &
-else
-cat <<End-of-message
-*******************************************************************************
-*******************************************************************************
-** Please now run:
-** debug_diag_job_plugin_test_slave_starter.sh
-** from an external host to successfully complete this test.
-**
-** You probably will need to adapt the 'unicast' settings in
-** debug_diag_job_plugin_test_master.json and
-** debug_diag_job_plugin_test_slave.json to your personal setup.
-*******************************************************************************
-*******************************************************************************
-End-of-message
-fi
-}
-sleep 1
-print_starter_message
-
-FAIL=0
-# Wait until all clients are finished
-for job in ${SERVICE_PIDS[*]}
-do
- # Fail gets incremented if a client exits with a non-zero exit code
- wait $job || FAIL=$(($FAIL+1))
-done
-
-kill $PID_VSOMEIPD
-
-echo ""
-
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop ietms
- docker rm ietms
-fi
-
-# Check if both exited successfully
-exit $FAIL
diff --git a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_service.cpp b/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_service.cpp
deleted file mode 100644
index ed4bb7a..0000000
--- a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_service.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <chrono>
-#include <condition_variable>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <thread>
-#include <map>
-#include <algorithm>
-
-#include <gtest/gtest.h>
-
-#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-
-#include "../debug_diag_job_plugin_tests/debug_diag_job_plugin_test_globals.hpp"
-
-static int service_number(0);
-
-class debug_diag_job_plugin_test_service {
-public:
- debug_diag_job_plugin_test_service(struct debug_diag_job_plugin_test::service_info _service_info_local,
- struct debug_diag_job_plugin_test::service_info _service_info_remote,
- std::uint32_t _events_to_offer) :
- service_info_local_(_service_info_local),
- service_info_remote_(_service_info_remote),
- app_(vsomeip::runtime::get()->create_application()),
- wait_until_registered_(true),
- events_to_offer_(_events_to_offer),
- offer_thread_(std::bind(&debug_diag_job_plugin_test_service::run, this)) {
- if (!app_->init()) {
- ADD_FAILURE() << "Couldn't initialize application";
- return;
- }
- app_->register_state_handler(
- std::bind(&debug_diag_job_plugin_test_service::on_state, this,
- std::placeholders::_1));
- app_->register_message_handler(service_info_local_.service_id,
- service_info_local_.instance_id, service_info_local_.method_id,
- std::bind(&debug_diag_job_plugin_test_service::on_shutdown_method_called,
- this, std::placeholders::_1));
- app_->register_message_handler(service_info_remote_.service_id,
- service_info_remote_.instance_id, service_info_remote_.method_id,
- std::bind(&debug_diag_job_plugin_test_service::on_shutdown_method_called,
- this, std::placeholders::_1));
-
- for (auto si : {service_info_local_, service_info_remote_}) {
- // offer field
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(si.eventgroup_id);
- for (std::uint16_t i = 0; i < events_to_offer_; i++) {
- app_->offer_event(si.service_id, si.instance_id,
- static_cast<vsomeip::event_t>(si.event_id + i), its_eventgroups, true);
- }
-
- // set value to field
- std::shared_ptr<vsomeip::payload> its_payload =
- vsomeip::runtime::get()->create_payload();
- vsomeip::byte_t its_data[2] = {static_cast<vsomeip::byte_t>((si.service_id & 0xFF00) >> 8),
- static_cast<vsomeip::byte_t>((si.service_id & 0xFF))};
- its_payload->set_data(its_data, 2);
- for (std::uint16_t i = 0; i < events_to_offer_; i++) {
- app_->notify(si.service_id, si.instance_id,
- static_cast<vsomeip::event_t>(si.event_id + i), its_payload);
- }
- }
-
- if (service_number == 1) {
- // the debug mode service only needs to be offered one time
- // debug mode service and event
-
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(1);
- app_->offer_event(0xfc10, 0x80, 0x8001, its_eventgroups, true);
- std::shared_ptr<vsomeip::payload> its_payload =
- vsomeip::runtime::get()->create_payload();
- vsomeip::byte_t data[1] = {0x1};
- its_payload->set_data(data, 1);
- app_->notify(0xfc10, 0x80, 0x8001, its_payload);
- }
- app_->start();
- }
-
- ~debug_diag_job_plugin_test_service() {
- offer_thread_.join();
- }
-
- void offer() {
- if (service_number == 1) {
- // the debug mode service only needs to be offered one time
- app_->offer_service(0xfc10, 0x80, 1, vsomeip::ANY_MINOR);
- }
- for (auto si : {service_info_local_, service_info_remote_}) {
- app_->offer_service(si.service_id, si.instance_id);
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
- << si.service_id << "] Offering";
- }
- }
-
- void on_state(vsomeip::state_type_e _state) {
- VSOMEIP_INFO << "Application " << app_->get_name() << " is "
- << (_state == vsomeip::state_type_e::ST_REGISTERED ?
- "registered." : "deregistered.");
-
- if (_state == vsomeip::state_type_e::ST_REGISTERED) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_registered_ = false;
- condition_.notify_one();
- }
- }
-
- void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
- app_->send(vsomeip::runtime::get()->create_response(_message));
- static bool shutdown_called_local = false;
- static bool shutdown_called_remote = false;
- if (_message->get_method() == service_info_local_.method_id) {
- shutdown_called_local = true;
- } else if (_message->get_method() == service_info_remote_.method_id) {
- shutdown_called_remote = true;
- }
- if (shutdown_called_local && shutdown_called_remote) {
- VSOMEIP_WARNING << "Shutdown method called -> going down!";
- for (auto si : {service_info_local_, service_info_remote_}) {
- app_->stop_offer_service(si.service_id, si.instance_id);
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0')
- << std::hex << si.service_id << "] Stop Offering";
- }
- app_->clear_all_handler();
- app_->stop();
- }
- }
-
- void run() {
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
- << service_info_local_.service_id << "] Running";
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_registered_) {
- condition_.wait(its_lock);
- }
- offer();
- }
-
-private:
- debug_diag_job_plugin_test::service_info service_info_local_;
- debug_diag_job_plugin_test::service_info service_info_remote_;
- std::shared_ptr<vsomeip::application> app_;
-
- bool wait_until_registered_;
- std::uint32_t events_to_offer_;
- std::mutex mutex_;
- std::condition_variable condition_;
- std::thread offer_thread_;
-};
-
-static std::uint32_t offer_multiple_events;
-
-TEST(someip_debug_diag_job_plugin_test, offer_one_remote_and_one_local_service)
-{
- debug_diag_job_plugin_test_service its_sample(
- debug_diag_job_plugin_test::service_infos_local[service_number],
- debug_diag_job_plugin_test::service_infos_remote[service_number],
- offer_multiple_events);
-}
-
-#ifndef _WIN32
-int main(int argc, char** argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- if(argc < 2) {
- std::cerr << "Please specify a service number and subscription type, like: " << argv[0] << " 2 SAME_SERVICE_ID" << std::endl;
- std::cerr << "Valid service numbers are in the range of [1,2]" << std::endl;
- return 1;
- }
-
- service_number = std::stoi(std::string(argv[1]), nullptr);
-
- offer_multiple_events = 1;
- return RUN_ALL_TESTS();
-}
-#endif
diff --git a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_slave_starter.sh b/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_slave_starter.sh
deleted file mode 100755
index 207ff64..0000000
--- a/test/debug_diag_job_plugin_tests/debug_diag_job_plugin_test_slave_starter.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Purpose: This script is needed to start the services with
-# one command. This is necessary as ctest - which is used to run the
-# tests - isn't able to start multiple binaries for one testcase. Therefore
-# the testcase simply executes this script. This script then runs the services
-# and checks that all exit successfully.
-
-FAIL=0
-
-export VSOMEIP_CONFIGURATION=debug_diag_job_plugin_test_slave.json
-
-../daemon/./vsomeipd &
-PID_VSOMEIPD=$!
-
-# Start the services
-export VSOMEIP_APPLICATION_NAME=debug_diag_job_plugin_test_client
-./debug_diag_job_plugin_test_client &
-PID_CLIENT=$!
-
-wait $PID_CLIENT || FAIL=$(($FAIL+1))
-
-kill $PID_VSOMEIPD
-
-sleep 1
-echo ""
-
-# Check if both exited successfully
-exit $FAIL
diff --git a/test/e2e_tests/e2e_test_client.cpp b/test/e2e_tests/e2e_test_client.cpp
index ca136d9..dc04b56 100644
--- a/test/e2e_tests/e2e_test_client.cpp
+++ b/test/e2e_tests/e2e_test_client.cpp
@@ -78,12 +78,10 @@ void e2e_test_client::on_state(vsomeip::state_type_e _state) {
app_->request_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
static_cast<vsomeip::event_t>(0x8001),
- its_eventgroups, true);
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD);
app_->request_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
static_cast<vsomeip::event_t>(0x8002),
- its_eventgroups_2, true);
- app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x01);
- app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x02);
+ its_eventgroups_2, vsomeip::event_type_e::ET_FIELD);
}
}
@@ -109,6 +107,10 @@ void e2e_test_client::on_availability(vsomeip::service_t _service,
}
else if(_is_available && !is_available_) {
is_available_ = true;
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x01);
+ app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x02);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
condition_.notify_one();
}
}
@@ -206,13 +208,13 @@ void e2e_test_client::run() {
// protected answer holding a fixed payload (profile 01 CRC8)
// this call triggers also an event 0x8001 which holds a calculated payload
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->send(request, true);
+ app_->send(request);
// send a request which is not e2e protected and expect an
// protected answer holding a fixed payload (custom profile CRC32)
// this call triggers also an event 0x8002 which holds a calculated payload
request->set_method(0x6543);
- app_->send(request, true);
+ app_->send(request);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
@@ -231,7 +233,7 @@ void e2e_test_client::shutdown_service() {
request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->send(request,true);
+ app_->send(request);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
// expect 10 x response messages for both method IDs and events for both Event IDs
diff --git a/test/e2e_tests/e2e_test_external_master_start.sh b/test/e2e_tests/e2e_test_external_master_start.sh
index c18f787..3e54d9b 100755
--- a/test/e2e_tests/e2e_test_external_master_start.sh
+++ b/test/e2e_tests/e2e_test_external_master_start.sh
@@ -31,7 +31,7 @@ PID_CLIENT=$!
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external e2e test on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./e2e_test_external_slave_start.sh $SERVICE_JSON_FILE" &
else
diff --git a/test/e2e_tests/e2e_test_service.cpp b/test/e2e_tests/e2e_test_service.cpp
index 886596e..9984cbc 100644
--- a/test/e2e_tests/e2e_test_service.cpp
+++ b/test/e2e_tests/e2e_test_service.cpp
@@ -59,7 +59,9 @@ bool e2e_test_service::init() {
// profile01 CRC8 Event ID: 0x8001
app_->offer_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- static_cast<vsomeip::event_t>(0x8001), its_eventgroups, true);
+ static_cast<vsomeip::event_t>(0x8001), its_eventgroups,
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
// set value to field which gets filled by e2e protection with CRC on sending
// after e2e protection the payload for first event should look like:
@@ -74,7 +76,9 @@ bool e2e_test_service::init() {
// custom profile CRC32 Event ID: 0x8002
app_->offer_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- static_cast<vsomeip::event_t>(0x8002), its_eventgroups_2, true);
+ static_cast<vsomeip::event_t>(0x8002), its_eventgroups_2,
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
// set value to field which gets filled by e2e protection with CRC on sending
// after e2e protection the payload for first event should look like:
@@ -154,7 +158,7 @@ void e2e_test_service::on_message(const std::shared_ptr<vsomeip::message>& _requ
if (_request->get_method() == vsomeip_test::TEST_SERVICE_METHOD_ID) {
its_vsomeip_payload->set_data(payloads_profile_01_[received_requests_counters_[vsomeip_test::TEST_SERVICE_METHOD_ID] % vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND]);
its_response->set_payload(its_vsomeip_payload);
- app_->send(its_response, true);
+ app_->send(its_response);
// set value to field which gets filled by e2e protection with CRC on sending
vsomeip::byte_t its_data[8] = {0x00, 0x00, (uint8_t)received_requests_counters_[vsomeip_test::TEST_SERVICE_METHOD_ID], 0xff, 0xff, 0xff, 0xff, 0xff};
@@ -166,7 +170,7 @@ void e2e_test_service::on_message(const std::shared_ptr<vsomeip::message>& _requ
//send fixed payload for custom profile CRC32
its_vsomeip_payload->set_data(payloads_custom_profile_[received_requests_counters_[0x6543] % vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND]);
its_response->set_payload(its_vsomeip_payload);
- app_->send(its_response, true);
+ app_->send(its_response);
// set value to field which gets filled by e2e protection with 4 byte CRC 32 on sending
vsomeip::byte_t its_data[8] = {0x00, 0x00, 0x00, 0x00, 0xff, 0xff, (uint8_t)received_requests_counters_[0x6543], 0x32};
diff --git a/test/event_tests/conf/event_test_master.json.in b/test/event_tests/conf/event_test_master.json.in
index 5190c87..b8db14f 100644
--- a/test/event_tests/conf/event_test_master.json.in
+++ b/test/event_tests/conf/event_test_master.json.in
@@ -19,7 +19,7 @@
"max_dispatch_time" : "1000"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/event_tests/conf/event_test_slave_tcp.json.in b/test/event_tests/conf/event_test_slave_tcp.json.in
index 57eba12..d0bbed9 100644
--- a/test/event_tests/conf/event_test_slave_tcp.json.in
+++ b/test/event_tests/conf/event_test_slave_tcp.json.in
@@ -30,7 +30,7 @@
}
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/event_tests/conf/event_test_slave_udp.json.in b/test/event_tests/conf/event_test_slave_udp.json.in
index 8071e04..6bf693b 100644
--- a/test/event_tests/conf/event_test_slave_udp.json.in
+++ b/test/event_tests/conf/event_test_slave_udp.json.in
@@ -27,7 +27,7 @@
"unreliable":"30001"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/event_tests/event_test_client.cpp b/test/event_tests/event_test_client.cpp
index fd65719..f415702 100644
--- a/test/event_tests/event_test_client.cpp
+++ b/test/event_tests/event_test_client.cpp
@@ -16,8 +16,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-#include "../../implementation/configuration/include/internal.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "event_test_globals.hpp"
@@ -64,7 +63,7 @@ public:
its_eventgroups.insert(service_info_.eventgroup_id);
app_->request_event(service_info_.service_id,
service_info_.instance_id, service_info_.event_id,
- its_eventgroups, false);
+ its_eventgroups, vsomeip::event_type_e::ET_EVENT);
app_->register_subscription_status_handler(service_info_.service_id,
service_info_.instance_id, service_info_.eventgroup_id,
service_info_.event_id,
@@ -73,8 +72,7 @@ public:
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5));
app_->subscribe(service_info_.service_id, service_info_.instance_id,
- service_info_.eventgroup_id, vsomeip::DEFAULT_MAJOR,
- vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ service_info_.eventgroup_id);
app_->start();
}
diff --git a/test/event_tests/event_test_master_starter.sh b/test/event_tests/event_test_master_starter.sh
index 6c39053..7c2aec0 100755
--- a/test/event_tests/event_test_master_starter.sh
+++ b/test/event_tests/event_test_master_starter.sh
@@ -18,7 +18,7 @@ TESTMODE=$1
COMMUNICATIONMODE=$2
export VSOMEIP_CONFIGURATION=event_test_master.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
./event_test_client $TESTMODE $COMMUNICATIONMODE &
@@ -28,7 +28,7 @@ sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./event_test_slave_starter.sh $COMMUNICATIONMODE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./event_test_slave_starter.sh $COMMUNICATIONMODE\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./event_test_slave_starter.sh $COMMUNICATIONMODE" &
else
diff --git a/test/event_tests/event_test_service.cpp b/test/event_tests/event_test_service.cpp
index 271aa49..f9cf28f 100644
--- a/test/event_tests/event_test_service.cpp
+++ b/test/event_tests/event_test_service.cpp
@@ -14,7 +14,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "event_test_globals.hpp"
@@ -41,7 +41,9 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(_service_info.eventgroup_id);
app_->offer_event(service_info_.service_id, service_info_.instance_id,
- service_info_.event_id, its_eventgroups, false);
+ service_info_.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
app_->register_message_handler(service_info_.service_id,
service_info_.instance_id, service_info_.shutdown_method_id,
std::bind(&event_test_service::on_shutdown_method_called, this,
@@ -53,7 +55,8 @@ public:
app_->register_subscription_handler(service_info_.service_id,
service_info_.instance_id, service_info_.eventgroup_id,
std::bind(&event_test_service::subscription_handler,
- this, std::placeholders::_1, std::placeholders::_2));
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
app_->start();
}
@@ -147,7 +150,9 @@ public:
}
}
- bool subscription_handler(vsomeip::client_t _client, bool _subscribed) {
+ bool subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
+ (void)_uid;
+ (void)_gid;
VSOMEIP_INFO << __func__ << ": client: 0x" << std::hex << _client
<< ((_subscribed) ? " subscribed" : "unsubscribed");
client_subscribed_ = _subscribed;
diff --git a/test/event_tests/event_test_slave_starter.sh b/test/event_tests/event_test_slave_starter.sh
index 9cc8e72..964175b 100755
--- a/test/event_tests/event_test_slave_starter.sh
+++ b/test/event_tests/event_test_slave_starter.sh
@@ -22,7 +22,7 @@ elif [ "$COMMUNICATIONMODE" = "UDP" ]; then
fi
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
./event_test_service &
diff --git a/test/header_factory_tests/header_factory_test_client.cpp b/test/header_factory_tests/header_factory_test_client.cpp
index 90cfef5..3ac4a06 100644
--- a/test/header_factory_tests/header_factory_test_client.cpp
+++ b/test/header_factory_tests/header_factory_test_client.cpp
@@ -8,7 +8,6 @@
header_factory_test_client::header_factory_test_client(bool _use_tcp) :
app_(vsomeip::runtime::get()->create_application()),
request_(vsomeip::runtime::get()->create_request(_use_tcp)),
- running_(true),
blocked_(false),
is_available_(false),
number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND),
@@ -134,7 +133,7 @@ void header_factory_test_client::run()
for (uint32_t i = 0; i < number_of_messages_to_send_; i++)
{
- app_->send(request_, true);
+ app_->send(request_);
VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0')
<< std::hex << request_->get_client() << "/" << std::setw(4)
<< std::setfill('0') << std::hex << request_->get_session()
diff --git a/test/header_factory_tests/header_factory_test_client.hpp b/test/header_factory_tests/header_factory_test_client.hpp
index eb62191..8e9a4c2 100644
--- a/test/header_factory_tests/header_factory_test_client.hpp
+++ b/test/header_factory_tests/header_factory_test_client.hpp
@@ -35,10 +35,8 @@ public:
private:
std::shared_ptr<vsomeip::application> app_;
std::shared_ptr<vsomeip::message> request_;
- bool use_tcp_;
std::mutex mutex_;
std::condition_variable condition_;
- bool running_;
bool blocked_;
bool is_available_;
std::uint32_t number_of_messages_to_send_;
diff --git a/test/header_factory_tests/header_factory_test_service.cpp b/test/header_factory_tests/header_factory_test_service.cpp
index 12527ed..d60c743 100644
--- a/test/header_factory_tests/header_factory_test_service.cpp
+++ b/test/header_factory_tests/header_factory_test_service.cpp
@@ -120,7 +120,7 @@ void header_factory_test_service::on_message(const std::shared_ptr<vsomeip::mess
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
if(number_of_received_messages_ >= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND)
{
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_tcp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_tcp.json.in
index 7cb35fb..a05d13f 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_tcp.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_tcp.json.in
@@ -31,116 +31,29 @@
{
"service":"0x1111",
"instance":"0x0001",
- "unreliable":"30001",
"reliable":
{
"port":"40001",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x1111",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1112",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1113",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1114",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1115",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x2222",
"instance":"0x0001",
- "unreliable":"30002",
"reliable":
{
"port":"40002",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x2222",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2223",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2224",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2225",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2226",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x3333",
"instance":"0x0001",
- "unreliable":"30003",
"reliable":
{
"port":"40003",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x3333",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3334",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3335",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3336",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3337",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x8888",
diff --git a/test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_master.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_udp.json.in
index cb47d1e..8ce06f0 100644
--- a/test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_master.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_master_udp.json.in
@@ -11,50 +11,49 @@
},
"dlt":"false"
},
- "diagnosis" : "0x63",
"applications":
[
{
- "name":"debug_diag_job_plugin_test_service_one",
- "id":"0x1010"
+ "name":"initial_event_test_service_one",
+ "id":"0x1111"
},
{
- "name":"debug_diag_job_plugin_test_service_two",
+ "name":"initial_event_test_service_two",
"id":"0x2222"
},
{
- "name":"vsomeipd",
- "plugins" :
- [
- {
- "application_plugin" : "vsomeip-debug-diagnosis-plugin-mgu"
- }
- ]
+ "name":"initial_event_test_service_three",
+ "id":"0x3333"
}
],
"services":
[
{
- "service":"0x1010",
+ "service":"0x1111",
"instance":"0x0001",
- "unreliable":"40001"
+ "unreliable":"30001"
},
{
- "service":"0x2020",
+ "service":"0x2222",
"instance":"0x0001",
- "unreliable":"40002"
+ "unreliable":"30002"
},
{
- "service":"0xfea3",
- "instance":"0x80",
- "unreliable":"50000"
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30003"
+ },
+ {
+ "service":"0x8888",
+ "instance":"0x0001",
+ "unreliable":"8888"
}
],
- "routing":"vsomeipd",
+ "routing":"initial_event_test_service_one",
"service-discovery":
{
"enable":"true",
- "multicast":"224.1.1.1",
+ "multicast":"224.0.0.1",
"port":"30490",
"protocol":"udp",
"initial_delay_min" : "10",
@@ -64,4 +63,4 @@
"cyclic_offer_delay" : "1000",
"ttl" : "3"
}
-} \ No newline at end of file
+}
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_tcp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_tcp.json.in
index 320e2a3..1fc97a4 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_tcp.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_tcp.json.in
@@ -32,116 +32,29 @@
{
"service":"0x4444",
"instance":"0x0001",
- "unreliable":"30004",
"reliable":
{
"port":"40004",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x4444",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4445",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4446",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4447",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4448",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x5555",
"instance":"0x0001",
- "unreliable":"30005",
"reliable":
{
"port":"40005",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x5555",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5556",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5557",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5558",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5559",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x6666",
"instance":"0x0001",
- "unreliable":"30006",
"reliable":
{
"port":"40006",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x6666",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6667",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6668",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6669",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x666a",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x9999",
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_udp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_udp.json.in
new file mode 100644
index 0000000..d303a4c
--- /dev/null
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_diff_ports_slave_udp.json.in
@@ -0,0 +1,67 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "diagnosis" : "0x63",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"initial_event_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"initial_event_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30004"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30005"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30006"
+ },
+ {
+ "service":"0x9999",
+ "instance":"0x0001",
+ "unreliable":"9999"
+ }
+ ],
+ "routing":"initial_event_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_tcp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_tcp.json.in
index 7336aa2..b065685 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_tcp.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_tcp.json.in
@@ -31,116 +31,29 @@
{
"service":"0x1111",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x1111",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1112",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1113",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1114",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x1115",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x2222",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x2222",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2223",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2224",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2225",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x2226",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x3333",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x3333",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3334",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3335",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3336",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x3337",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x8888",
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_udp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_udp.json.in
new file mode 100644
index 0000000..ca77daf
--- /dev/null
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_master_udp.json.in
@@ -0,0 +1,66 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"initial_event_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"initial_event_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x8888",
+ "instance":"0x0001",
+ "unreliable":"8888"
+ }
+ ],
+ "routing":"initial_event_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_tcp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_tcp.json.in
index f22ad4e..eaeab4a 100644
--- a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_tcp.json.in
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_tcp.json.in
@@ -32,116 +32,29 @@
{
"service":"0x4444",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x4444",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4445",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4446",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4447",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x4448",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x5555",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x5555",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5556",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5557",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5558",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x5559",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x6666",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x6666",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6667",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6668",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x6669",
- "is_field" : "true",
- "is_reliable" : "true"
- },
- {
- "event" : "0x666a",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x9999",
diff --git a/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_udp.json.in b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_udp.json.in
new file mode 100644
index 0000000..5d978f0
--- /dev/null
+++ b/test/initial_event_tests/conf/initial_event_test_diff_client_ids_same_ports_slave_udp.json.in
@@ -0,0 +1,67 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "diagnosis" : "0x63",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"initial_event_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"initial_event_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x9999",
+ "instance":"0x0001",
+ "unreliable":"9999"
+ }
+ ],
+ "routing":"initial_event_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/initial_event_tests/initial_event_test_availability_checker.cpp b/test/initial_event_tests/initial_event_test_availability_checker.cpp
index 719d6d3..6a2eab9 100644
--- a/test/initial_event_tests/initial_event_test_availability_checker.cpp
+++ b/test/initial_event_tests/initial_event_test_availability_checker.cpp
@@ -15,7 +15,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "initial_event_test_globals.hpp"
@@ -28,7 +28,6 @@ public:
service_infos_(_service_infos),
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
- wait_until_other_services_available_(true),
wait_for_stop_(true),
stop_thread_(std::bind(&initial_event_test_availability_checker::wait_for_stop, this)) {
if (!app_->init()) {
@@ -117,7 +116,6 @@ private:
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
bool wait_until_registered_;
- bool wait_until_other_services_available_;
std::mutex mutex_;
std::condition_variable condition_;
diff --git a/test/initial_event_tests/initial_event_test_client.cpp b/test/initial_event_tests/initial_event_test_client.cpp
index 20f1f94..a26e7b0 100644
--- a/test/initial_event_tests/initial_event_test_client.cpp
+++ b/test/initial_event_tests/initial_event_test_client.cpp
@@ -20,7 +20,7 @@
#endif
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "initial_event_test_globals.hpp"
@@ -31,17 +31,16 @@ extern "C" void signal_handler(int _signum);
class initial_event_test_client {
public:
initial_event_test_client(int _client_number,
- vsomeip::subscription_type_e _subscription_type,
+ bool _service_offered_tcp_and_udp,
std::array<initial_event_test::service_info, 7> _service_infos,
bool _subscribe_on_available, std::uint32_t _events_to_subscribe,
bool _initial_event_strict_checking,
bool _dont_exit, bool _subscribe_only_one) :
client_number_(_client_number),
service_infos_(_service_infos),
- subscription_type_(_subscription_type),
+ service_offered_tcp_and_udp_(_service_offered_tcp_and_udp),
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
- wait_until_other_services_available_(true),
wait_for_stop_(true),
subscribe_on_available_(_subscribe_on_available),
events_to_subscribe_(_events_to_subscribe),
@@ -81,7 +80,7 @@ public:
for (std::uint32_t j = 0; j < events_to_subscribe_; j++ ) {
app_->request_event(i.service_id, i.instance_id,
static_cast<vsomeip::event_t>(i.event_id + j),
- its_eventgroups, true);
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD);
}
other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false;
@@ -89,19 +88,19 @@ public:
if (!subscribe_on_available_) {
if (events_to_subscribe_ == 1) {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_);
+ vsomeip::DEFAULT_MAJOR);
other_services_received_notification_[std::make_pair(i.service_id, i.event_id)] = 0;
} else if (events_to_subscribe_ > 1) {
if (!subscribe_only_one_) {
for (std::uint32_t j = 0; j < events_to_subscribe_; j++ ) {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_,
+ vsomeip::DEFAULT_MAJOR,
static_cast<vsomeip::event_t>(i.event_id + j));
other_services_received_notification_[std::make_pair(i.service_id, i.event_id + j)] = 0;
}
} else {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_,
+ vsomeip::DEFAULT_MAJOR,
static_cast<vsomeip::event_t>(i.event_id));
other_services_received_notification_[std::make_pair(i.service_id, i.event_id)] = 0;
}
@@ -177,11 +176,11 @@ public:
}
if (events_to_subscribe_ == 1 ) {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_);
+ vsomeip::DEFAULT_MAJOR);
} else if (events_to_subscribe_ > 1) {
for (std::uint32_t j = 0; j < events_to_subscribe_; j++ ) {
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_,
+ vsomeip::DEFAULT_MAJOR,
static_cast<vsomeip::event_t>(i.event_id + j));
}
}
@@ -214,20 +213,14 @@ public:
EXPECT_EQ((_message->get_service() & 0xFF00 ) >> 8, its_payload->get_data()[0]);
EXPECT_EQ((_message->get_service() & 0xFF), its_payload->get_data()[1]);
bool notify(false);
- switch(subscription_type_) {
- case vsomeip::subscription_type_e::SU_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_RELIABLE:
- if (all_notifications_received()) {
- notify = true;
- }
- break;
- case vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE:
- if (all_notifications_received_tcp_and_udp()) {
- notify = true;
- }
- break;
+ if (!service_offered_tcp_and_udp_) {
+ if (all_notifications_received()) {
+ notify = true;
+ }
+ } else {
+ if (all_notifications_received_tcp_and_udp()) {
+ notify = true;
+ }
}
if (notify && !dont_exit_) {
@@ -245,8 +238,9 @@ public:
[&](const std::map<std::pair<vsomeip::service_t,
vsomeip::method_t>, std::uint32_t>::value_type& v)
{
+ bool result;
if (v.second == initial_event_test::notifications_to_send) {
- return true;
+ result = true;
} else {
if (v.second >= initial_event_test::notifications_to_send) {
VSOMEIP_WARNING
@@ -268,12 +262,14 @@ public:
<< std::setw(4) << std::setfill('0') << std::hex << v.first.second
<< " number of received events: " << v.second;
}
- return initial_event_strict_checking_ ? false : true;
+ result = initial_event_strict_checking_ ? false : true;
} else {
- return false;
+ result = false;
}
}
+
+ return result;
}
);
}
@@ -315,7 +311,7 @@ public:
// routing manager stub receives the notification
// - twice from external nodes
// - and normal from all internal nodes
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ VSOMEIP_ERROR << "[" << std::setw(4) << std::setfill('0') << std::hex
<< client_number_ << "] "
<< "Received notifications:"
<< " Normal: " << received_normal
@@ -377,12 +373,15 @@ public:
}
void wait_for_stop() {
+ static int its_call_number(0);
+ its_call_number++;
+
{
std::unique_lock<std::mutex> its_lock(stop_mutex_);
while (wait_for_stop_) {
stop_condition_.wait_for(its_lock, std::chrono::milliseconds(100));
}
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ VSOMEIP_ERROR << "(" << std::dec << its_call_number << ") [" << std::setw(4) << std::setfill('0') << std::hex
<< client_number_
<< "] Received notifications from all services, going down";
}
@@ -399,13 +398,12 @@ public:
private:
int client_number_;
std::array<initial_event_test::service_info, 7> service_infos_;
- vsomeip::subscription_type_e subscription_type_;
+ bool service_offered_tcp_and_udp_;
std::shared_ptr<vsomeip::application> app_;
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_notification_;
bool wait_until_registered_;
- bool wait_until_other_services_available_;
std::mutex mutex_;
std::condition_variable condition_;
@@ -427,7 +425,7 @@ private:
};
static int client_number;
-static vsomeip::subscription_type_e subscription_type;
+static bool service_offered_tcp_and_udp;
static bool use_same_service_id;
static bool subscribe_on_available;
static std::uint32_t subscribe_multiple_events;
@@ -443,12 +441,13 @@ TEST(someip_initial_event_test, wait_for_initial_events_of_all_services)
{
if(use_same_service_id) {
initial_event_test_client its_sample(client_number,
- subscription_type,
- initial_event_test::service_infos_same_service_id, subscribe_on_available,
- subscribe_multiple_events, initial_event_strict_checking, dont_exit,
+ service_offered_tcp_and_udp,
+ initial_event_test::service_infos_same_service_id,
+ subscribe_on_available, subscribe_multiple_events,
+ initial_event_strict_checking, dont_exit,
subscribe_only_one);
} else {
- initial_event_test_client its_sample(client_number, subscription_type,
+ initial_event_test_client its_sample(client_number, service_offered_tcp_and_udp,
initial_event_test::service_infos, subscribe_on_available,
subscribe_multiple_events, initial_event_strict_checking, dont_exit,
subscribe_only_one);
@@ -464,12 +463,11 @@ int main(int argc, char** argv)
pthread_sigmask(SIG_BLOCK, &mask, NULL);
::testing::InitGoogleTest(&argc, argv);
- if(argc < 3) {
- std::cerr << "Please specify a client number and subscription type, like: " << argv[0] << " 2 UDP SUBSCRIBE_BEFORE_START SAME_SERVICE_ID" << std::endl;
+ if(argc < 2) {
+ std::cerr << "Please specify a client number, like: " << argv[0] << " 2 SUBSCRIBE_BEFORE_START SAME_SERVICE_ID" << std::endl;
std::cerr << "Valid client numbers are from 0 to 0xFFFF" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
- std::cerr << "After client number and subscription types one/multiple of these flags can be specified:";
+ std::cerr << "After client number one/multiple of these flags can be specified:";
+ std::cerr << " - SERVICE_OFFERED_TCP_AND_UDP flag. Set this if the service is offered via TCP and UDP" << std::endl;
std::cerr << " - Time of subscription, valid values: [SUBSCRIBE_ON_AVAILABILITY, SUBSCRIBE_BEFORE_START], default SUBSCRIBE_BEFORE_START" << std::endl;
std::cerr << " - SAME_SERVICE_ID flag. If set the test is run w/ multiple instances of the same service, default false" << std::endl;
std::cerr << " - MULTIPLE_EVENTS flag. If set the test will subscribe to multiple events in the eventgroup, default false" << std::endl;
@@ -481,31 +479,15 @@ int main(int argc, char** argv)
client_number = std::stoi(std::string(argv[1]), nullptr);
- if(std::string("TCP_AND_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE;
- } else if(std::string("PREFER_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE;
- } else if(std::string("PREFER_TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_RELIABLE;
- } else if(std::string("UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_UNRELIABLE;
- } else if(std::string("TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE;
- } else {
- std::cerr << "Wrong subscription type passed, exiting" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
- return 1;
- }
-
subscribe_on_available = false;
initial_event_strict_checking = false;
+ service_offered_tcp_and_udp = false;
use_same_service_id = false;
subscribe_multiple_events = 1;
dont_exit = false;
subscribe_only_one = false;
- if (argc > 3) {
- for (int i = 3; i < argc; i++) {
+ if (argc > 2) {
+ for (int i = 2; i < argc; i++) {
if (std::string("SUBSCRIBE_ON_AVAILABILITY") == std::string(argv[i])) {
subscribe_on_available = true;
} else if (std::string("SUBSCRIBE_BEFORE_START") == std::string(argv[i])) {
diff --git a/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_master_udp.json b/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_master_udp.json
new file mode 100644
index 0000000..a5bdb5f
--- /dev/null
+++ b/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_master_udp.json
@@ -0,0 +1,66 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"initial_event_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"initial_event_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30002"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30003"
+ },
+ {
+ "service":"0x8888",
+ "instance":"0x0001",
+ "unreliable":"8888"
+ }
+ ],
+ "routing":"initial_event_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_slave_udp.json b/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_slave_udp.json
new file mode 100644
index 0000000..caf4e12
--- /dev/null
+++ b/test/initial_event_tests/initial_event_test_diff_client_ids_diff_ports_slave_udp.json
@@ -0,0 +1,67 @@
+{
+ "unicast":"10.0.3.2",
+ "diagnosis" : "0x63",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"initial_event_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"initial_event_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30004"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30005"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30006"
+ },
+ {
+ "service":"0x9999",
+ "instance":"0x0001",
+ "unreliable":"9999"
+ }
+ ],
+ "routing":"initial_event_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_master_udp.json b/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_master_udp.json
new file mode 100644
index 0000000..5d15fbf
--- /dev/null
+++ b/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_master_udp.json
@@ -0,0 +1,66 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"initial_event_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"initial_event_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x8888",
+ "instance":"0x0001",
+ "unreliable":"8888"
+ }
+ ],
+ "routing":"initial_event_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_slave_udp.json b/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_slave_udp.json
new file mode 100644
index 0000000..3c6a682
--- /dev/null
+++ b/test/initial_event_tests/initial_event_test_diff_client_ids_same_ports_slave_udp.json
@@ -0,0 +1,67 @@
+{
+ "unicast":"10.0.3.2",
+ "diagnosis" : "0x63",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"initial_event_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"initial_event_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"initial_event_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x9999",
+ "instance":"0x0001",
+ "unreliable":"9999"
+ }
+ ],
+ "routing":"initial_event_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/initial_event_tests/initial_event_test_master_starter.sh b/test/initial_event_tests/initial_event_test_master_starter.sh
index b083c53..c78d3e8 100755
--- a/test/initial_event_tests/initial_event_test_master_starter.sh
+++ b/test/initial_event_tests/initial_event_test_master_starter.sh
@@ -10,57 +10,33 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP initial_event_test_diff_client_ids_diff_ports_master.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
- echo "For example: $0 UDP initial_event_test_diff_client_ids_diff_ports_master.json"
+ echo "For example: $0 initial_event_test_diff_client_ids_diff_ports_master.json"
echo "To use the same service id but different instances on the node pass SAME_SERVICE_ID as third parameter"
echo "To ensure the first client only subscribes to one event pass SUBSCRIBE_ONLY_ONE as third/fourth parameter"
exit 1
fi
-PASSED_SUBSCRIPTION_TYPE=$1
-PASSED_JSON_FILE=$2
+PASSED_JSON_FILE=$1
# Remove processed options from $@
-shift 2
+shift 1
REMAINING_OPTIONS="$@"
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $PASSED_SUBSCRIPTION_TYPE ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
- exit 1
-fi
-
print_starter_message () {
if [ ! -z "$USE_LXC_TEST" ]; then
- echo "starting initial event test on slave LXC with params $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $REMAINING_OPTIONS"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $REMAINING_OPTIONS\"" &
+ echo "starting initial event test on slave LXC with params $CLIENT_JSON_FILE $REMAINING_OPTIONS"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name ietms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $REMAINING_OPTIONS" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS" &
else
cat <<End-of-message
*******************************************************************************
*******************************************************************************
** Please now run:
-** initial_event_test_slave_starter.sh $PASSED_SUBSCRIPTION_TYPE $CLIENT_JSON_FILE $REMAINING_OPTIONS
+** initial_event_test_slave_starter.sh $CLIENT_JSON_FILE $REMAINING_OPTIONS
** from an external host to successfully complete this test.
**
** You probably will need to adapt the 'unicast' settings in
@@ -100,7 +76,7 @@ unset VSOMEIP_APPLICATION_NAME
CLIENT_PIDS=()
# Start first client which subscribes remotely
-./initial_event_test_client 9000 $PASSED_SUBSCRIPTION_TYPE DONT_EXIT $REMAINING_OPTIONS &
+./initial_event_test_client 9000 DONT_EXIT $REMAINING_OPTIONS &
FIRST_PID=$!
# Start availability checker in order to wait until the services on the remote
@@ -125,7 +101,7 @@ sleep 2
for client_number in $(seq 9001 9011)
do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE STRICT_CHECKING $REMAINING_OPTIONS &
+ ./initial_event_test_client $client_number STRICT_CHECKING $REMAINING_OPTIONS &
CLIENT_PIDS+=($!)
done
@@ -153,11 +129,6 @@ kill $PID_SERVICE_ONE
sleep 1
echo ""
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop ietms
- docker rm ietms
-fi
-
# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/initial_event_tests/initial_event_test_service.cpp b/test/initial_event_tests/initial_event_test_service.cpp
index 037149e..3b96174 100644
--- a/test/initial_event_tests/initial_event_test_service.cpp
+++ b/test/initial_event_tests/initial_event_test_service.cpp
@@ -15,7 +15,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "initial_event_test_globals.hpp"
@@ -42,7 +42,10 @@ public:
its_eventgroups.insert(service_info_.eventgroup_id);
for (std::uint16_t i = 0; i < events_to_offer_; i++) {
app_->offer_event(service_info_.service_id, service_info_.instance_id,
- static_cast<vsomeip::event_t>(service_info_.event_id + i), its_eventgroups, true);
+ static_cast<vsomeip::event_t>(service_info_.event_id + i),
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(), false, true, nullptr,
+ vsomeip::reliability_type_e::RT_UNKNOWN);
}
// set value to field
@@ -103,7 +106,7 @@ private:
std::thread offer_thread_;
};
-static int service_number;
+static unsigned long service_number;
static bool use_same_service_id;
static std::uint32_t offer_multiple_events;
@@ -131,7 +134,7 @@ int main(int argc, char** argv)
return 1;
}
- service_number = std::stoi(std::string(argv[1]), nullptr);
+ service_number = std::stoul(std::string(argv[1]), nullptr);
offer_multiple_events = 1;
use_same_service_id = false;
diff --git a/test/initial_event_tests/initial_event_test_slave_starter.sh b/test/initial_event_tests/initial_event_test_slave_starter.sh
index 59fdd5b..083119f 100755
--- a/test/initial_event_tests/initial_event_test_slave_starter.sh
+++ b/test/initial_event_tests/initial_event_test_slave_starter.sh
@@ -10,12 +10,8 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP initial_event_test_diff_client_ids_diff_ports_slave.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
echo "For example: $0 UDP initial_event_test_diff_client_ids_diff_ports_slave.json"
echo "To use the same service id but different instances on the node pass SAME_SERVICE_ID as third parameter"
@@ -23,32 +19,11 @@ then
exit 1
fi
-PASSED_SUBSCRIPTION_TYPE=$1
-PASSED_JSON_FILE=$2
+PASSED_JSON_FILE=$1
# Remove processed options from $@
-shift 2
+shift 1
REMAINING_OPTIONS=$@
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $PASSED_SUBSCRIPTION_TYPE ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
- exit 1
-fi
-
-
FAIL=0
export VSOMEIP_CONFIGURATION=$PASSED_JSON_FILE
@@ -72,7 +47,7 @@ unset VSOMEIP_APPLICATION_NAME
CLIENT_PIDS=()
# Start first client which subscribes remotely
-./initial_event_test_client 9000 $PASSED_SUBSCRIPTION_TYPE DONT_EXIT $REMAINING_OPTIONS &
+./initial_event_test_client 9000 DONT_EXIT $REMAINING_OPTIONS &
FIRST_PID=$!
# remove SUBSCRIBE_ONLY_ONCE parameter from $REMAINING_OPTIONS to ensure the
@@ -90,7 +65,7 @@ wait $PID_AVAILABILITY_CHECKER
sleep 2;
for client_number in $(seq 9001 9011)
do
- ./initial_event_test_client $client_number $PASSED_SUBSCRIPTION_TYPE STRICT_CHECKING $REMAINING_OPTIONS &
+ ./initial_event_test_client $client_number STRICT_CHECKING $REMAINING_OPTIONS &
CLIENT_PIDS+=($!)
done
diff --git a/test/initial_event_tests/initial_event_test_stop_service.cpp b/test/initial_event_tests/initial_event_test_stop_service.cpp
index 8f32fbc..83cd34c 100644
--- a/test/initial_event_tests/initial_event_test_stop_service.cpp
+++ b/test/initial_event_tests/initial_event_test_stop_service.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "initial_event_test_globals.hpp"
@@ -146,15 +146,18 @@ public:
<< std::setw(4) << std::setfill('0') << std::hex
<< _message->get_session() << "] shutdown method called";
+
+ VSOMEIP_ERROR << "stop_service::" << __func__
+ << ": (1)";
std::lock_guard<std::mutex> its_lock(stop_mutex_);
+ VSOMEIP_ERROR << "stop_service::" << __func__
+ << ": (2)";
wait_for_stop_ = false;
stop_condition_.notify_one();
}
}
void run() {
- VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
- << service_info_.service_id << "] Running";
{
std::unique_lock<std::mutex> its_lock(mutex_);
while (wait_until_registered_) {
@@ -198,11 +201,14 @@ public:
}
void wait_for_stop() {
+ static int its_call_number(0);
+ its_call_number++;
+
std::unique_lock<std::mutex> its_lock(stop_mutex_);
while (wait_for_stop_) {
stop_condition_.wait(its_lock);
}
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ VSOMEIP_INFO << "(" << std::dec << its_call_number << ") [" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id
<< "] shutdown method was called, going down";
while(!called_other_node_) {
diff --git a/test/magic_cookies_tests/magic_cookies_test_client.cpp b/test/magic_cookies_tests/magic_cookies_test_client.cpp
index 4be0889..dc02309 100644
--- a/test/magic_cookies_tests/magic_cookies_test_client.cpp
+++ b/test/magic_cookies_tests/magic_cookies_test_client.cpp
@@ -21,7 +21,6 @@ class magic_cookies_test_client {
public:
magic_cookies_test_client()
: app_(new vsomeip::application_impl("")),
- is_available_(false),
is_blocked_(false),
sent_messages_good_(8),
sent_messages_bad_(7),
@@ -53,7 +52,8 @@ public:
app_->register_availability_handler(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
std::bind(&magic_cookies_test_client::on_availability,
this,
- std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
+ vsomeip::DEFAULT_MAJOR, vsomeip::DEFAULT_MINOR);
}
void start() {
@@ -72,8 +72,7 @@ public:
VSOMEIP_INFO << "Client registration done.";
app_->request_service(vsomeip_test::TEST_SERVICE_SERVICE_ID,
vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR,
- false);
+ vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
}
}
@@ -162,49 +161,49 @@ public:
// Test sequence
its_good_payload_data[11] = 0x01;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x02;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x03;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x04;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x05;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x06;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x07;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x08;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x09;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x0A;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x0B;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x0C;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x0D;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_bad_payload_data[11] = 0x0E;
- its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_bad_payload_data, sizeof(its_bad_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
std::this_thread::sleep_for(std::chrono::seconds(11));
its_good_payload_data[11] = 0x0F;
- its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true, true);
+ its_routing->send(0x1343, its_good_payload_data, sizeof(its_good_payload_data), vsomeip_test::TEST_SERVICE_INSTANCE_ID, true);
while (wait_for_replies_) {
if(std::cv_status::timeout ==
@@ -222,7 +221,6 @@ private:
std::shared_ptr< vsomeip::application_impl > app_;
std::mutex mutex_;
std::condition_variable condition_;
- bool is_available_;
bool is_blocked_;
const std::uint32_t sent_messages_good_;
const std::uint32_t sent_messages_bad_;
diff --git a/test/magic_cookies_tests/magic_cookies_test_service.cpp b/test/magic_cookies_tests/magic_cookies_test_service.cpp
index 7cd4376..d8ac4d7 100644
--- a/test/magic_cookies_tests/magic_cookies_test_service.cpp
+++ b/test/magic_cookies_tests/magic_cookies_test_service.cpp
@@ -92,11 +92,11 @@ public:
->create_payload();
std::vector<vsomeip::byte_t> its_payload_data;
for (std::size_t i = 0; i < 120; ++i)
- its_payload_data.push_back(i % 256);
+ its_payload_data.push_back(static_cast<vsomeip::byte_t>(i % 256));
its_payload->set_data(its_payload_data);
its_response->set_payload(its_payload);
- app_->send(its_response, true);
+ app_->send(its_response);
if(_request->get_session() == 0x0F) {
std::lock_guard<std::mutex> its_lock(mutex_);
blocked_ = true;
diff --git a/test/magic_cookies_tests/magic_cookies_test_starter.sh b/test/magic_cookies_tests/magic_cookies_test_starter.sh
index 631eef7..c5342fc 100755
--- a/test/magic_cookies_tests/magic_cookies_test_starter.sh
+++ b/test/magic_cookies_tests/magic_cookies_test_starter.sh
@@ -17,9 +17,9 @@ FAIL=0
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting magic cookies test on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./magic_cookies_test_client_start.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./magic_cookies_test_client_start.sh\"" &
elif [ ! -z "$USE_DOCKER" ]; then
- docker run $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./magic_cookies_test_client_start.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./magic_cookies_test_client_start.sh" &
else
cat <<End-of-message
*******************************************************************************
diff --git a/test/malicious_data_tests/conf/malicious_data_test_master.json.in b/test/malicious_data_tests/conf/malicious_data_test_master.json.in
index 066989b..5c2e511 100644
--- a/test/malicious_data_tests/conf/malicious_data_test_master.json.in
+++ b/test/malicious_data_tests/conf/malicious_data_test_master.json.in
@@ -32,7 +32,7 @@
}
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
index 5072632..87bb0d4 100755
--- a/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
+++ b/test/malicious_data_tests/conf/malicious_data_test_master_starter.sh.in
@@ -24,7 +24,7 @@ TESTMODE=$1
export VSOMEIP_CONFIGURATION=malicious_data_test_master.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
./malicious_data_test_service $TESTMODE &
@@ -36,10 +36,12 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./malicious_data_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
else
cat <<End-of-message
*******************************************************************************
@@ -67,10 +69,5 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otems
- docker rm otems
-fi
-
# Check if everything went well
exit $FAIL
diff --git a/test/malicious_data_tests/malicious_data_test_msg_sender.cpp b/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
index 84d09bf..bd9b305 100644
--- a/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
+++ b/test/malicious_data_tests/malicious_data_test_msg_sender.cpp
@@ -92,7 +92,7 @@ TEST_F(malicious_data, send_malicious_events)
vsomeip::sd::message_impl sd_msg;
EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
+ for (const auto& e : sd_msg.get_entries()) {
if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
EXPECT_TRUE(e->is_eventgroup_entry());
EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
@@ -321,7 +321,7 @@ TEST_F(malicious_data, send_wrong_protocol_version)
vsomeip::sd::message_impl sd_msg;
EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
+ for (const auto& e : sd_msg.get_entries()) {
if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
EXPECT_TRUE(e->is_eventgroup_entry());
EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
@@ -543,6 +543,13 @@ TEST_F(malicious_data, send_wrong_protocol_version)
std::size_t bytes_transferred = tcp_socket2.receive(
boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (!error) {
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
+ }
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
std::shared_ptr<vsomeip::message> its_message(its_deserializer.deserialize_message());
EXPECT_EQ(0x3345, its_message->get_service());
@@ -701,7 +708,7 @@ TEST_F(malicious_data, send_wrong_message_type)
vsomeip::sd::message_impl sd_msg;
EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
+ for (const auto& e : sd_msg.get_entries()) {
if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
EXPECT_TRUE(e->is_eventgroup_entry());
EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
@@ -1000,7 +1007,7 @@ TEST_F(malicious_data, send_wrong_return_code)
vsomeip::sd::message_impl sd_msg;
EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
+ for (const auto& e : sd_msg.get_entries()) {
if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
EXPECT_TRUE(e->is_eventgroup_entry());
EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
@@ -1304,7 +1311,7 @@ TEST_F(malicious_data, wrong_header_fields_udp)
vsomeip::sd::message_impl sd_msg;
EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
+ for (const auto& e : sd_msg.get_entries()) {
if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
EXPECT_TRUE(e->is_eventgroup_entry());
EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
@@ -1345,7 +1352,7 @@ TEST_F(malicious_data, wrong_header_fields_udp)
std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
EXPECT_EQ(0u, its_casted_entry->get_minor_version());
}
- for (const auto op : sd_msg.get_options()) {
+ for (const auto& op : sd_msg.get_options()) {
EXPECT_EQ(op->get_type(), vsomeip::sd::option_type_e::IP4_ENDPOINT);
EXPECT_EQ(op->get_length(), 9u);
if (op->get_type() == vsomeip::sd::option_type_e::IP4_ENDPOINT) {
diff --git a/test/malicious_data_tests/malicious_data_test_service.cpp b/test/malicious_data_tests/malicious_data_test_service.cpp
index cc4999e..408ecb3 100644
--- a/test/malicious_data_tests/malicious_data_test_service.cpp
+++ b/test/malicious_data_tests/malicious_data_test_service.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "malicious_data_test_globals.hpp"
@@ -43,7 +43,7 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(_service_info.eventgroup_id);
app_->request_event(service_info_.service_id, service_info_.instance_id,
- service_info_.event_id, its_eventgroups, false);
+ service_info_.event_id, its_eventgroups, vsomeip::event_type_e::ET_EVENT);
app_->register_message_handler(vsomeip::ANY_SERVICE,
vsomeip::ANY_INSTANCE, service_info_.shutdown_method_id,
std::bind(&malicious_data_test_service::on_shutdown_method_called, this,
@@ -62,9 +62,6 @@ public:
app_->request_service(service_info_.service_id, service_info_.instance_id);
app_->subscribe(service_info_.service_id, service_info_.instance_id,
service_info_.eventgroup_id, 0,
- (testmode_ == malicious_data_test::test_mode_e::WRONG_HEADER_FIELDS_UDP) ?
- vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE :
- vsomeip::subscription_type_e::SU_RELIABLE,
service_info_.event_id);
app_->start();
diff --git a/test/npdu_tests/conf/npdu_test_client_no_npdu.json.in b/test/npdu_tests/conf/npdu_test_client_no_npdu.json.in
new file mode 100644
index 0000000..07cfe08
--- /dev/null
+++ b/test/npdu_tests/conf/npdu_test_client_no_npdu.json.in
@@ -0,0 +1,39 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_client_side",
+ "id":"0x6666"
+ },
+ {
+ "name":"npdu_test_client_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"npdu_test_client_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"npdu_test_client_three",
+ "id":"0x3333"
+ },
+ {
+ "name":"npdu_test_client_four",
+ "id":"0x4444"
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_client_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/conf/npdu_test_client_npdu.json.in b/test/npdu_tests/conf/npdu_test_client_npdu.json.in
new file mode 100644
index 0000000..dc35023
--- /dev/null
+++ b/test/npdu_tests/conf/npdu_test_client_npdu.json.in
@@ -0,0 +1,167 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_client_side",
+ "id":"0x6666"
+ },
+ {
+ "name":"npdu_test_client_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"npdu_test_client_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"npdu_test_client_three",
+ "id":"0x3333"
+ },
+ {
+ "name":"npdu_test_client_four",
+ "id":"0x4444"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unicast":"@TEST_IP_MASTER@",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "requests" : {
+ "0x1001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x1002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x1003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x1004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unicast":"@TEST_IP_MASTER@",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "requests" : {
+ "0x2001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x2002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x2003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x2004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unicast":"@TEST_IP_MASTER@",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "requests" : {
+ "0x3001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x3002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x3003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x3004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unicast":"@TEST_IP_MASTER@",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times": {
+ "requests" : {
+ "0x4001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x4002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x4003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x4004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_client_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/conf/npdu_test_service_no_npdu.json.in b/test/npdu_tests/conf/npdu_test_service_no_npdu.json.in
new file mode 100644
index 0000000..b4c8eaa
--- /dev/null
+++ b/test/npdu_tests/conf/npdu_test_service_no_npdu.json.in
@@ -0,0 +1,87 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_service_side",
+ "id":"0x6667"
+ },
+ {
+ "name":"npdu_test_service_one",
+ "id":"0x1000"
+ },
+ {
+ "name":"npdu_test_service_two",
+ "id":"0x2000"
+ },
+ {
+ "name":"npdu_test_service_three",
+ "id":"0x3000"
+ },
+ {
+ "name":"npdu_test_service_four",
+ "id":"0x4000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x6667",
+ "instance":"0x6666",
+ "unreliable":"60666"
+ },
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_service_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/conf/npdu_test_service_npdu.json.in b/test/npdu_tests/conf/npdu_test_service_npdu.json.in
new file mode 100644
index 0000000..0de75cf
--- /dev/null
+++ b/test/npdu_tests/conf/npdu_test_service_npdu.json.in
@@ -0,0 +1,168 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_service_side",
+ "id":"0x6667"
+ },
+ {
+ "name":"npdu_test_service_one",
+ "id":"0x1000"
+ },
+ {
+ "name":"npdu_test_service_two",
+ "id":"0x2000"
+ },
+ {
+ "name":"npdu_test_service_three",
+ "id":"0x3000"
+ },
+ {
+ "name":"npdu_test_service_four",
+ "id":"0x4000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x6667",
+ "instance":"0x6666",
+ "unreliable":"60666"
+ },
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "responses" : {
+ "0x1001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x1002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x1003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x1004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "responses" : {
+ "0x2001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x2002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x2003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x2004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "responses" : {
+ "0x3001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x3002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x3003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x3004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times": {
+ "responses" : {
+ "0x4001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x4002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x4003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x4004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_service_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/npdu_test_client.cpp b/test/npdu_tests/npdu_test_client.cpp
new file mode 100644
index 0000000..ca29aa6
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client.cpp
@@ -0,0 +1,599 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include "../npdu_tests/npdu_test_client.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+#include "../../implementation/configuration/include/configuration.hpp"
+#include "../../implementation/configuration/include/configuration_impl.hpp"
+#include "../../implementation/configuration/include/configuration_plugin.hpp"
+#include "../../implementation/plugin/include/plugin_manager_impl.hpp"
+
+enum class payloadsize
+ : std::uint8_t
+ {
+ UDS, TCP, UDP
+};
+
+// this variables are changed via cmdline parameters
+static bool use_tcp = false;
+static bool call_service_sync = true;
+static bool wait_for_replies = true;
+static std::uint32_t sliding_window_size = vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND;
+static payloadsize max_payload_size = payloadsize::UDS;
+static bool shutdown_service_at_end = true;
+
+npdu_test_client::npdu_test_client(
+ bool _use_tcp,
+ bool _call_service_sync,
+ std::uint32_t _sliding_window_size,
+ bool _wait_for_replies,
+ std::array<std::array<std::chrono::milliseconds, 4>, 4> _applicative_debounce) :
+ app_(vsomeip::runtime::get()->create_application()),
+ request_(vsomeip::runtime::get()->create_request(_use_tcp)),
+ call_service_sync_(_call_service_sync),
+ wait_for_replies_(_wait_for_replies),
+ sliding_window_size_(_sliding_window_size),
+ blocked_({false}),
+ is_available_({false}), // will set first element to false, rest to 0
+ number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND),
+ number_of_sent_messages_{0,0,0,0},
+ number_of_acknowledged_messages_{{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}},
+ current_payload_size_({0}),
+ all_msg_acknowledged_({false, false, false, false}),
+ acknowledgements_{0,0,0,0},
+ applicative_debounce_(_applicative_debounce),
+ finished_waiter_(&npdu_test_client::wait_for_all_senders, this)
+{
+ senders_[0] = std::thread(&npdu_test_client::run<0>, this);
+ senders_[1] = std::thread(&npdu_test_client::run<1>, this);
+ senders_[2] = std::thread(&npdu_test_client::run<2>, this);
+ senders_[3] = std::thread(&npdu_test_client::run<3>, this);
+}
+
+npdu_test_client::~npdu_test_client() {
+ finished_waiter_.join();
+}
+
+void npdu_test_client::init()
+{
+ app_->init();
+
+ app_->register_state_handler(
+ std::bind(&npdu_test_client::on_state, this,
+ std::placeholders::_1));
+
+ register_availability_handler<0>();
+ register_availability_handler<1>();
+ register_availability_handler<2>();
+ register_availability_handler<3>();
+
+ register_message_handler_for_all_service_methods<0>();
+ register_message_handler_for_all_service_methods<1>();
+ register_message_handler_for_all_service_methods<2>();
+ register_message_handler_for_all_service_methods<3>();
+
+ request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
+ request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
+ if(!wait_for_replies_)
+ request_->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+}
+
+template<int service_idx>
+void npdu_test_client::register_availability_handler() {
+ app_->register_availability_handler(npdu_test::service_ids[service_idx],
+ npdu_test::instance_ids[service_idx],
+ std::bind(
+ &npdu_test_client::on_availability<service_idx>,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+}
+
+template<int service_idx>
+void npdu_test_client::register_message_handler_for_all_service_methods() {
+ register_message_handler<service_idx, 0>();
+ register_message_handler<service_idx, 1>();
+ register_message_handler<service_idx, 2>();
+ register_message_handler<service_idx, 3>();
+}
+
+template<int service_idx, int method_idx>
+void npdu_test_client::register_message_handler() {
+ app_->register_message_handler(npdu_test::service_ids[service_idx],
+ npdu_test::instance_ids[service_idx],
+ npdu_test::method_ids[service_idx][method_idx],
+ std::bind(
+ &npdu_test_client::on_message<service_idx, method_idx>,
+ this, std::placeholders::_1));
+}
+
+void npdu_test_client::start()
+{
+ VSOMEIP_INFO << "Starting...";
+ app_->start();
+}
+
+void npdu_test_client::stop()
+{
+ VSOMEIP_INFO << "Stopping...";
+
+ app_->unregister_state_handler();
+
+ for (unsigned int i = 0; i< npdu_test::service_ids.size(); i++) {
+ app_->unregister_availability_handler(npdu_test::service_ids[i],
+ npdu_test::instance_ids[i]);
+
+ for(unsigned int j = 0; j < npdu_test::method_ids[i].size(); j++) {
+ app_->unregister_message_handler(npdu_test::service_ids[i],
+ npdu_test::instance_ids[i],
+ npdu_test::method_ids[i][j]);
+ }
+ }
+
+ if(shutdown_service_at_end) {
+ // notify the routing manager daemon that were finished
+ request_->set_service(npdu_test::RMD_SERVICE_ID_CLIENT_SIDE);
+ request_->set_instance(npdu_test::RMD_INSTANCE_ID);
+ request_->set_method(npdu_test::RMD_SHUTDOWN_METHOD_ID);
+ request_->set_payload(vsomeip::runtime::get()->create_payload());
+ request_->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ app_->send(request_);
+ // sleep otherwise the app will shutdown before the message reaches the rmd
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ }
+ app_->stop();
+}
+
+void npdu_test_client::join_sender_thread() {
+ for (auto& t : senders_) {
+ t.join();
+ }
+}
+
+void npdu_test_client::on_state(vsomeip::state_type_e _state)
+{
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ for (unsigned int i = 0; i< npdu_test::service_ids.size(); i++) {
+ app_->request_service(npdu_test::service_ids[i],
+ npdu_test::instance_ids[i]);
+ }
+ }
+}
+
+template<int service_idx>
+void npdu_test_client::on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance, bool _is_available)
+{
+ VSOMEIP_INFO<< "Service [" << std::setw(4) << std::setfill('0') << std::hex
+ << _service << "." << std::setw(4) << std::setfill('0') << _instance << "] is "
+ << (_is_available ? "available." : "NOT available.");
+ if(npdu_test::service_ids[service_idx] == _service
+ && npdu_test::instance_ids[service_idx] == _instance) {
+ if(is_available_[service_idx] && !_is_available)
+ {
+ is_available_[service_idx] = false;
+ }
+ else if(_is_available && !is_available_[service_idx])
+ {
+ is_available_[service_idx] = true;
+ send<service_idx>();
+ }
+ }
+}
+
+template<int service_idx, int method_idx>
+void npdu_test_client::on_message(const std::shared_ptr<vsomeip::message>& _response) {
+ (void)_response;
+ //TODO make sure the replies were sent within demanded debounce times
+ VSOMEIP_DEBUG << "Received reply from:" << std::setw(4) << std::setfill('0')
+ << std::hex << npdu_test::service_ids[service_idx] << ":"
+ << std::setw(4) << std::setfill('0') << std::hex
+ << npdu_test::instance_ids[service_idx] << ":" << std::setw(4)
+ << std::setfill('0') << std::hex
+ << npdu_test::method_ids[service_idx][method_idx];
+
+ if(call_service_sync_)
+ {
+ // We notify the sender thread every time a message was acknowledged
+ std::lock_guard<std::mutex> lk(all_msg_acknowledged_mutexes_[service_idx][method_idx]);
+ all_msg_acknowledged_[service_idx][method_idx] = true;
+ all_msg_acknowledged_cvs_[service_idx][method_idx].notify_one();
+ }
+ else
+ {
+
+ std::lock_guard<std::mutex> its_lock(number_of_acknowledged_messages_mutexes_[service_idx][method_idx]);
+ number_of_acknowledged_messages_[service_idx][method_idx]++;
+
+ // We notify the sender thread only if all sent messages have been acknowledged
+ if(number_of_acknowledged_messages_[service_idx][method_idx] == number_of_messages_to_send_)
+ {
+ std::lock_guard<std::mutex> lk(all_msg_acknowledged_mutexes_[service_idx][method_idx]);
+ // reset
+ number_of_acknowledged_messages_[service_idx][method_idx] = 0;
+ all_msg_acknowledged_[service_idx][method_idx] = true;
+ all_msg_acknowledged_cvs_[service_idx][method_idx].notify_one();
+ } else if(number_of_acknowledged_messages_[service_idx][method_idx] % sliding_window_size == 0)
+ {
+ std::lock_guard<std::mutex> lk(all_msg_acknowledged_mutexes_[service_idx][method_idx]);
+ all_msg_acknowledged_[service_idx][method_idx] = true;
+ all_msg_acknowledged_cvs_[service_idx][method_idx].notify_one();
+ }
+ }
+}
+
+template<int service_idx>
+void npdu_test_client::send()
+{
+ std::lock_guard<std::mutex> its_lock(mutexes_[service_idx]);
+ blocked_[service_idx] = true;
+ conditions_[service_idx].notify_one();
+}
+
+template<int service_idx>
+void npdu_test_client::run()
+{
+ std::unique_lock<std::mutex> its_lock(mutexes_[service_idx]);
+ while (!blocked_[service_idx])
+ {
+ conditions_[service_idx].wait(its_lock);
+ }
+ current_payload_size_[service_idx] = 1;
+
+ std::uint32_t max_allowed_payload = get_max_allowed_payload();
+
+ for (int var = 0; var < 4; ++var) {
+ payloads_[service_idx][var] = vsomeip::runtime::get()->create_payload();
+ payload_data_[service_idx][var] = std::vector<vsomeip::byte_t>();
+ }
+
+ bool lastrun = false;
+ while (current_payload_size_[service_idx] <= max_allowed_payload)
+ {
+ // prepare the payloads w/ current payloadsize
+ for (int var = 0; var < 4; ++var) {
+ // assign 0x11 to first, 0x22 to second...
+ payload_data_[service_idx][var].assign(
+ current_payload_size_[service_idx], static_cast<vsomeip::byte_t>(0x11 * (var + 1)));
+ payloads_[service_idx][var]->set_data(payload_data_[service_idx][var]);
+ }
+
+ // send the payloads to the service's methods
+ if(wait_for_replies_) {
+ call_service_sync_ ? send_messages_sync<service_idx>() : send_messages_async<service_idx>();
+ } else {
+ send_messages_and_dont_wait_for_reply<service_idx>();
+ }
+
+ // Increase array size for next iteration
+ current_payload_size_[service_idx] *= 2;
+
+ //special case to test the biggest payload possible as last test
+ // 16 Bytes are reserved for the SOME/IP header
+ if(current_payload_size_[service_idx] > max_allowed_payload - 16 && !lastrun)
+ {
+ current_payload_size_[service_idx] = max_allowed_payload - 16;
+ lastrun = true;
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ blocked_[service_idx] = false;
+
+ {
+ std::lock_guard<std::mutex> its_lock(finished_mutex_);
+ finished_[service_idx] = true;
+ }
+}
+
+
+std::uint32_t npdu_test_client::get_max_allowed_payload()
+{
+ std::uint32_t payload;
+ switch (max_payload_size)
+ {
+ case payloadsize::UDS:
+ payload = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE;
+ break;
+ case payloadsize::TCP:
+ payload = 4095;
+ break;
+ case payloadsize::UDP:
+ payload = VSOMEIP_MAX_UDP_MESSAGE_SIZE;
+ break;
+ default:
+ payload = VSOMEIP_MAX_LOCAL_MESSAGE_SIZE;
+ break;
+ }
+ return payload;
+}
+
+template<int service_idx>
+void npdu_test_client::send_messages_sync()
+{
+ std::thread t0 = start_send_thread_sync<service_idx, 0>();
+ std::thread t1 = start_send_thread_sync<service_idx, 1>();
+ std::thread t2 = start_send_thread_sync<service_idx, 2>();
+ std::thread t3 = start_send_thread_sync<service_idx, 3>();
+ t0.join();
+ t1.join();
+ t2.join();
+ t3.join();
+}
+
+template<int service_idx, int method_idx>
+std::thread npdu_test_client::start_send_thread_sync() {
+ return std::thread([&]() {
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx] =
+ std::unique_lock<std::mutex>
+ (all_msg_acknowledged_mutexes_[service_idx][method_idx]);
+
+ std::shared_ptr<vsomeip::message> request = vsomeip::runtime::get()->create_request(use_tcp);
+ request->set_service(npdu_test::service_ids[service_idx]);
+ request->set_instance(npdu_test::instance_ids[service_idx]);
+ request->set_method(npdu_test::method_ids[service_idx][method_idx]);
+ request->set_payload(payloads_[service_idx][method_idx]);
+ for (std::uint32_t i = 0; i < number_of_messages_to_send_; i++)
+ {
+ all_msg_acknowledged_[service_idx][method_idx] = false;
+ app_->send(request);
+
+ std::chrono::high_resolution_clock::time_point sent =
+ std::chrono::high_resolution_clock::now();
+
+ while(!all_msg_acknowledged_[service_idx][method_idx]) {
+ all_msg_acknowledged_cvs_[service_idx][method_idx].wait(
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx]);
+ }
+
+ std::chrono::nanoseconds waited_for_response =
+ std::chrono::high_resolution_clock::now() - sent;
+ if(waited_for_response < applicative_debounce_[service_idx][method_idx]) {
+ // make sure we don't send faster than debounce time + max retention time
+ std::this_thread::sleep_for(
+ applicative_debounce_[service_idx][method_idx]
+ - waited_for_response);
+ }
+ }
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx].unlock();
+ });
+}
+
+template<int service_idx>
+void npdu_test_client::send_messages_async()
+{
+ std::thread t0 = start_send_thread_async<service_idx, 0>();
+ std::thread t1 = start_send_thread_async<service_idx, 1>();
+ std::thread t2 = start_send_thread_async<service_idx, 2>();
+ std::thread t3 = start_send_thread_async<service_idx, 3>();
+ t0.join();
+ t1.join();
+ t2.join();
+ t3.join();
+}
+
+template<int service_idx, int method_idx>
+std::thread npdu_test_client::start_send_thread_async() {
+ return std::thread([&]() {
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx] =
+ std::unique_lock<std::mutex>
+ (all_msg_acknowledged_mutexes_[service_idx][method_idx]);
+ std::shared_ptr<vsomeip::message> request = vsomeip::runtime::get()->create_request(use_tcp);
+ request->set_service(npdu_test::service_ids[service_idx]);
+ request->set_instance(npdu_test::instance_ids[service_idx]);
+ request->set_method(npdu_test::method_ids[service_idx][method_idx]);
+ request->set_payload(payloads_[service_idx][method_idx]);
+ for (std::uint32_t i = 0; i < number_of_messages_to_send_; i++)
+ {
+ app_->send(request);
+
+ if((i+1) == number_of_messages_to_send_ || (i+1) % sliding_window_size == 0) {
+ // wait until all send messages have been acknowledged
+ // as long we wait lk is released; after wait returns lk is reacquired
+ while(!all_msg_acknowledged_[service_idx][method_idx]) {
+ all_msg_acknowledged_cvs_[service_idx][method_idx].wait(
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx]);
+ }
+ // Reset condition variable
+ all_msg_acknowledged_[service_idx][method_idx] = false;
+ }
+ // make sure we don't send faster than debounce time + max retention time
+ std::this_thread::sleep_for(applicative_debounce_[service_idx][method_idx]);
+ }
+ all_msg_acknowledged_unique_locks_[service_idx][method_idx].unlock();
+ });
+}
+
+template<int service_idx>
+void npdu_test_client::send_messages_and_dont_wait_for_reply()
+{
+ std::thread t0 = start_send_thread<service_idx, 0>();
+ std::thread t1 = start_send_thread<service_idx, 1>();
+ std::thread t2 = start_send_thread<service_idx, 2>();
+ std::thread t3 = start_send_thread<service_idx, 3>();
+ t0.join();
+ t1.join();
+ t2.join();
+ t3.join();
+}
+
+template<int service_idx, int method_idx>
+std::thread npdu_test_client::start_send_thread() {
+ return std::thread([&]() {
+ std::shared_ptr<vsomeip::message> request = vsomeip::runtime::get()->create_request(use_tcp);
+ request->set_service(npdu_test::service_ids[service_idx]);
+ request->set_instance(npdu_test::instance_ids[service_idx]);
+ request->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ request->set_method(npdu_test::method_ids[service_idx][method_idx]);
+ request->set_payload(payloads_[service_idx][method_idx]);
+ for (std::uint32_t i = 0; i < number_of_messages_to_send_; i++)
+ {
+ app_->send(request);
+ // make sure we don't send faster than debounce time + max retention time
+ std::this_thread::sleep_for(applicative_debounce_[service_idx][method_idx]);
+ }
+ });
+}
+
+void npdu_test_client::wait_for_all_senders() {
+ bool all_finished(false);
+ while (!all_finished) {
+ {
+ std::lock_guard<std::mutex> its_lock(finished_mutex_);
+ if (std::all_of(finished_.begin(), finished_.end(), [](bool i) { return i; })) {
+ all_finished = true;
+ }
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ join_sender_thread();
+
+ if (!wait_for_replies_ || !call_service_sync_) {
+ // sleep longer here as sending is asynchronously and it's necessary
+ // to wait until all messages have left the application
+ VSOMEIP_INFO << "Sleeping for 180sec since the client is running "
+ "in --dont-wait-for-replies or --async mode. "
+ "Otherwise it might be possible that not all messages leave the "
+ "application.";
+ for(int i = 0; i < 180; i++) {
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ std::cout << ".";
+ std::cout.flush();
+ }
+ } else {
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ }
+ stop();
+}
+
+TEST(someip_npdu_test, send_different_payloads)
+{
+ // get the configuration
+ std::shared_ptr<vsomeip::configuration> its_configuration;
+ auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
+ vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
+ if (its_plugin) {
+ auto its_config_plugin = std::dynamic_pointer_cast<vsomeip::configuration_plugin>(its_plugin);
+ if (its_config_plugin) {
+ its_configuration = its_config_plugin->get_configuration("");
+ }
+ }
+ if (!its_configuration) {
+ ADD_FAILURE() << "No configuration object. "
+ "Either memory overflow or loading error detected!";
+ return;
+ }
+
+ // used to store the debounce times
+ std::array<std::array<std::chrono::milliseconds, 4>, 4> applicative_debounce;
+
+ // query the debouncetimes from the configuration. We want to know the
+ // debounce times which the _clients_ of this service have to comply with
+ // when they send requests to this service.
+ // This is necessary as we must ensure a applicative debouncing greater than
+ // debounce time + maximum retention time. Therefore the send threads sleep
+ // for this amount of time after sending a message.
+ for(int service_id = 0; service_id < 4; service_id++) {
+ for(int method_id = 0; method_id < 4; method_id++) {
+ std::chrono::nanoseconds debounce(0), retention(0);
+ its_configuration->get_configured_timing_requests(
+ npdu_test::service_ids[service_id],
+ its_configuration->get_unicast_address(npdu_test::service_ids[service_id],
+ npdu_test::instance_ids[service_id]),
+ its_configuration->get_unreliable_port(
+ npdu_test::service_ids[service_id],
+ npdu_test::instance_ids[service_id]),
+ npdu_test::method_ids[service_id][method_id],
+ &debounce, &retention);
+ if (debounce == std::chrono::nanoseconds(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO) &&
+ retention == std::chrono::nanoseconds(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO)) {
+ // no timings specified don't don't sleep after sending...
+ applicative_debounce[service_id][method_id] =
+ std::chrono::milliseconds(0);
+ } else {
+ // we add 1 milliseconds to sleep a little bit longer
+ applicative_debounce[service_id][method_id] = std::chrono::duration_cast<
+ std::chrono::milliseconds>(debounce + retention)
+ + std::chrono::milliseconds(1);
+
+ }
+
+ }
+ }
+
+ npdu_test_client test_client_(use_tcp, call_service_sync,
+ sliding_window_size, wait_for_replies,
+ applicative_debounce);
+ test_client_.init();
+ test_client_.start();
+}
+
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ std::string tcp_enable("--TCP");
+ std::string udp_enable("--UDP");
+ std::string sync_enable("--sync");
+ std::string async_enable("--async");
+ std::string no_reply_enable("--dont-wait-for-replies");
+ std::string sliding_window_size_param("--sliding-window-size");
+ std::string max_payload_size_param("--max-payload-size");
+ std::string shutdown_service_disable_param("--dont-shutdown-service");
+ std::string help("--help");
+
+ int i = 1;
+ while (i < argc)
+ {
+ if (tcp_enable == argv[i]) {
+ use_tcp = true;
+ } else if (udp_enable == argv[i]) {
+ use_tcp = false;
+ } else if (sync_enable == argv[i]) {
+ call_service_sync = true;
+ } else if (async_enable == argv[i]) {
+ call_service_sync = false;
+ } else if (no_reply_enable == argv[i]) {
+ wait_for_replies = false;
+ } else if (sliding_window_size_param == argv[i] && i + 1 < argc) {
+ i++;
+ std::stringstream converter(argv[i]);
+ converter >> sliding_window_size;
+ } else if (max_payload_size_param == argv[i] && i + 1 < argc) {
+ i++;
+ if (std::string("UDS") == argv[i]) {
+ max_payload_size = payloadsize::UDS;
+ } else if (std::string("TCP") == argv[i]) {
+ max_payload_size = payloadsize::TCP;
+ } else if (std::string("UDP") == argv[i]) {
+ max_payload_size = payloadsize::UDP;
+ }
+ } else if (shutdown_service_disable_param == argv[i]) {
+ shutdown_service_at_end = false;
+ } else if (help == argv[i]) {
+ VSOMEIP_INFO << "Parameters:\n"
+ << "--TCP: Send messages via TCP\n"
+ << "--UDP: Send messages via UDP (default)\n"
+ << "--sync: Wait for acknowledge before sending next message (default)\n"
+ << "--async: Send multiple messages w/o waiting for"
+ " acknowledge of service\n"
+ << "--dont-wait-for-replies: Just send out the messages w/o waiting for "
+ "a reply by the service (use REQUEST_NO_RETURN message type)\n"
+ << "--sliding-window-size: Number of messages to send before waiting "
+ "for acknowledge of service. Default: " << sliding_window_size << "\n"
+ << "--max-payload-size: limit the maximum payloadsize of send requests. One of {"
+ "UDS (=" << VSOMEIP_MAX_LOCAL_MESSAGE_SIZE << "byte), "
+ "UDP (=" << VSOMEIP_MAX_UDP_MESSAGE_SIZE << "byte), "
+ "TCP (=" << VSOMEIP_MAX_TCP_MESSAGE_SIZE << "byte)}, default: UDS\n"
+ << "--dont-shutdown-service: Don't shutdown the service upon "
+ "finishing of the payload test\n"
+ << "--help: print this help";
+ }
+ i++;
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/npdu_tests/npdu_test_client.hpp b/test/npdu_tests/npdu_test_client.hpp
new file mode 100644
index 0000000..980c16a
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client.hpp
@@ -0,0 +1,103 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef PAYLOADTESTCLIENT_HPP_
+#define NPDUTESTCLIENT_HPP_
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <functional>
+#include <map>
+
+#include "../npdu_tests/npdu_test_globals.hpp"
+#include "../someip_test_globals.hpp"
+
+class npdu_test_client
+{
+public:
+ npdu_test_client(bool _use_tcp, bool _call_service_sync,
+ std::uint32_t _sliding_window_size,
+ bool _wait_for_replies,
+ std::array<std::array<std::chrono::milliseconds, 4>, 4> _applicative_debounce);
+ ~npdu_test_client();
+ void init();
+ void start();
+ void stop();
+ void join_sender_thread();
+ void on_state(vsomeip::state_type_e _state);
+ template<int service_idx> void on_availability(vsomeip::service_t _service,
+ vsomeip::instance_t _instance,
+ bool _is_available);
+ template<int service_idx, int method_idx> void on_message(
+ const std::shared_ptr<vsomeip::message> &_response);
+ template<int service_idx> void send();
+ template<int service_idx> void run();
+
+private:
+ template<int service_idx> void send_messages_sync();
+ template<int service_idx, int method_idx> std::thread start_send_thread_sync();
+ template<int service_idx> void send_messages_async();
+ template<int service_idx, int method_idx> std::thread start_send_thread_async();
+ template<int service_idx> void send_messages_and_dont_wait_for_reply();
+ std::uint32_t get_max_allowed_payload();
+ template<int service_idx> void register_availability_handler();
+ template<int service_idx> void register_message_handler_for_all_service_methods();
+ template<int service_idx, int method_idx> void register_message_handler();
+ template<int service_idx, int method_idx>
+ std::thread start_send_thread();
+ void wait_for_all_senders();
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ std::shared_ptr<vsomeip::message> request_;
+ bool call_service_sync_;
+ bool wait_for_replies_;
+ std::uint32_t sliding_window_size_;
+
+ std::array<std::mutex, npdu_test::service_ids.size()> mutexes_;
+ std::array<std::condition_variable, npdu_test::service_ids.size()> conditions_;
+ std::array<bool, npdu_test::service_ids.size()> blocked_;
+ std::array<bool, npdu_test::service_ids.size()> is_available_;
+ const std::uint32_t number_of_messages_to_send_;
+ std::uint32_t number_of_sent_messages_[npdu_test::service_ids.size()];
+ std::array<std::array<std::uint32_t, npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> number_of_acknowledged_messages_;
+ std::array<std::array<std::mutex, npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> number_of_acknowledged_messages_mutexes_;
+
+ std::array<std::uint32_t, npdu_test::service_ids.size()> current_payload_size_;
+
+ std::array<std::array<bool, npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> all_msg_acknowledged_;
+ std::array<std::array<std::mutex, npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> all_msg_acknowledged_mutexes_;
+ std::array<std::array<std::unique_lock<std::mutex>, npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> all_msg_acknowledged_unique_locks_;
+ std::array<
+ std::array<std::condition_variable,
+ npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> all_msg_acknowledged_cvs_;
+ std::array<std::uint32_t, 4> acknowledgements_;
+ std::array<std::array<std::chrono::milliseconds, 4>, 4> applicative_debounce_;
+ std::array<
+ std::array<std::shared_ptr<vsomeip::payload>,
+ npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> payloads_;
+ std::array<
+ std::array<std::vector<vsomeip::byte_t>,
+ npdu_test::method_ids[0].size()>,
+ npdu_test::service_ids.size()> payload_data_;
+ std::array<std::thread, npdu_test::service_ids.size()> senders_;
+ std::mutex finished_mutex_;
+ std::array<bool, npdu_test::service_ids.size()> finished_;
+ std::thread finished_waiter_;
+};
+
+#endif /* NPDUTESTCLIENT_HPP_ */
diff --git a/test/npdu_tests/npdu_test_client_no_npdu.json b/test/npdu_tests/npdu_test_client_no_npdu.json
new file mode 100644
index 0000000..6fb942f
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client_no_npdu.json
@@ -0,0 +1,39 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_client_side",
+ "id":"0x6666"
+ },
+ {
+ "name":"npdu_test_client_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"npdu_test_client_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"npdu_test_client_three",
+ "id":"0x3333"
+ },
+ {
+ "name":"npdu_test_client_four",
+ "id":"0x4444"
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_client_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/npdu_test_client_no_npdu_start.sh b/test/npdu_tests/npdu_test_client_no_npdu_start.sh
new file mode 100755
index 0000000..bc84421
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client_no_npdu_start.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the routing manager daemon and the
+# clients with one command. This is necessary as ctest - which is used to run
+# the tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the routing
+# manager daemon and the clients and checks if all of them exit successfully.
+
+FAIL=0
+
+if [ $# -lt 2 ]; then
+ echo "Error: Please pass a protocol and communication mode to this script."
+ echo "Valid protocols are [UDP,TCP]."
+ echo "Valid communication modes are [sync, async]."
+ echo "For example $> $0 UDP sync"
+ exit 1;
+fi
+
+FAIL=0
+PROTOCOL=$1
+COMMUNICATION_MODE=$2
+
+start_clients(){
+ export VSOMEIP_CONFIGURATION=npdu_test_client_no_npdu.json
+
+ # Start the routing manager daemon
+ export VSOMEIP_APPLICATION_NAME=npdu_test_routing_manager_daemon_client_side
+ ./npdu_test_rmd_client_side &
+
+ # sleep 1 second to let the RMD startup.
+ sleep 1
+ # Start client 1
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_one
+ ./npdu_test_client_1 $* &
+
+ # Start client 2
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_two
+ ./npdu_test_client_2 $* &
+
+ # Start client 3
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_three
+ ./npdu_test_client_3 $* &
+
+ # Start client 4
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_four
+ ./npdu_test_client_4 $* &
+}
+
+wait_for_bg_processes(){
+ # Wait until client and service are finished
+ for job in $(jobs -p)
+ do
+ # Fail gets incremented if one of the jobs exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+ done
+
+ # Check if everything exited successfully
+ if [ $FAIL -eq 0 ]
+ then
+ echo "All clients exited successfully"
+ else
+ echo "Something went wrong"
+ exit 1
+ fi
+}
+
+if [ $# -eq 0 ]
+then
+ echo "Error: Please pass a mode to this script: UDP or TCP."
+ echo "For example $> $0 UDP"
+fi
+
+echo "Contacting services via $PROTOCOL"
+start_clients --$PROTOCOL --max-payload-size $PROTOCOL --$COMMUNICATION_MODE
+wait_for_bg_processes
+
+exit 0
diff --git a/test/npdu_tests/npdu_test_client_npdu.json b/test/npdu_tests/npdu_test_client_npdu.json
new file mode 100644
index 0000000..569d426
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client_npdu.json
@@ -0,0 +1,167 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_client_side",
+ "id":"0x6666"
+ },
+ {
+ "name":"npdu_test_client_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"npdu_test_client_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"npdu_test_client_three",
+ "id":"0x3333"
+ },
+ {
+ "name":"npdu_test_client_four",
+ "id":"0x4444"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unicast":"10.0.3.1",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "requests" : {
+ "0x1001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x1002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x1003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x1004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unicast":"10.0.3.1",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "requests" : {
+ "0x2001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x2002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x2003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x2004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unicast":"10.0.3.1",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "requests" : {
+ "0x3001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x3002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x3003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x3004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unicast":"10.0.3.1",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times": {
+ "requests" : {
+ "0x4001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x4002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x4003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x4004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_client_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/npdu_test_client_npdu_start.sh b/test/npdu_tests/npdu_test_client_npdu_start.sh
new file mode 100755
index 0000000..70b6c53
--- /dev/null
+++ b/test/npdu_tests/npdu_test_client_npdu_start.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the routing manager daemon and the
+# clients with one command. This is necessary as ctest - which is used to run
+# the tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the routing
+# manager daemon and the clients and checks if all of them exit successfully.
+
+if [ $# -lt 2 ]; then
+ echo "Error: Please pass a protocol and communication mode to this script."
+ echo "Valid protocols are [UDP,TCP]."
+ echo "Valid communication modes are [sync, async]."
+ echo "For example $> $0 UDP sync"
+ exit 1;
+fi
+
+FAIL=0
+PROTOCOL=$1
+COMMUNICATION_MODE=$2
+
+start_clients(){
+ export VSOMEIP_CONFIGURATION=npdu_test_client_npdu.json
+
+ # Start the routing manager daemon
+ export VSOMEIP_APPLICATION_NAME=npdu_test_routing_manager_daemon_client_side
+ ./npdu_test_rmd_client_side &
+
+ # sleep 1 second to let the RMD startup.
+ sleep 1
+ # Start client 1
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_one
+ ./npdu_test_client_1 $* &
+
+ # Start client 2
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_two
+ ./npdu_test_client_2 $* &
+
+ # Start client 3
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_three
+ ./npdu_test_client_3 $* &
+
+ # Start client 4
+ export VSOMEIP_APPLICATION_NAME=npdu_test_client_four
+ ./npdu_test_client_4 $* &
+}
+
+wait_for_bg_processes(){
+ # Wait until client and service are finished
+ for job in $(jobs -p)
+ do
+ # Fail gets incremented if one of the jobs exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+ done
+
+ # Check if everything exited successfully
+ if [ $FAIL -eq 0 ]
+ then
+ echo "All clients exited successfully"
+ else
+ echo "Something went wrong"
+ exit 1
+ fi
+}
+
+
+echo "Contacting services via $PROTOCOL"
+start_clients --$PROTOCOL --max-payload-size $PROTOCOL --$COMMUNICATION_MODE
+wait_for_bg_processes
+
+exit 0
diff --git a/test/npdu_tests/npdu_test_globals.hpp b/test/npdu_tests/npdu_test_globals.hpp
new file mode 100644
index 0000000..8cee3ee
--- /dev/null
+++ b/test/npdu_tests/npdu_test_globals.hpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef NPDU_TESTS_NPDU_TEST_GLOBALS_HPP_
+#define NPDU_TESTS_NPDU_TEST_GLOBALS_HPP_
+
+namespace npdu_test {
+
+// Routing manager daemon
+constexpr vsomeip::client_t RMD_CLIENT_ID_CLIENT_SIDE = 0x6666;
+constexpr vsomeip::service_t RMD_SERVICE_ID_CLIENT_SIDE = 0x6666;
+
+constexpr vsomeip::client_t RMD_CLIENT_ID_SERVICE_SIDE = 0x6667;
+constexpr vsomeip::service_t RMD_SERVICE_ID_SERVICE_SIDE = 0x6667;
+
+constexpr vsomeip::instance_t RMD_INSTANCE_ID = 0x6666;
+constexpr vsomeip::method_t RMD_SHUTDOWN_METHOD_ID = 0x6666;
+
+
+
+constexpr vsomeip::method_t NPDU_SERVICE_SHUTDOWNMETHOD_ID = 0x7777;
+
+constexpr std::array<vsomeip::service_t, 4> service_ids =
+ { 0x1000, 0x2000, 0x3000, 0x4000 };
+constexpr std::array<vsomeip::instance_t, 4> instance_ids =
+ { service_ids[0] >> 12,
+ service_ids[1] >> 12,
+ service_ids[2] >> 12,
+ service_ids[3] >> 12 };
+constexpr std::array<std::array<vsomeip::method_t, 4>, 4> method_ids = {{
+ { service_ids[0]+1, service_ids[0]+2 ,service_ids[0]+3 ,service_ids[0]+4 },
+ { service_ids[1]+1, service_ids[1]+2 ,service_ids[1]+3 ,service_ids[1]+4 },
+ { service_ids[2]+1, service_ids[2]+2 ,service_ids[2]+3 ,service_ids[2]+4 },
+ { service_ids[3]+1, service_ids[3]+2 ,service_ids[3]+3 ,service_ids[3]+4 }
+}};
+
+constexpr std::array<vsomeip::client_t, 4> client_ids_clients =
+ { 0x1111, 0x2222, 0x3333, 0x4444 };
+
+constexpr std::array<vsomeip::client_t, 4> client_ids_services = service_ids;
+
+}
+#endif /* NPDU_TESTS_NPDU_TEST_GLOBALS_HPP_ */
diff --git a/test/npdu_tests/npdu_test_rmd.cpp b/test/npdu_tests/npdu_test_rmd.cpp
new file mode 100644
index 0000000..1174a91
--- /dev/null
+++ b/test/npdu_tests/npdu_test_rmd.cpp
@@ -0,0 +1,160 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <atomic>
+
+#include "../npdu_tests/npdu_test_rmd.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+#include "npdu_test_globals.hpp"
+
+#include "../npdu_tests/npdu_test_globals.hpp"
+
+npdu_test_rmd::npdu_test_rmd() :
+ app_(vsomeip::runtime::get()->create_application()),
+ is_registered_(false),
+ blocked_(false),
+ offer_thread_(std::bind(&npdu_test_rmd::run, this))
+{
+ // TODO Auto-generated constructor stub
+}
+
+void npdu_test_rmd::init() {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ app_->init();
+
+#ifdef RMD_CLIENT_SIDE
+ app_->register_message_handler(npdu_test::RMD_SERVICE_ID_CLIENT_SIDE,
+#elif defined (RMD_SERVICE_SIDE)
+ app_->register_message_handler(npdu_test::RMD_SERVICE_ID_SERVICE_SIDE,
+#endif
+ npdu_test::RMD_INSTANCE_ID, npdu_test::RMD_SHUTDOWN_METHOD_ID,
+ std::bind(&npdu_test_rmd::on_message_shutdown,
+ this, std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&npdu_test_rmd::on_state, this,
+ std::placeholders::_1));
+}
+
+void npdu_test_rmd::start() {
+ VSOMEIP_INFO << "Starting...";
+ app_->start();
+}
+
+void npdu_test_rmd::stop() {
+ VSOMEIP_INFO << "Stopping...";
+
+ app_->unregister_message_handler(npdu_test::RMD_SERVICE_ID_CLIENT_SIDE,
+ npdu_test::RMD_INSTANCE_ID, npdu_test::RMD_SHUTDOWN_METHOD_ID);
+ app_->unregister_state_handler();
+ offer_thread_.join();
+ app_->stop();
+}
+
+void npdu_test_rmd::on_state(
+ vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." :
+ "deregistered.");
+
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ if(!is_registered_)
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_registered_ = true;
+ blocked_ = true;
+ // "start" the run method thread
+ condition_.notify_one();
+ }
+ }
+ else
+ {
+ is_registered_ = false;
+ }
+}
+
+void npdu_test_rmd::on_message_shutdown(
+ const std::shared_ptr<vsomeip::message>& _request) {
+ (void)_request;
+ std::shared_ptr<vsomeip::message> request = vsomeip::runtime::get()->create_request(false);
+#ifdef RMD_CLIENT_SIDE
+ static int counter = 0;
+ counter++;
+ VSOMEIP_INFO << counter << " of " << npdu_test::client_ids_clients.size()
+ << " clients are finished.";
+
+ if (counter == npdu_test::client_ids_clients.size()) {
+ VSOMEIP_INFO << "All clients are finished, notify routing manager daemon on service side.";
+ // notify the RMD_SERVICE_SIDE that he can shutdown as well
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ request->set_service(npdu_test::RMD_SERVICE_ID_SERVICE_SIDE);
+ request->set_instance(npdu_test::RMD_INSTANCE_ID);
+ request->set_method(npdu_test::RMD_SHUTDOWN_METHOD_ID);
+ request->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ app_->send(request);
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ stop();
+ }
+#elif defined RMD_SERVICE_SIDE
+ VSOMEIP_INFO << "All clients are finished shutting down services";
+ // shutdown all services
+ for(unsigned int i = 0; i < npdu_test::service_ids.size(); i++) {
+ request->set_service(npdu_test::service_ids[i]);
+ request->set_instance(npdu_test::instance_ids[i]);
+ request->set_method(npdu_test::NPDU_SERVICE_SHUTDOWNMETHOD_ID);
+ request->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ app_->send(request);
+ }
+ app_->stop_offer_service(npdu_test::RMD_SERVICE_ID_SERVICE_SIDE, npdu_test::RMD_INSTANCE_ID);
+
+ VSOMEIP_INFO << "Wait a few seconds until all services are shutdown.";
+ std::atomic<bool> finished(false);
+ for (int i = 0; !finished && i < 20; i++) {
+ app_->get_offered_services_async(
+ vsomeip::offer_type_e::OT_REMOTE,
+ [&](const std::vector<std::pair<vsomeip::service_t,
+ vsomeip::instance_t>> &_services){
+ if (_services.empty()) {
+ finished = true;
+ }
+ });
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ stop();
+#endif
+}
+
+void npdu_test_rmd::join_shutdown_thread() {
+ shutdown_thread_.join();
+}
+
+void npdu_test_rmd::run() {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!blocked_)
+ condition_.wait(its_lock);
+#ifdef RMD_CLIENT_SIDE
+ app_->offer_service(npdu_test::RMD_SERVICE_ID_CLIENT_SIDE, npdu_test::RMD_INSTANCE_ID);
+#elif defined (RMD_SERVICE_SIDE)
+ app_->offer_service(npdu_test::RMD_SERVICE_ID_SERVICE_SIDE, npdu_test::RMD_INSTANCE_ID);
+#endif
+}
+
+TEST(someip_npdu_test, offer_routing_manager_functionality)
+{
+ npdu_test_rmd daemon;
+ daemon.init();
+ daemon.start();
+}
+
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+
diff --git a/test/security_config_plugin_tests/security_config_plugin_test_service.hpp b/test/npdu_tests/npdu_test_rmd.hpp
index eb43957..0b1e28d 100644
--- a/test/security_config_plugin_tests/security_config_plugin_test_service.hpp
+++ b/test/npdu_tests/npdu_test_rmd.hpp
@@ -1,34 +1,30 @@
-// Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef SECURITY_CONFIG_PLUGIN_TEST_SERVICE_HPP
-#define SECURITY_CONFIG_PLUGIN_TEST_SERVICE_HPP
+#ifndef NPDU_TESTS_NPDUTESTROUTINGMANAGERDAEMON_HPP_
+#define NPDU_TESTS_NPDUTESTROUTINGMANAGERDAEMON_HPP_
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../someip_test_globals.hpp"
-
#include <thread>
#include <mutex>
#include <condition_variable>
+#include <functional>
+
+class npdu_test_rmd {
-class security_config_plugin_test_service {
public:
- security_config_plugin_test_service();
- bool init();
+ npdu_test_rmd();
+ void init();
void start();
void stop();
- void offer();
- void stop_offer();
- void join_offer_thread();
void on_state(vsomeip::state_type_e _state);
- void on_message(const std::shared_ptr<vsomeip::message> &_request);
void on_message_shutdown(const std::shared_ptr<vsomeip::message> &_request);
- void on_message_try_offer(const std::shared_ptr<vsomeip::message> &_request);
+ void join_shutdown_thread();
void run();
private:
@@ -36,10 +32,14 @@ private:
bool is_registered_;
std::mutex mutex_;
+ std::mutex mutex2_;
std::condition_variable condition_;
+ std::condition_variable condition2_;
bool blocked_;
- std::uint32_t number_of_received_messages_;
+ bool blocked2_;
std::thread offer_thread_;
+ std::thread shutdown_thread_;
+
};
-#endif // SECURITY_CONFIG_PLUGIN_TEST_SERVICE_HPP
+#endif /* NPDU_TESTS_NPDUTESTROUTINGMANAGERDAEMON_HPP_ */
diff --git a/test/npdu_tests/npdu_test_service.cpp b/test/npdu_tests/npdu_test_service.cpp
new file mode 100644
index 0000000..901084b
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service.cpp
@@ -0,0 +1,306 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "../npdu_tests/npdu_test_service.hpp"
+#include "../npdu_tests/npdu_test_globals.hpp"
+
+#include <vsomeip/internal/logger.hpp>
+#include "../../implementation/configuration/include/configuration.hpp"
+#include "../../implementation/configuration/include/configuration_impl.hpp"
+#include "../../implementation/configuration/include/configuration_plugin.hpp"
+#include "../../implementation/plugin/include/plugin_manager_impl.hpp"
+
+
+
+// this variable is set during compile time to create 4 service binaries of
+// which each of them offers a service.
+// Based on this number the service id, instance id and method ids are
+// selected from the arrays defined in npdu_test_globals.hpp
+#ifndef SERVICE_NUMBER
+#define SERVICE_NUMBER 0
+#endif
+
+npdu_test_service::npdu_test_service(vsomeip::service_t _service_id,
+ vsomeip::instance_t _instance_id,
+ std::array<vsomeip::method_t, 4> _method_ids,
+ std::array<std::chrono::nanoseconds, 4> _debounce_times,
+ std::array<std::chrono::nanoseconds, 4> _max_retention_times) :
+ app_(vsomeip::runtime::get()->create_application()),
+ is_registered_(false),
+ method_ids_(_method_ids),
+ debounce_times_(_debounce_times),
+ max_retention_times_(_max_retention_times),
+ service_id_(_service_id),
+ instance_id_(_instance_id),
+ blocked_(false),
+ allowed_to_shutdown_(false),
+ number_of_received_messages_(0),
+ offer_thread_(std::bind(&npdu_test_service::run, this)),
+ shutdown_thread_(std::bind(&npdu_test_service::stop, this))
+{
+ // init timepoints of last received message to one hour before now.
+ // needed that the first message which arrives isn't registered as undershot
+ // debounce time
+ for(auto &tp : timepoint_last_received_message_) {
+ tp = std::chrono::steady_clock::now() - std::chrono::hours(1);
+ }
+}
+
+void npdu_test_service::init()
+{
+ std::lock_guard<std::mutex> its_lock(mutex_);
+
+ app_->init();
+
+ register_message_handler<0>();
+ register_message_handler<1>();
+ register_message_handler<2>();
+ register_message_handler<3>();
+
+ app_->register_message_handler(service_id_, instance_id_,
+ npdu_test::NPDU_SERVICE_SHUTDOWNMETHOD_ID,
+ std::bind(&npdu_test_service::on_message_shutdown, this,
+ std::placeholders::_1));
+
+ app_->register_state_handler(
+ std::bind(&npdu_test_service::on_state, this,
+ std::placeholders::_1));
+}
+
+template <int method_idx>
+void npdu_test_service::register_message_handler() {
+ app_->register_message_handler(service_id_, instance_id_, method_ids_[method_idx],
+ std::bind(&npdu_test_service::on_message<method_idx>, this,
+ std::placeholders::_1));
+}
+
+void npdu_test_service::start()
+{
+ VSOMEIP_INFO << "Starting...";
+ app_->start();
+}
+
+void npdu_test_service::stop()
+{
+ std::unique_lock<std::mutex> its_lock(shutdown_mutex_);
+ while (!allowed_to_shutdown_) {
+ shutdown_condition_.wait(its_lock);
+ }
+
+ VSOMEIP_INFO << "Stopping...";
+ if (!undershot_debounce_times_.empty()) {
+ std::chrono::microseconds sum(0);
+ for (const auto t : undershot_debounce_times_) {
+ sum += t;
+ }
+ double average = static_cast<double>(sum.count())/static_cast<double>(undershot_debounce_times_.size());
+ VSOMEIP_INFO << "["
+ << std::setw(4) << std::setfill('0') << std::hex << service_id_ << "."
+ << std::setw(4) << std::setfill('0') << std::hex << instance_id_ << "]: "
+ << " Debounce time was undershot " << std::dec << undershot_debounce_times_.size() << "/" << number_of_received_messages_
+ << "(" << std::setprecision(2) << (static_cast<double>(undershot_debounce_times_.size()) / static_cast<double>(number_of_received_messages_)) * 100.00
+ << "%) on average: " << std::setprecision(4) << average << "µs";
+ }
+ app_->unregister_message_handler(service_id_, instance_id_, method_ids_[0]);
+ app_->unregister_message_handler(service_id_, instance_id_, method_ids_[1]);
+ app_->unregister_message_handler(service_id_, instance_id_, method_ids_[2]);
+ app_->unregister_message_handler(service_id_, instance_id_, method_ids_[3]);
+ app_->unregister_message_handler(service_id_,
+ instance_id_, npdu_test::NPDU_SERVICE_SHUTDOWNMETHOD_ID);
+ app_->unregister_state_handler();
+ offer_thread_.join();
+ stop_offer();
+ app_->stop();
+}
+
+void npdu_test_service::offer()
+{
+ app_->offer_service(service_id_, instance_id_);
+}
+
+void npdu_test_service::stop_offer()
+{
+ app_->stop_offer_service(service_id_, instance_id_);
+}
+
+void npdu_test_service::join_shutdown_thread() {
+ shutdown_thread_.join();
+}
+
+void npdu_test_service::on_state(vsomeip::state_type_e _state)
+{
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." :
+ "deregistered.");
+
+ if(_state == vsomeip::state_type_e::ST_REGISTERED)
+ {
+ if(!is_registered_)
+ {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ is_registered_ = true;
+ blocked_ = true;
+ // "start" the run method thread
+ condition_.notify_one();
+ }
+ }
+ else
+ {
+ is_registered_ = false;
+ }
+}
+
+template<int method_idx>
+void npdu_test_service::check_times() {
+ std::lock_guard<std::mutex> its_lock(timepoint_mutexes_[method_idx]);
+ // what time is it?
+ std::chrono::steady_clock::time_point now =
+ std::chrono::steady_clock::now();
+ // how long is it since we received the last message?
+ std::chrono::nanoseconds time_since_last_message =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ now - timepoint_last_received_message_[method_idx]);
+ // store the current time
+ timepoint_last_received_message_[method_idx] = now;
+
+ // check if the debounce time was undershot
+ if (time_since_last_message < debounce_times_[method_idx]) {
+ const auto time_undershot = std::chrono::duration_cast<
+ std::chrono::microseconds>(debounce_times_[method_idx] - time_since_last_message);
+ undershot_debounce_times_.push_back(time_undershot);
+ }
+ // check if maximum retention time was exceeded
+ // Disabled as it can't be guaranteed that exact every max retention time a
+ // message leaves the client endpoint.
+#if 0
+ if(time_since_last_message > max_retention_times_[method_idx]) {
+ VSOMEIP_ERROR << std::setw(4) << std::setfill('0') << std::hex
+ << service_id_ << ":" << std::setw(4) << std::setfill('0')
+ << std::hex << instance_id_ << ":" << std::setw(4) << std::setfill('0')
+ << std::hex << npdu_test::method_ids[SERVICE_NUMBER][method_idx]
+ << ": max_retention_time exceeded by: " << std::dec
+ << std::chrono::duration_cast<std::chrono::milliseconds>(
+ time_since_last_message - max_retention_times_[method_idx]).count()
+ << "ms";
+ GTEST_FATAL_FAILURE_("Max retention time was exceeded");
+ }
+#endif
+}
+
+template<int method_idx>
+void npdu_test_service::on_message(const std::shared_ptr<vsomeip::message>& _request)
+{
+ number_of_received_messages_++;
+ check_times<method_idx>();
+ VSOMEIP_DEBUG << __func__ << " 0x" << std::setw(4) << std::setfill('0') << std::hex
+ << method_ids_[method_idx] << " payload size: "
+ << std::dec << _request->get_payload()->get_length();
+ if(_request->get_message_type() != vsomeip::message_type_e::MT_REQUEST_NO_RETURN) {
+ std::shared_ptr<vsomeip::message> its_response =
+ vsomeip::runtime::get()->create_response(_request);
+ app_->send(its_response);
+ }
+}
+
+void npdu_test_service::on_message_shutdown(
+ const std::shared_ptr<vsomeip::message>& _request)
+{
+ (void)_request;
+ VSOMEIP_DEBUG << "Number of received messages: " << number_of_received_messages_;
+ VSOMEIP_INFO << "Shutdown method was called, going down now.";
+
+ std::lock_guard<std::mutex> its_lock(shutdown_mutex_);
+ allowed_to_shutdown_ = true;
+ shutdown_condition_.notify_one();
+}
+
+void npdu_test_service::run()
+{
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (!blocked_)
+ condition_.wait(its_lock);
+
+ offer();
+}
+
+TEST(someip_npdu_test, offer_service_and_check_debounce_times)
+{
+ // get the configuration
+ std::shared_ptr<vsomeip::configuration> its_configuration;
+ auto its_plugin = vsomeip::plugin_manager::get()->get_plugin(
+ vsomeip::plugin_type_e::CONFIGURATION_PLUGIN, VSOMEIP_CFG_LIBRARY);
+ if (its_plugin) {
+ auto its_config_plugin = std::dynamic_pointer_cast<vsomeip::configuration_plugin>(its_plugin);
+ if (its_config_plugin) {
+ its_configuration = its_config_plugin->get_configuration("");
+ }
+ }
+ if (!its_configuration) {
+ ADD_FAILURE() << "No configuration object. "
+ "Either memory overflow or loading error detected!";
+ return;
+ }
+
+ // used to store the debounce times
+ std::array<std::chrono::nanoseconds, 4> debounce_times;
+ std::array<std::chrono::nanoseconds, 4> max_retention_times;
+
+
+ // query the debouncetimes from the configuration. We want to know the
+ // debounce times which the _clients_ of this service have to comply with
+ // when they send requests to this service. This is necessary as we want to
+ // check on the service side if they adhere to them.
+ // client one will only query method one, client two will only query method
+ // two and so on.
+ for(int i = 0; i < 4; i++) {
+ std::chrono::nanoseconds debounce(0), retention(0);
+ its_configuration->get_configured_timing_requests(
+ npdu_test::service_ids[SERVICE_NUMBER],
+ its_configuration->get_unicast_address().to_string(),
+ its_configuration->get_unreliable_port(
+ npdu_test::service_ids[SERVICE_NUMBER],
+ npdu_test::instance_ids[SERVICE_NUMBER]),
+ npdu_test::method_ids[SERVICE_NUMBER][i],
+ &debounce_times[i],
+ &max_retention_times[i]);
+ if (debounce == std::chrono::nanoseconds(VSOMEIP_DEFAULT_NPDU_DEBOUNCING_NANO) &&
+ retention == std::chrono::nanoseconds(VSOMEIP_DEFAULT_NPDU_MAXIMUM_RETENTION_NANO)) {
+ // no timings specified - checks in check_times() should never
+ // report an error in this case.
+ // set debounce time to 0 this can't be undershot
+ debounce_times[i] = std::chrono::nanoseconds(0);
+ // set max retention time its max, this won't be exceeded
+ max_retention_times[i] = std::chrono::nanoseconds::max();
+ }
+ }
+
+ npdu_test_service test_service(
+ npdu_test::service_ids[SERVICE_NUMBER],
+ npdu_test::instance_ids[SERVICE_NUMBER],
+ npdu_test::method_ids[SERVICE_NUMBER],
+ debounce_times, max_retention_times);
+ test_service.init();
+ test_service.start();
+ test_service.join_shutdown_thread();
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ int i = 1;
+ while (i < argc)
+ {
+ if(std::string("--help") == argv[i])
+ {
+ VSOMEIP_INFO << "Parameters:\n"
+ << "--help: print this help";
+ }
+ i++;
+ }
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/npdu_tests/npdu_test_service.hpp b/test/npdu_tests/npdu_test_service.hpp
new file mode 100644
index 0000000..bef0680
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service.hpp
@@ -0,0 +1,64 @@
+// Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef NPDUTESTSERVICE_HPP_
+#define NPDUTESTSERVICE_HPP_
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <functional>
+#include <chrono>
+#include <deque>
+
+class npdu_test_service
+{
+public:
+ npdu_test_service(vsomeip::service_t _service_id,
+ vsomeip::instance_t _instance_id,
+ std::array<vsomeip::method_t, 4> _method_ids,
+ std::array<std::chrono::nanoseconds, 4> _debounce_times,
+ std::array<std::chrono::nanoseconds, 4> _max_retention_times);
+ void init();
+ void start();
+ void stop();
+ void offer();
+ void stop_offer();
+ void join_shutdown_thread();
+ void on_state(vsomeip::state_type_e _state);
+ template<int method_idx> void on_message(const std::shared_ptr<vsomeip::message> &_request);
+ void on_message_shutdown(const std::shared_ptr<vsomeip::message> &_request);
+ void run();
+
+private:
+ template<int method_idx> void check_times();
+ template <int method_idx> void register_message_handler();
+
+private:
+ std::shared_ptr<vsomeip::application> app_;
+ bool is_registered_;
+ std::array<vsomeip::method_t, 4> method_ids_;
+ std::array<std::chrono::nanoseconds, 4> debounce_times_;
+ std::array<std::chrono::nanoseconds, 4> max_retention_times_;
+ std::array<std::chrono::steady_clock::time_point, 4> timepoint_last_received_message_;
+ std::array<std::mutex, 4> timepoint_mutexes_;
+ std::deque<std::chrono::microseconds> undershot_debounce_times_;
+ vsomeip::service_t service_id_;
+ vsomeip::instance_t instance_id_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ bool blocked_;
+ std::mutex shutdown_mutex_;
+ std::condition_variable shutdown_condition_;
+ bool allowed_to_shutdown_;
+ std::uint32_t number_of_received_messages_;
+ std::thread offer_thread_;
+ std::thread shutdown_thread_;
+};
+
+#endif /* NPDUTESTSERVICE_HPP_ */
diff --git a/test/npdu_tests/npdu_test_service_no_npdu.json b/test/npdu_tests/npdu_test_service_no_npdu.json
new file mode 100644
index 0000000..642db48
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service_no_npdu.json
@@ -0,0 +1,87 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_service_side",
+ "id":"0x6667"
+ },
+ {
+ "name":"npdu_test_service_one",
+ "id":"0x1000"
+ },
+ {
+ "name":"npdu_test_service_two",
+ "id":"0x2000"
+ },
+ {
+ "name":"npdu_test_service_three",
+ "id":"0x3000"
+ },
+ {
+ "name":"npdu_test_service_four",
+ "id":"0x4000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x6667",
+ "instance":"0x6666",
+ "unreliable":"60666"
+ },
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_service_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/npdu_test_service_no_npdu_start.sh b/test/npdu_tests/npdu_test_service_no_npdu_start.sh
new file mode 100755
index 0000000..cf05aaa
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service_no_npdu_start.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the routing manager daemon and the
+# services with one command. This is necessary as ctest - which is used to run
+# the tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the routing
+# manager daemon and the services and checks if all of them exit successfully.
+
+FAIL=0
+
+start_services(){
+ export VSOMEIP_CONFIGURATION=npdu_test_service_no_npdu.json
+
+ # Start the routing manager daemon
+ export VSOMEIP_APPLICATION_NAME=npdu_test_routing_manager_daemon_service_side
+ ./npdu_test_rmd_service_side &
+
+ # sleep 1 second to let the RMD startup.
+ sleep 1
+
+ # Start service 1
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_one
+ ./npdu_test_service_1 $* &
+
+ # Start service 2
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_two
+ ./npdu_test_service_2 $* &
+
+ # Start service 3
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_three
+ ./npdu_test_service_3 $* &
+
+ # Start service 4
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_four
+ ./npdu_test_service_4 $* &
+}
+
+wait_for_bg_processes(){
+ # Wait until client and service are finished
+ for job in $(jobs -p)
+ do
+ # Fail gets incremented if one of the jobs exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+ done
+
+ # Check if everything exited successfully
+ if [ $FAIL -eq 0 ]
+ then
+ echo "All services exited successfully"
+ else
+ echo "Something went wrong"
+ exit 1
+ fi
+}
+
+start_services
+wait_for_bg_processes
+
+exit 0
diff --git a/test/npdu_tests/npdu_test_service_npdu.json b/test/npdu_tests/npdu_test_service_npdu.json
new file mode 100644
index 0000000..5dc905e
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service_npdu.json
@@ -0,0 +1,168 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications":
+ [
+ {
+ "name":"npdu_test_routing_manager_daemon_service_side",
+ "id":"0x6667"
+ },
+ {
+ "name":"npdu_test_service_one",
+ "id":"0x1000"
+ },
+ {
+ "name":"npdu_test_service_two",
+ "id":"0x2000"
+ },
+ {
+ "name":"npdu_test_service_three",
+ "id":"0x3000"
+ },
+ {
+ "name":"npdu_test_service_four",
+ "id":"0x4000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x6667",
+ "instance":"0x6666",
+ "unreliable":"60666"
+ },
+ {
+ "service":"0x1000",
+ "instance":"0x0001",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times":
+ {
+ "responses" : {
+ "0x1001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x1002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x1003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x1004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x2000",
+ "instance":"0x0002",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "responses" : {
+ "0x2001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x2002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x2003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x2004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x3000",
+ "instance":"0x0003",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times" : {
+ "responses" : {
+ "0x3001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x3002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x3003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x3004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ },
+ {
+ "service":"0x4000",
+ "instance":"0x0004",
+ "unreliable":"30509",
+ "reliable":
+ {
+ "port":"30510",
+ "enable-magic-cookies":"false"
+ },
+ "debounce-times": {
+ "responses" : {
+ "0x4001" : {
+ "debounce-time" : "10",
+ "maximum-retention-time" : "100"
+ },
+ "0x4002" : {
+ "debounce-time" : "20",
+ "maximum-retention-time" : "200"
+ },
+ "0x4003" : {
+ "debounce-time" : "30",
+ "maximum-retention-time" : "300"
+ },
+ "0x4004" : {
+ "debounce-time" : "40",
+ "maximum-retention-time" : "400"
+ }
+ }
+ }
+ }
+ ],
+ "routing":"npdu_test_routing_manager_daemon_service_side",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp"
+ }
+}
diff --git a/test/npdu_tests/npdu_test_service_npdu_start.sh b/test/npdu_tests/npdu_test_service_npdu_start.sh
new file mode 100755
index 0000000..0ca238b
--- /dev/null
+++ b/test/npdu_tests/npdu_test_service_npdu_start.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the routing manager daemon and the
+# services with one command. This is necessary as ctest - which is used to run
+# the tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the routing
+# manager daemon and the services and checks if all of them exit successfully.
+
+FAIL=0
+
+start_services(){
+ export VSOMEIP_CONFIGURATION=npdu_test_service_npdu.json
+
+ # Start the routing manager daemon
+ export VSOMEIP_APPLICATION_NAME=npdu_test_routing_manager_daemon_service_side
+ ./npdu_test_rmd_service_side &
+
+ # sleep 1 second to let the RMD startup.
+ sleep 1
+
+ # Start service 1
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_one
+ ./npdu_test_service_1 $* &
+
+ # Start service 2
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_two
+ ./npdu_test_service_2 $* &
+
+ # Start service 3
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_three
+ ./npdu_test_service_3 $* &
+
+ # Start service 4
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_four
+ ./npdu_test_service_4 $* &
+}
+
+wait_for_bg_processes(){
+ # Wait until client and service are finished
+ for job in $(jobs -p)
+ do
+ # Fail gets incremented if one of the jobs exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+ done
+
+ # Check if everything exited successfully
+ if [ $FAIL -eq 0 ]
+ then
+ echo "All services exited successfully"
+ else
+ echo "Something went wrong"
+ exit 1
+ fi
+}
+
+start_services
+wait_for_bg_processes
+
+exit 0
diff --git a/test/npdu_tests/npdu_test_starter.sh b/test/npdu_tests/npdu_test_starter.sh
new file mode 100755
index 0000000..2e88be6
--- /dev/null
+++ b/test/npdu_tests/npdu_test_starter.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Purpose: This script is needed to start the routing manager daemon and the
+# services with one command. This is necessary as ctest - which is used to run
+# the tests - isn't able to start multiple binaries for one testcase. Therefore
+# the testcase simply executes this script. This script then runs the routing
+# manager daemon and the services and checks if all of them exit successfully.
+
+FAIL=0
+
+if [ $# -lt 2 ]; then
+ echo "Error: Please pass a protocol and communication mode to this script."
+ echo "Valid protocols are [UDP,TCP]."
+ echo "Valid communication modes are [sync, async]."
+ echo "For example $> $0 UDP sync"
+ exit 1;
+fi
+
+start_services(){
+ export VSOMEIP_CONFIGURATION=npdu_test_service_npdu.json
+
+ # Start the routing manager daemon
+ export VSOMEIP_APPLICATION_NAME=npdu_test_routing_manager_daemon_service_side
+ ./npdu_test_rmd_service_side &
+
+ # sleep 1 second to let the RMD startup.
+ sleep 1
+
+ # Start service 1
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_one
+ ./npdu_test_service_1 $* &
+
+ # Start service 2
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_two
+ ./npdu_test_service_2 $* &
+
+ # Start service 3
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_three
+ ./npdu_test_service_3 $* &
+
+ # Start service 4
+ export VSOMEIP_APPLICATION_NAME=npdu_test_service_four
+ ./npdu_test_service_4 $* &
+}
+
+wait_for_bg_processes(){
+ # Wait until client and service are finished
+ for job in $(jobs -p)
+ do
+ # Fail gets incremented if one of the jobs exit
+ # with a non-zero exit code
+ wait $job || ((FAIL+=1))
+ done
+
+ # Check if everything exited successfully
+ if [ $FAIL -eq 0 ]
+ then
+ echo "All services exited successfully"
+ else
+ echo "Something went wrong"
+ exit 1
+ fi
+}
+
+
+start_services
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "starting magic cookies test on slave LXC"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./npdu_test_client_npdu_start.sh $*\"" &
+elif [ ! -z "$USE_DOCKER" ]; then
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./npdu_test_client_npdu_start.sh $*" &
+else
+sleep 1
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** npdu_test_client_npdu_start.sh $*
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** npdu_test_client_npdu.json and
+** npdu_test_service_npdu.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+wait_for_bg_processes
+
+exit 0
diff --git a/test/offer_tests/conf/offer_test_big_sd_msg_master.json.in b/test/offer_tests/conf/offer_test_big_sd_msg_master.json.in
index 17158c1..06609f6 100644
--- a/test/offer_tests/conf/offer_test_big_sd_msg_master.json.in
+++ b/test/offer_tests/conf/offer_test_big_sd_msg_master.json.in
@@ -18,7 +18,7 @@
"id" : "0x6666"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in b/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
index 2547673..07d4079 100755
--- a/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
+++ b/test/offer_tests/conf/offer_test_big_sd_msg_master_starter.sh.in
@@ -14,7 +14,7 @@ FAIL=0
export VSOMEIP_CONFIGURATION=offer_test_big_sd_msg_master.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
./offer_test_big_sd_msg_client &
@@ -27,10 +27,12 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_big_sd_msg_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./offer_test_big_sd_msg_slave_starter.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_big_sd_msg_slave_starter.sh\"" &
echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./offer_test_big_sd_msg_slave_starter.sh" &
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_big_sd_msg_slave_starter.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -59,11 +61,6 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otems
- docker rm otems
-fi
-
# wait for slave to finish
for job in $(jobs -p)
do
diff --git a/test/offer_tests/conf/offer_test_big_sd_msg_slave.json.in b/test/offer_tests/conf/offer_test_big_sd_msg_slave.json.in
index cd5056a..0c8427d 100644
--- a/test/offer_tests/conf/offer_test_big_sd_msg_slave.json.in
+++ b/test/offer_tests/conf/offer_test_big_sd_msg_slave.json.in
@@ -321,7 +321,7 @@
{"service":"0x12B","instance":"0x1","unreliable":"30299","reliable":{"port":"30299","enable-magic-cookies":"false"}},
{"service":"0x12C","instance":"0x1","unreliable":"30300","reliable":{"port":"30300","enable-magic-cookies":"false"}}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/offer_tests/conf/offer_test_external_master.json.in b/test/offer_tests/conf/offer_test_external_master.json.in
index b16a258..c54d9ac 100644
--- a/test/offer_tests/conf/offer_test_external_master.json.in
+++ b/test/offer_tests/conf/offer_test_external_master.json.in
@@ -24,7 +24,7 @@
}
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/offer_tests/conf/offer_test_external_master_starter.sh.in b/test/offer_tests/conf/offer_test_external_master_starter.sh.in
index 0f8f104..272689a 100755
--- a/test/offer_tests/conf/offer_test_external_master_starter.sh.in
+++ b/test/offer_tests/conf/offer_test_external_master_starter.sh.in
@@ -23,7 +23,7 @@ FAIL=0
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_external_master.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
./offer_test_service 2 &
@@ -40,10 +40,12 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./offer_test_external_slave_starter.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_external_slave_starter.sh\"" &
echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./offer_test_external_slave_starter.sh" &
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_external_slave_starter.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -72,11 +74,6 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otems
- docker rm otems
-fi
-
# wait for slave to finish
for job in $(jobs -p)
do
@@ -95,7 +92,7 @@ done
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_external_master.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
./offer_test_service 2 &
@@ -111,10 +108,12 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_external_sd_msg_sender"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./offer_test_external_sd_msg_sender $LXC_TEST_MASTER_IP\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./offer_test_external_sd_msg_sender $LXC_TEST_MASTER_IP\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otesms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./offer_test_external_sd_msg_sender $DOCKER_IP" &
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && sleep 10; ./offer_test_external_sd_msg_sender $DOCKER_IP" &
else
cat <<End-of-message
*******************************************************************************
@@ -141,11 +140,6 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otesms
- docker rm otesms
-fi
-
# wait for slave to finish
for job in $(jobs -p)
do
diff --git a/test/offer_tests/conf/offer_test_external_slave.json.in b/test/offer_tests/conf/offer_test_external_slave.json.in
index 47a3e9d..73a0e58 100644
--- a/test/offer_tests/conf/offer_test_external_slave.json.in
+++ b/test/offer_tests/conf/offer_test_external_slave.json.in
@@ -24,7 +24,7 @@
}
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/offer_tests/offer_test_big_sd_msg_client.cpp b/test/offer_tests/offer_test_big_sd_msg_client.cpp
index cf00de7..3ef1f61 100644
--- a/test/offer_tests/offer_test_big_sd_msg_client.cpp
+++ b/test/offer_tests/offer_test_big_sd_msg_client.cpp
@@ -16,8 +16,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-#include "../../implementation/configuration/include/internal.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "offer_test_globals.hpp"
@@ -26,7 +25,6 @@ public:
offer_test_big_sd_msg_client(struct offer_test::service_info _service_info) :
service_info_(_service_info),
app_(vsomeip::runtime::get()->create_application("offer_test_big_sd_msg_client")),
- service_available_(false),
wait_until_registered_(true),
wait_until_service_available_(true),
wait_until_subscribed_(true),
@@ -55,13 +53,12 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(offer_test::big_msg_eventgroup_id);
for (std::uint16_t s = 1; s <= offer_test::big_msg_number_services; s++) {
- app_->request_service(s,0x1,0x1,0x1,false);
+ app_->request_service(s,0x1,0x1,0x1);
app_->request_event(s,0x1, offer_test::big_msg_event_id,
- its_eventgroups, false);
+ its_eventgroups, vsomeip::event_type_e::ET_EVENT);
app_->subscribe(s, 0x1,offer_test::big_msg_eventgroup_id, 0x1,
- vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
offer_test::big_msg_event_id);
- services_available_subribed_[s] = std::make_pair(false,false);
+ services_available_subribed_[s] = std::make_pair(false,0);
app_->register_subscription_status_handler(s,0x1,
offer_test::big_msg_eventgroup_id,
offer_test::big_msg_event_id,
@@ -132,11 +129,17 @@ public:
std::lock_guard<std::mutex> its_lock(mutex_);
auto found_service = services_available_subribed_.find(_service);
if (found_service != services_available_subribed_.end()) {
- found_service->second.second = true;
+ found_service->second.second++;
+ if (found_service->second.second > 1) {
+ ADD_FAILURE() << "Registered subscription status handler was "
+ "called " << std::dec << found_service->second.second
+ << " times for service: " << std::hex
+ << found_service->first;
+ }
if (std::all_of(services_available_subribed_.cbegin(),
services_available_subribed_.cend(),
[](const services_available_subribed_t::value_type& v) {
- return v.second.second;
+ return v.second.second == 1;
}
)) {
VSOMEIP_WARNING << "************************************************************";
@@ -203,7 +206,6 @@ public:
private:
struct offer_test::service_info service_info_;
std::shared_ptr<vsomeip::application> app_;
- bool service_available_;
bool wait_until_registered_;
bool wait_until_service_available_;
@@ -215,7 +217,7 @@ private:
std::mutex stop_mutex_;
std::condition_variable stop_condition_;
- typedef std::map<vsomeip::service_t,std::pair<bool, bool>> services_available_subribed_t;
+ typedef std::map<vsomeip::service_t,std::pair<bool, std::uint32_t>> services_available_subribed_t;
services_available_subribed_t services_available_subribed_;
std::thread stop_thread_;
std::thread send_thread_;
diff --git a/test/offer_tests/offer_test_big_sd_msg_service.cpp b/test/offer_tests/offer_test_big_sd_msg_service.cpp
index d5666c8..5424be3 100644
--- a/test/offer_tests/offer_test_big_sd_msg_service.cpp
+++ b/test/offer_tests/offer_test_big_sd_msg_service.cpp
@@ -12,11 +12,12 @@
#include <map>
#include <algorithm>
#include <atomic>
+#include <algorithm>
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "offer_test_globals.hpp"
@@ -24,12 +25,12 @@ class offer_test_big_sd_msg_service {
public:
offer_test_big_sd_msg_service(struct offer_test::service_info _service_info) :
service_info_(_service_info),
- // service with number 1 uses "vsomeipd" as application name
+ // service with number 1 uses "routingmanagerd" as application name
// this way the same json file can be reused for all local tests
- // including the ones with vsomeipd
+ // including the ones with routingmanagerd
app_(vsomeip::runtime::get()->create_application("offer_test_big_sd_msg_service")),
- counter_(0),
wait_until_registered_(true),
+ wait_until_client_subscribed_to_all_services_(true),
shutdown_method_called_(false),
offer_thread_(std::bind(&offer_test_big_sd_msg_service::run, this)) {
if (!app_->init()) {
@@ -45,13 +46,22 @@ public:
its_eventgroups.insert(offer_test::big_msg_eventgroup_id);
for (std::uint16_t s = 1; s <= offer_test::big_msg_number_services; s++) {
app_->offer_event(s, 0x1,
- offer_test::big_msg_event_id, its_eventgroups, false);
+ offer_test::big_msg_event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
+ app_->register_subscription_handler(s, 0x1, offer_test::big_msg_eventgroup_id,
+ std::bind(&offer_test_big_sd_msg_service::on_subscription,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4, s));
+ subscriptions_[s] = 0;
}
app_->register_message_handler(vsomeip::ANY_SERVICE,
vsomeip::ANY_INSTANCE, service_info_.shutdown_method_id,
std::bind(&offer_test_big_sd_msg_service::on_shutdown_method_called, this,
std::placeholders::_1));
+
+
app_->start();
}
@@ -77,6 +87,31 @@ public:
}
}
+ bool on_subscription(vsomeip::client_t _client,
+ std::uint32_t _uid, std::uint32_t _gid,
+ bool _subscribed,
+ vsomeip::service_t _service) {
+ (void)_client;
+ (void)_uid;
+ (void)_gid;
+ if (_subscribed) {
+ subscriptions_[_service]++;
+ EXPECT_EQ(1u, subscriptions_[_service]);
+ if (std::all_of(subscriptions_.begin(), subscriptions_.end(), [&](const subscriptions_t::value_type& v){
+ return v.second == 1;
+ })) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_client_subscribed_to_all_services_ = false;
+ VSOMEIP_WARNING << "************************************************************";
+ VSOMEIP_WARNING << "Client subscribed to all services!";
+ VSOMEIP_WARNING << "************************************************************";
+ condition_.notify_one();
+ }
+ }
+
+ return true;
+ }
+
void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
app_->send(vsomeip::runtime::get()->create_response(_message));
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -102,17 +137,23 @@ public:
VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] Offering";
offer();
+
+ while (wait_until_client_subscribed_to_all_services_) {
+ condition_.wait(its_lock);
+ }
}
private:
struct offer_test::service_info service_info_;
std::shared_ptr<vsomeip::application> app_;
- std::uint32_t counter_;
bool wait_until_registered_;
+ bool wait_until_client_subscribed_to_all_services_;
std::mutex mutex_;
std::condition_variable condition_;
std::atomic<bool> shutdown_method_called_;
+ typedef std::map<vsomeip::service_t, std::uint32_t> subscriptions_t;
+ subscriptions_t subscriptions_;
std::thread offer_thread_;
};
diff --git a/test/offer_tests/offer_test_big_sd_msg_slave_starter.sh b/test/offer_tests/offer_test_big_sd_msg_slave_starter.sh
index d83139f..32379ed 100755
--- a/test/offer_tests/offer_test_big_sd_msg_slave_starter.sh
+++ b/test/offer_tests/offer_test_big_sd_msg_slave_starter.sh
@@ -15,7 +15,7 @@ FAIL=0
export VSOMEIP_CONFIGURATION=offer_test_big_sd_msg_slave.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
sleep 1
# Start the services
diff --git a/test/offer_tests/offer_test_client.cpp b/test/offer_tests/offer_test_client.cpp
index b337199..11446fb 100644
--- a/test/offer_tests/offer_test_client.cpp
+++ b/test/offer_tests/offer_test_client.cpp
@@ -16,8 +16,13 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-#include "../../implementation/configuration/include/internal.hpp"
+#include <vsomeip/internal/logger.hpp>
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
#include "offer_test_globals.hpp"
@@ -32,7 +37,6 @@ public:
service_info_(_service_info),
operation_mode_(_mode),
app_(vsomeip::runtime::get()->create_application("offer_test_client")),
- service_available_(false),
wait_until_registered_(true),
wait_until_service_available_(true),
wait_for_stop_(true),
@@ -68,11 +72,10 @@ public:
its_eventgroups.insert(service_info_.eventgroup_id);
app_->request_event(service_info_.service_id,
service_info_.instance_id, service_info_.event_id,
- its_eventgroups, false);
+ its_eventgroups, vsomeip::event_type_e::ET_EVENT);
app_->subscribe(service_info_.service_id, service_info_.instance_id,
- service_info_.eventgroup_id, vsomeip::DEFAULT_MAJOR,
- vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE);
+ service_info_.eventgroup_id, vsomeip::DEFAULT_MAJOR);
}
app_->start();
@@ -124,10 +127,10 @@ public:
vsomeip::byte_t *d = its_payload->get_data();
static std::uint32_t number_received_notifications(0);
std::uint32_t counter(0);
- counter |= d[0] << 24;
- counter |= d[1] << 16;
- counter |= d[2] << 8;
- counter |= d[3];
+ counter |= static_cast<std::uint32_t>(d[0] << 24);
+ counter |= static_cast<std::uint32_t>(d[0] << 16);
+ counter = counter | static_cast<std::uint32_t>((d[2] << 8));
+ counter = counter | static_cast<std::uint32_t>(d[3]);
VSOMEIP_DEBUG
<< "Received a notification with Client/Session [" << std::setw(4)
@@ -227,7 +230,6 @@ private:
struct offer_test::service_info service_info_;
operation_mode_e operation_mode_;
std::shared_ptr<vsomeip::application> app_;
- bool service_available_;
bool wait_until_registered_;
bool wait_until_service_available_;
diff --git a/test/offer_tests/offer_test_external_slave_starter.sh b/test/offer_tests/offer_test_external_slave_starter.sh
index d7f08fb..5c30e87 100755
--- a/test/offer_tests/offer_test_external_slave_starter.sh
+++ b/test/offer_tests/offer_test_external_slave_starter.sh
@@ -15,7 +15,7 @@ FAIL=0
export VSOMEIP_CONFIGURATION=offer_test_external_slave.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
sleep 1
# Start the services
diff --git a/test/offer_tests/offer_test_local.json b/test/offer_tests/offer_test_local.json
index a54049c..be8aa09 100644
--- a/test/offer_tests/offer_test_local.json
+++ b/test/offer_tests/offer_test_local.json
@@ -11,7 +11,7 @@
},
"dlt":"false"
},
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"false"
diff --git a/test/offer_tests/offer_test_local_starter.sh b/test/offer_tests/offer_test_local_starter.sh
index 38efbb6..6e5af18 100755
--- a/test/offer_tests/offer_test_local_starter.sh
+++ b/test/offer_tests/offer_test_local_starter.sh
@@ -76,7 +76,7 @@ End-of-message
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_local.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
@@ -128,7 +128,7 @@ End-of-message
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_local.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the service
./offer_test_service 2 &
@@ -186,7 +186,7 @@ End-of-message
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_local.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the service
./offer_test_service 2 &
@@ -247,7 +247,7 @@ End-of-message
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offer_test_local.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the service
./offer_test_service 2 &
diff --git a/test/offer_tests/offer_test_service.cpp b/test/offer_tests/offer_test_service.cpp
index 13c193f..c56d005 100644
--- a/test/offer_tests/offer_test_service.cpp
+++ b/test/offer_tests/offer_test_service.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "offer_test_globals.hpp"
@@ -26,11 +26,11 @@ class offer_test_service {
public:
offer_test_service(struct offer_test::service_info _service_info) :
service_info_(_service_info),
- // service with number 1 uses "vsomeipd" as application name
+ // service with number 1 uses "routingmanagerd" as application name
// this way the same json file can be reused for all local tests
- // including the ones with vsomeipd
+ // including the ones with routingmanagerd
app_(vsomeip::runtime::get()->create_application(
- (service_number == "1") ? "vsomeipd" :
+ (service_number == "1") ? "routingmanagerd" :
"offer_test_service" + service_number)),
counter_(0),
wait_until_registered_(true),
@@ -48,7 +48,9 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(service_info_.eventgroup_id);
app_->offer_event(service_info_.service_id, service_info_.instance_id,
- service_info_.event_id, its_eventgroups, false);
+ service_info_.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
inc_counter_and_notify();
diff --git a/test/offer_tests/offer_test_service_external.cpp b/test/offer_tests/offer_test_service_external.cpp
index 694a678..5948f74 100644
--- a/test/offer_tests/offer_test_service_external.cpp
+++ b/test/offer_tests/offer_test_service_external.cpp
@@ -15,7 +15,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "offer_test_globals.hpp"
@@ -25,11 +25,11 @@ class offer_test_service {
public:
offer_test_service(struct offer_test::service_info _service_info) :
service_info_(_service_info),
- // service with number 1 uses "vsomeipd" as application name
+ // service with number 1 uses "routingmanagerd" as application name
// this way the same json file can be reused for all local tests
- // including the ones with vsomeipd
+ // including the ones with routingmanagerd
app_(vsomeip::runtime::get()->create_application(
- (service_number == "1") ? "vsomeipd" :
+ (service_number == "1") ? "routingmanagerd" :
"offer_test_service" + service_number)),
wait_until_registered_(true),
wait_until_service_available_(true),
diff --git a/test/offered_services_info_test/offered_services_info_test_client.cpp b/test/offered_services_info_test/offered_services_info_test_client.cpp
index 1aa0802..202d0a6 100644
--- a/test/offered_services_info_test/offered_services_info_test_client.cpp
+++ b/test/offered_services_info_test/offered_services_info_test_client.cpp
@@ -17,8 +17,13 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
-#include "../../implementation/configuration/include/internal.hpp"
+#include <vsomeip/internal/logger.hpp>
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif
#include "offered_services_info_test_globals.hpp"
@@ -38,11 +43,9 @@ public:
remote_service_info_(_remote_service_info),
operation_mode_(_mode),
app_(vsomeip::runtime::get()->create_application("offered_services_info_test_client")),
- service_available_(false),
wait_until_registered_(true),
wait_until_service_available_(true),
wait_for_stop_(true),
- last_received_counter_(0),
last_received_response_(std::chrono::steady_clock::now()),
number_received_responses_(0),
stop_thread_(std::bind(&offered_services_info_test_client::wait_for_stop, this)),
@@ -273,7 +276,6 @@ private:
struct offer_test::service_info remote_service_info_;
operation_mode_e operation_mode_;
std::shared_ptr<vsomeip::application> app_;
- bool service_available_;
bool wait_until_registered_;
bool wait_until_service_available_;
@@ -284,7 +286,6 @@ private:
std::mutex stop_mutex_;
std::condition_variable stop_condition_;
- std::uint32_t last_received_counter_;
std::chrono::steady_clock::time_point last_received_response_;
std::atomic<std::uint32_t> number_received_responses_;
std::promise<void> all_callbacks_received_;
diff --git a/test/offered_services_info_test/offered_services_info_test_local.json b/test/offered_services_info_test/offered_services_info_test_local.json
index cb7db92..872ebd2 100644
--- a/test/offered_services_info_test/offered_services_info_test_local.json
+++ b/test/offered_services_info_test/offered_services_info_test_local.json
@@ -29,24 +29,24 @@
"instance" : "0x1"
},
{
- "service" : "0x2222",
- "instance" : "0x2",
- "reliable" : { "port" : "30502" },
- "unreliable" : "31002"
+ "service" : "0x2222",
+ "instance" : "0x2",
+ "reliable" : { "port" : "30502" },
+ "unreliable" : "31002"
},
{
- "service" : "0x2223",
- "instance" : "0x3",
- "reliable" : { "port" : "30503" }
+ "service" : "0x2223",
+ "instance" : "0x3",
+ "reliable" : { "port" : "30503" }
},
{
- "service" : "0x2224",
- "instance" : "0x4",
- "unreliable" : "31004"
+ "service" : "0x2224",
+ "instance" : "0x4",
+ "unreliable" : "31004"
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable" : "false",
diff --git a/test/offered_services_info_test/offered_services_info_test_local_starter.sh b/test/offered_services_info_test/offered_services_info_test_local_starter.sh
index 68482f9..50047db 100755
--- a/test/offered_services_info_test/offered_services_info_test_local_starter.sh
+++ b/test/offered_services_info_test/offered_services_info_test_local_starter.sh
@@ -31,8 +31,8 @@ End-of-message
# Array for client pids
CLIENT_PIDS=()
export VSOMEIP_CONFIGURATION=offered_services_info_test_local.json
-# Start the services (vsomeipd as app name)
-./offered_services_info_test_service 1 & #vsomeipd as app name
+# Start the services (routingmanagerd as app name)
+./offered_services_info_test_service 1 & #routingmanagerd as app name
PID_SERVICE_ONE=$!
./offered_services_info_test_client METHODCALL &
CLIENT_PIDS+=($!)
diff --git a/test/offered_services_info_test/offered_services_info_test_service.cpp b/test/offered_services_info_test/offered_services_info_test_service.cpp
index d9a7ae4..a77b074 100644
--- a/test/offered_services_info_test/offered_services_info_test_service.cpp
+++ b/test/offered_services_info_test/offered_services_info_test_service.cpp
@@ -17,7 +17,13 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
+
+#ifdef ANDROID
+#include "../../configuration/include/internal_android.hpp"
+#else
+#include "../../configuration/include/internal.hpp"
+#endif // ANDROID
#include "offered_services_info_test_globals.hpp"
@@ -32,13 +38,12 @@ public:
offer_test_service(struct offer_test::service_info _service_info, struct offer_test::service_info _remote_service_info) :
service_info_(_service_info),
remote_service_info_(_remote_service_info),
- // service with number 1 uses "vsomeipd" as application name
+ // service with number 1 uses "routingmanagerd" as application name
// this way the same json file can be reused for all local tests
- // including the ones with vsomeipd
+ // including the ones with routingmanagerd
app_(vsomeip::runtime::get()->create_application(
- (service_number == "1") ? "vsomeipd" :
+ (service_number == "1") ? "routingmanagerd" :
"offered_services_info_test_service" + service_number)),
- counter_(0),
wait_until_registered_(true),
shutdown_method_called_(false),
offer_thread_(std::bind(&offer_test_service::run, this)) {
@@ -230,7 +235,6 @@ private:
struct offer_test::service_info service_info_;
struct offer_test::service_info remote_service_info_;
std::shared_ptr<vsomeip::application> app_;
- std::uint32_t counter_;
bool wait_until_registered_;
std::mutex mutex_;
diff --git a/test/payload_tests/conf/external_local_payload_test_client_external.json.in b/test/payload_tests/conf/external_local_payload_test_client_external.json.in
index d027a6f..0abaea2 100644
--- a/test/payload_tests/conf/external_local_payload_test_client_external.json.in
+++ b/test/payload_tests/conf/external_local_payload_test_client_external.json.in
@@ -36,7 +36,12 @@
}
}
],
-
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "external_local_payload_test_client_external",
"service-discovery" :
{
diff --git a/test/payload_tests/conf/external_local_payload_test_client_local.json.in b/test/payload_tests/conf/external_local_payload_test_client_local.json.in
index 40f40ca..1f4fd6d 100644
--- a/test/payload_tests/conf/external_local_payload_test_client_local.json.in
+++ b/test/payload_tests/conf/external_local_payload_test_client_local.json.in
@@ -37,7 +37,12 @@
}
}
],
-
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "external_local_payload_test_service",
"service-discovery" :
{
diff --git a/test/payload_tests/conf/external_local_payload_test_service.json.in b/test/payload_tests/conf/external_local_payload_test_service.json.in
index dc7680c..aaeae82 100644
--- a/test/payload_tests/conf/external_local_payload_test_service.json.in
+++ b/test/payload_tests/conf/external_local_payload_test_service.json.in
@@ -34,7 +34,12 @@
}
}
],
-
+ "npdu-default-timings" : {
+ "debounce-time-request" : "0",
+ "debounce-time-response" : "0",
+ "max-retention-time-request" : "0",
+ "max-retention-time-response" : "0"
+ },
"routing" : "external_local_payload_test_service",
"service-discovery" :
{
diff --git a/test/payload_tests/external_local_payload_test_client_external_starter.sh b/test/payload_tests/external_local_payload_test_client_external_starter.sh
index da6ca08..97d195a 100755
--- a/test/payload_tests/external_local_payload_test_client_external_starter.sh
+++ b/test/payload_tests/external_local_payload_test_client_external_starter.sh
@@ -58,10 +58,10 @@ SERIVCE_PID=$!
# to finish the test successfully
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external local payload on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./external_local_payload_test_client_external_start.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./external_local_payload_test_client_external_start.sh\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name elptces $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -112,11 +112,6 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2
# with a non-zero exit code
wait $SERIVCE_PID || ((FAIL+=1))
-if [ ! -z "$USE_DOCKER" ]; then
- docker wait elptces
- docker rm elptces
-fi
-
# Check if server exited sucessfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh
index 041abc4..b1dd78d 100755
--- a/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh
+++ b/test/payload_tests/external_local_payload_test_client_local_and_external_starter.sh
@@ -75,10 +75,10 @@ wait $CLIENT_PID || ((FAIL+=1))
# to finish the test successfully
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external local payload on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./external_local_payload_test_client_external_start.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./external_local_payload_test_client_external_start.sh\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name elptclaes $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_payload_test_client_external_start.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -129,11 +129,6 @@ check_tcp_udp_sockets_are_open $SERIVCE_PID 2
# with a non-zero exit code
wait $SERIVCE_PID || ((FAIL+=1))
-if [ ! -z "$USE_DOCKER" ]; then
- docker wait elptclaes
- docker rm elptclaes
-fi
-
# Check if client and server both exited sucessfully and the service didnt't
# have any open TCP/UDP sockets
if [ $FAIL -eq 0 ]
diff --git a/test/payload_tests/payload_test_client.cpp b/test/payload_tests/payload_test_client.cpp
index 65dbec7..0a9708f 100644
--- a/test/payload_tests/payload_test_client.cpp
+++ b/test/payload_tests/payload_test_client.cpp
@@ -86,7 +86,7 @@ void payload_test_client::shutdown_service()
request_->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
request_->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
request_->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->send(request_,true);
+ app_->send(request_);
}
void payload_test_client::join_sender_thread()
@@ -151,7 +151,7 @@ void payload_test_client::on_message(const std::shared_ptr<vsomeip::message>& _r
all_msg_acknowledged_ = true;
all_msg_acknowledged_cv_.notify_one();
}
- else if(number_of_acknowledged_messages_ % sliding_window_size == 0)
+ else if(number_of_acknowledged_messages_ % sliding_window_size_ == 0)
{
std::lock_guard<std::mutex> lk(all_msg_acknowledged_mutex_);
all_msg_acknowledged_ = true;
@@ -259,7 +259,7 @@ void payload_test_client::send_messages_sync(std::unique_lock<std::mutex>& lk)
number_of_sent_messages_ < number_of_messages_to_send_;
number_of_sent_messages_++, number_of_sent_messages_total_++)
{
- app_->send(request_, true);
+ app_->send(request_);
// wait until the send messages has been acknowledged
// as long we wait lk is released; after wait returns lk is reacquired
all_msg_acknowledged_cv_.wait(lk, [&]
@@ -275,9 +275,9 @@ void payload_test_client::send_messages_async(std::unique_lock<std::mutex>& lk)
number_of_sent_messages_ < number_of_messages_to_send_;
number_of_sent_messages_++, number_of_sent_messages_total_++)
{
- app_->send(request_, true);
+ app_->send(request_);
- if((number_of_sent_messages_+1) % sliding_window_size == 0)
+ if((number_of_sent_messages_+1) % sliding_window_size_ == 0)
{
// wait until all send messages have been acknowledged
// as long we wait lk is released; after wait returns lk is reacquired
diff --git a/test/payload_tests/payload_test_service.cpp b/test/payload_tests/payload_test_service.cpp
index bb174cd..18935f9 100644
--- a/test/payload_tests/payload_test_service.cpp
+++ b/test/payload_tests/payload_test_service.cpp
@@ -6,13 +6,12 @@
#include "payload_test_service.hpp"
// this variables are changed via cmdline parameters
-static bool use_tcp = false;
+
static bool check_payload = true;
-payload_test_service::payload_test_service(bool _use_tcp) :
+payload_test_service::payload_test_service() :
app_(vsomeip::runtime::get()->create_application()),
is_registered_(false),
- use_tcp_(_use_tcp),
blocked_(false),
number_of_received_messages_(0),
offer_thread_(std::bind(&payload_test_service::run, this))
@@ -130,7 +129,7 @@ void payload_test_service::on_message(const std::shared_ptr<vsomeip::message>& _
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
}
void payload_test_service::on_message_shutdown(
@@ -152,7 +151,7 @@ void payload_test_service::run()
TEST(someip_payload_test, send_response_for_every_request)
{
- payload_test_service test_service(use_tcp);
+ payload_test_service test_service;
if (test_service.init()) {
test_service.start();
test_service.join_offer_thread();
diff --git a/test/payload_tests/payload_test_service.hpp b/test/payload_tests/payload_test_service.hpp
index 32ae1e7..9054fd9 100644
--- a/test/payload_tests/payload_test_service.hpp
+++ b/test/payload_tests/payload_test_service.hpp
@@ -19,7 +19,7 @@
class payload_test_service
{
public:
- payload_test_service(bool _use_tcp);
+ payload_test_service();
bool init();
void start();
void stop();
@@ -34,8 +34,6 @@ public:
private:
std::shared_ptr<vsomeip::application> app_;
bool is_registered_;
- bool use_tcp_;
- bool use_static_routing_;
std::mutex mutex_;
std::condition_variable condition_;
diff --git a/test/pending_subscription_tests/conf/pending_subscription_test_master.json.in b/test/pending_subscription_tests/conf/pending_subscription_test_master.json.in
index 5c363a7..5bcbe9a 100644
--- a/test/pending_subscription_tests/conf/pending_subscription_test_master.json.in
+++ b/test/pending_subscription_tests/conf/pending_subscription_test_master.json.in
@@ -29,10 +29,21 @@
{
"port":"40001",
"enable-magic-cookies":"false"
- }
+ },
+ "events" :
+ [
+ {
+ "event" : "0x1111",
+ "is_reliable" : "false"
+ },
+ {
+ "event" : "0x1112",
+ "is_reliable" : "false"
+ }
+ ]
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
diff --git a/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in b/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
index c36f14d..a43e3c4 100755
--- a/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
+++ b/test/pending_subscription_tests/conf/pending_subscription_test_master_starter.sh.in
@@ -23,7 +23,7 @@ fi
TESTMODE=$1
export VSOMEIP_CONFIGURATION=pending_subscription_test_master.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
./pending_subscription_test_service $1 &
@@ -35,10 +35,12 @@ if [ ! -z "$USE_LXC_TEST" ]; then
echo "Waiting for 5s"
sleep 5
echo "starting offer test on slave LXC offer_test_external_slave_starter.sh"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
echo "remote ssh pid: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name otems --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && sleep 10; ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./pending_subscription_test_sd_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
else
cat <<End-of-message
*******************************************************************************
@@ -66,10 +68,5 @@ done
kill $PID_VSOMEIPD
sleep 1
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop otems
- docker rm otems
-fi
-
# Check if everything went well
exit $FAIL
diff --git a/test/pending_subscription_tests/pending_subscription_test_sd_msg_sender.cpp b/test/pending_subscription_tests/pending_subscription_test_sd_msg_sender.cpp
index 9668c66..6d597cb 100644
--- a/test/pending_subscription_tests/pending_subscription_test_sd_msg_sender.cpp
+++ b/test/pending_subscription_tests/pending_subscription_test_sd_msg_sender.cpp
@@ -51,6 +51,12 @@ protected:
std::thread io_thread_;
};
+/*
+ * @test Send 16 subscriptions to the service and check that every
+ * subscription is answered with an SubscribeEventgroupAck entry by the service.
+ * Check that the subscription is active at the end of the test and check that
+ * the notifications send by the service receive the client
+ */
TEST_F(pending_subscription, send_multiple_subscriptions)
{
std::promise<bool> trigger_notifications;
@@ -61,90 +67,88 @@ TEST_F(pending_subscription, send_multiple_subscriptions)
udp_socket.set_option(boost::asio::socket_base::linger(true, 0));
std::thread receive_thread([&](){
- std::atomic<bool> keep_receiving(true);
- std::function<void()> receive;
+ bool keep_receiving(true);
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
+ std::uint32_t subscribe_acks_receiveid = 0;
+ std::uint32_t events_received = 0;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
keep_receiving = false;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(3u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ } else {
+
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(3u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ subscribe_acks_receiveid++;
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ events_received = 2;
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ }
}
}
- EXPECT_EQ(0u, sd_msg.get_options().size());
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
- }
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
+ if (subscribe_acks_receiveid == 30) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ subscribe_acks_receiveid++; // don't set promise value again
+ }
+ if (its_received_events.size() == 2 && events_received == 2) {
+ // all events received as well
+ keep_receiving = false;
}
}
-
- static int called = 0;
- if (++called == 15) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- }
- if (called == 18) { // events were received as well
- keep_receiving = false;
- }
- if (!error && keep_receiving) {
- receive();
- }
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(keep_receiving) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
@@ -221,6 +225,13 @@ TEST_F(pending_subscription, send_multiple_subscriptions)
udp_socket.close(ec);
}
+/*
+ * @test Send 16 subscriptions to the service while alternating between Subscribe
+ * and Unsubscribe and check that every SubscribeEventgroupEntry (ttl > 0)
+ * is answered with an SubscribeEventgroupAck entry by the service.
+ * Check that the subscription is active at the end of the test and check that
+ * the notifications send by the service receive the client
+ */
TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe)
{
std::promise<bool> trigger_notifications;
@@ -242,97 +253,101 @@ TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe)
bool triggered_notifications(false);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ bool keep_receiving(true);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
+ keep_receiving = false;
acks_received = expected_acks;
responses_received = expected_responses;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(16u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
- }
+ } else {
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
}
- EXPECT_EQ(0u, sd_msg.get_options().size());
- acks_received++;
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(16u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ acks_received++;
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
}
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
- notifications_received++;
- }
- }
-
- if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- triggered_notifications = true;
+ if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ triggered_notifications = true;
+ }
+ }
}
-
- if (!error && (acks_received != expected_acks ||
- responses_received != expected_responses ||
- notifications_received != expected_notifications)) {
- receive();
+ if (acks_received == expected_acks &&
+ responses_received == expected_responses &&
+ notifications_received == expected_notifications) {
+ keep_receiving = false;
}
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(acks_received < expected_acks ||
- responses_received < expected_responses ||
- notifications_received < expected_notifications) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+
+
EXPECT_EQ(expected_acks, acks_received);
EXPECT_EQ(expected_responses, responses_received);
EXPECT_EQ(expected_notifications, notifications_received);
@@ -418,6 +433,14 @@ TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe)
udp_socket.close(ec);
}
+/*
+ * @test Send 16 subscriptions to the service while only two contain a
+ * SubscribeEventgroupEntry and the rest contain StopSubscribeEventgroupEntries
+ * and check that all subscriptions with SubscribeEventgroupEntries are
+ * answered with an SubscribeEventgroupAck entry by the service.
+ * Check that the subscription is active at the end of the test and check that
+ * the notifications send by the service receive the client
+ */
TEST_F(pending_subscription, send_multiple_unsubscriptions)
{
std::promise<bool> trigger_notifications;
@@ -439,97 +462,98 @@ TEST_F(pending_subscription, send_multiple_unsubscriptions)
bool triggered_notifications(false);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ bool keep_receiving(true);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
+ keep_receiving = false;
acks_received = expected_acks;
responses_received = expected_responses;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(16u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
- }
+ } else {
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
}
- EXPECT_EQ(0u, sd_msg.get_options().size());
- acks_received++;
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
+ std::uint32_t its_pos = 0;
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(16u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ acks_received++;
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
}
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
- notifications_received++;
+ }
+ if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ triggered_notifications = true;
}
}
-
-
- if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- triggered_notifications = true;
- }
-
- if (!error && (acks_received != expected_acks ||
- responses_received != expected_responses ||
- notifications_received != expected_notifications)) {
- receive();
+ if (acks_received == expected_acks &&
+ responses_received == expected_responses &&
+ notifications_received == expected_notifications) {
+ std::cerr << "every thing received" << std::endl;
+ keep_receiving = false;
}
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(acks_received < expected_acks ||
- responses_received < expected_responses ||
- notifications_received < expected_notifications) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+
EXPECT_EQ(expected_acks, acks_received);
EXPECT_EQ(expected_responses, responses_received);
EXPECT_EQ(expected_notifications, notifications_received);
@@ -615,6 +639,12 @@ TEST_F(pending_subscription, send_multiple_unsubscriptions)
udp_socket.close(ec);
}
+/*
+ * @test Send 16 subscriptions to the service and check that every second
+ * subscription is answered with an SubscribeEventgroupNack entry by the service.
+ * Check that the subscription is active at the end of the test and check that
+ * the notifications send by the service receive the client
+ */
TEST_F(pending_subscription, send_alternating_subscribe_nack_unsubscribe)
{
std::promise<bool> trigger_notifications;
@@ -638,107 +668,110 @@ TEST_F(pending_subscription, send_alternating_subscribe_nack_unsubscribe)
std::atomic<std::uint32_t> notifications_received(0);
bool triggered_notifications(false);
+ bool keep_receiving(true);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
+ keep_receiving = false;
acks_received = expected_acks;
responses_received = expected_responses;
nacks_received = expected_nacks;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- if (e->get_ttl()) {
- EXPECT_EQ(16u, e->get_ttl());
- acks_received++;
- } else {
- EXPECT_EQ(0u, e->get_ttl());
- nacks_received++;
- }
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
- }
+ } else {
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
}
- EXPECT_EQ(0u, sd_msg.get_options().size());
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
+ std::uint32_t its_pos = 0;
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ if (e->get_ttl()) {
+ EXPECT_EQ(16u, e->get_ttl());
+ acks_received++;
+ } else {
+ EXPECT_EQ(0u, e->get_ttl());
+ nacks_received++;
+ }
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
}
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
- notifications_received++;
- }
- }
- if (!triggered_notifications && acks_received == expected_acks &&
- nacks_received == expected_nacks) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- triggered_notifications = true;
+ if (!triggered_notifications && acks_received == expected_acks &&
+ nacks_received == expected_nacks) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ triggered_notifications = true;
+ }
+ }
}
-
- if (!error && (acks_received != expected_acks ||
- responses_received != expected_responses ||
- notifications_received != expected_notifications ||
- nacks_received != expected_nacks)) {
- receive();
+ if (nacks_received == expected_nacks &&
+ acks_received == expected_acks &&
+ notifications_received == expected_notifications &&
+ responses_received == expected_responses) {
+ keep_receiving = false;
}
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(acks_received < expected_acks ||
- responses_received < expected_responses ||
- notifications_received < expected_notifications) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+
EXPECT_EQ(expected_acks, acks_received);
+ EXPECT_EQ(expected_nacks, nacks_received);
EXPECT_EQ(expected_responses, responses_received);
EXPECT_EQ(expected_notifications, notifications_received);
});
@@ -823,6 +856,14 @@ TEST_F(pending_subscription, send_alternating_subscribe_nack_unsubscribe)
udp_socket.close(ec);
}
+/*
+ * @test Send 16 subscriptions containing an UDP and TCP endpoint option
+ * to the service while alternating between Subscribe
+ * and Unsubscribe and check that every SubscribeEventgroupEntry (ttl > 0)
+ * is answered with an SubscribeEventgroupAck entry by the service.
+ * Check that the subscription is active at the end of the test and check that
+ * the notifications send by the service receive the client
+ */
TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe_same_port)
{
std::promise<bool> trigger_notifications;
@@ -848,7 +889,6 @@ TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe_same_port)
bool triggered_notifications(false);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
@@ -858,93 +898,93 @@ TEST_F(pending_subscription, send_alternating_subscribe_unsubscribe_same_port)
ASSERT_EQ(0, ec.value());
tcp_connected.set_value();
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ bool keep_receiving(true);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
+ keep_receiving = false;
acks_received = expected_acks;
responses_received = expected_responses;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(16u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
- }
- }
- EXPECT_EQ(0u, sd_msg.get_options().size());
- acks_received++;
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ } else {
+
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(16u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ acks_received++;
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[0]);
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[1]);
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
}
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
- notifications_received++;
- }
- }
- if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- triggered_notifications = true;
+ if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ triggered_notifications = true;
+ }
+ }
}
-
- if (!error && (acks_received != expected_acks ||
- responses_received != expected_responses ||
- notifications_received != expected_notifications)) {
- receive();
+ if (acks_received == expected_acks &&
+ responses_received == expected_responses &&
+ notifications_received == expected_notifications) {
+ keep_receiving = false;
}
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(acks_received < expected_acks ||
- responses_received < expected_responses ||
- notifications_received < expected_notifications) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+
+
EXPECT_EQ(expected_acks, acks_received);
EXPECT_EQ(expected_responses, responses_received);
EXPECT_EQ(expected_notifications, notifications_received);
@@ -1056,99 +1096,115 @@ TEST_F(pending_subscription, subscribe_resubscribe_mixed)
udp_socket.set_option(boost::asio::socket_base::linger(true, 0));
std::thread receive_thread([&](){
- std::atomic<bool> keep_receiving(true);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ const std::uint32_t expected_acks(3);
+ std::atomic<std::uint32_t> acks_received(0);
+
+ const std::uint32_t expected_responses(1);
+ std::atomic<std::uint32_t> responses_received(0);
+
+ const std::uint32_t expected_notifications(2);
+ std::atomic<std::uint32_t> notifications_received(0);
+
+ bool keep_receiving(true);
+ bool first_initial_event_checked(false);
+ bool second_initial_event_checked(false);
+
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transfered = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
keep_receiving = false;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_GE(2u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(3u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
- its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ } else {
+
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transfered > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transfered -= its_message_size;
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_GE(2u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(3u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ acks_received++;
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id ||
+ its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id+1);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ if (its_received_events.size() == 2) {
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[0]);
+ EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[1]);
+ }
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
}
- }
- EXPECT_EQ(0u, sd_msg.get_options().size());
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- if (its_received_events.size() == 2) {
+
+ if (!first_initial_event_checked && notifications_received == 1) {
+ EXPECT_EQ(1u, its_received_events.size());
+ EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[0]);
+ // all subscribeAcks and one initial event of first event received
+ first_initial_event_received.set_value();
+ first_initial_event_checked = true;
+ }
+
+ if (!second_initial_event_checked && notifications_received == 2) { // events were received as well
+ // all subscribeAcks and one initial event of second event received
+ EXPECT_EQ(2u, its_received_events.size());
EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[0]);
EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[1]);
+ second_initial_event_received.set_value();
+ second_initial_event_checked = true;
+ }
+ if (notifications_received == 2 && responses_received == 1) {
+ keep_receiving = false;
}
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
}
}
-
- static int called = 0;
- if (++called == 2) {
- EXPECT_EQ(1u, its_received_events.size());
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[0]);
- // all subscribeAcks and one initial event of first event received
- first_initial_event_received.set_value();
- }
- if (called == 4) { // events were received as well
- // all subscribeAcks and one initial event of second event received
- EXPECT_EQ(2u, its_received_events.size());
- EXPECT_EQ(static_cast<vsomeip::event_t>(pending_subscription_test::service.event_id + 1u), its_received_events[0]);
- EXPECT_EQ(pending_subscription_test::service.event_id, its_received_events[1]);
- keep_receiving = false;
- second_initial_event_received.set_value();
- }
- if (!error && keep_receiving) {
- receive();
- }
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(keep_receiving) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+ EXPECT_EQ(expected_acks, acks_received);
+ EXPECT_EQ(expected_notifications, notifications_received);
+ EXPECT_EQ(expected_responses, responses_received);
});
std::thread send_thread([&]() {
@@ -1261,7 +1317,7 @@ TEST_F(pending_subscription, send_subscribe_stop_subscribe_subscribe)
tcp_socket.set_option(boost::asio::socket_base::linger(true, 0));
std::thread receive_thread([&](){
- const std::uint32_t expected_acks(1);
+ const std::uint32_t expected_acks(2);
std::atomic<std::uint32_t> acks_received(0);
const std::uint32_t expected_responses(1);
@@ -1272,7 +1328,6 @@ TEST_F(pending_subscription, send_subscribe_stop_subscribe_subscribe)
bool triggered_notifications(false);
- std::function<void()> receive;
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
@@ -1282,88 +1337,93 @@ TEST_F(pending_subscription, send_subscribe_stop_subscribe_subscribe)
ASSERT_EQ(0, ec.value());
tcp_connected.set_value();
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ bool keep_receiving(true);
+
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
+ keep_receiving = false;
acks_received = expected_acks;
responses_received = expected_responses;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(1u, sd_msg.get_entries().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_eventgroup_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
- EXPECT_EQ(16u, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
- std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
- std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
- EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id);
- }
- }
- EXPECT_EQ(0u, sd_msg.get_options().size());
- acks_received++;
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
- its_received_events.push_back(msg.get_method());
- EXPECT_EQ(1u, its_received_events.size());
- EXPECT_EQ(1u, msg.get_payload()->get_length());
- EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(0x0, msg.get_client());
- notifications_received++;
- }
- }
+ } else {
+ std::uint32_t its_pos = 0;
- if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
- trigger_notifications.set_value(true);
- triggered_notifications = true;
- }
+ while (bytes_transferred > 0) {
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
+ }
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
+
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK, e->get_type());
+ EXPECT_EQ(16u, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_TRUE(its_casted_entry->get_eventgroup() == pending_subscription_test::service.eventgroup_id);
+ }
+ }
+ EXPECT_EQ(0u, sd_msg.get_options().size());
+ acks_received++;
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ its_received_events.push_back(msg.get_method());
+ EXPECT_EQ(1u, its_received_events.size());
+ EXPECT_EQ(1u, msg.get_payload()->get_length());
+ EXPECT_EQ(0xDD, *msg.get_payload()->get_data());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(0x0, msg.get_client());
+ notifications_received++;
+ }
+ }
- if (!error && (acks_received != expected_acks ||
- responses_received != expected_responses ||
- notifications_received != expected_notifications)) {
- receive();
+ if (!triggered_notifications && acks_received == expected_acks) { // all subscribeAcks received
+ trigger_notifications.set_value(true);
+ triggered_notifications = true;
+ }
+ }
+ if (acks_received == expected_acks &&
+ responses_received == expected_responses &&
+ notifications_received == expected_notifications) {
+ keep_receiving = false;
+ }
}
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(acks_received < expected_acks ||
- responses_received < expected_responses ||
- notifications_received < expected_notifications) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
EXPECT_EQ(expected_acks, acks_received);
EXPECT_EQ(expected_responses, responses_received);
@@ -1376,10 +1436,26 @@ TEST_F(pending_subscription, send_subscribe_stop_subscribe_subscribe)
}
try {
+ std::uint8_t its_normal_subscribe_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x06, 0x00, 0x00, 0x10, // subscribe Eventgroup entry
+ 0x11, 0x22, 0x00, 0x01, // service / instance
+ 0x00, 0x00, 0x00, 0x10, // 16 seconds TTL
+ 0x00, 0x00, 0x10, 0x00, // eventgroup
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // ip address
+ 0x00, 0x11, 0x77, 0x1a
+ };
std::uint8_t its_subscribe_message[] = {
0xff, 0xff, 0x81, 0x00,
0x00, 0x00, 0x00, 0x50, // length
- 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x02,
0x01, 0x01, 0x02, 0x00,
0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, // length entries array
@@ -1404,10 +1480,13 @@ TEST_F(pending_subscription, send_subscribe_stop_subscribe_subscribe)
boost::asio::ip::address its_local_address =
boost::asio::ip::address::from_string(std::string(local_address));
std::memcpy(&its_subscribe_message[80], &its_local_address.to_v4().to_bytes()[0], 4);
+ std::memcpy(&its_normal_subscribe_message[48], &its_local_address.to_v4().to_bytes()[0], 4);
boost::asio::ip::udp::socket::endpoint_type target_sd(
boost::asio::ip::address::from_string(std::string(remote_address)),
30490);
+
+ udp_socket.send_to(boost::asio::buffer(its_normal_subscribe_message), target_sd);
udp_socket.send_to(boost::asio::buffer(its_subscribe_message), target_sd);
if (std::future_status::timeout == trigger_notifications.get_future().wait_for(std::chrono::seconds(10))) {
@@ -1466,80 +1545,80 @@ TEST_F(pending_subscription, send_request_to_sd_port)
udp_socket.set_option(boost::asio::socket_base::linger(true, 0));
std::thread receive_thread([&](){
- std::atomic<bool> keep_receiving(true);
- std::function<void()> receive;
+ bool keep_receiving(true);
std::vector<std::uint8_t> receive_buffer(4096);
std::vector<vsomeip::event_t> its_received_events;
- const std::function<void(const boost::system::error_code&, std::size_t)> receive_cbk = [&](
- const boost::system::error_code& error, std::size_t bytes_transferred) {
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
if (error) {
keep_receiving = false;
ADD_FAILURE() << __func__ << " error: " << error.message();
- return;
- }
- #if 0
- std::stringstream str;
- for (size_t i = 0; i < bytes_transferred; i++) {
- str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
- }
- std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
- #endif
-
- static int offers_received = 0;
- static int responses_received = 0;
- vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
- vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
- receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
- vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
- receive_buffer[VSOMEIP_METHOD_POS_MAX]);
- if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
- vsomeip::sd::message_impl sd_msg;
- EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
- EXPECT_EQ(1u, sd_msg.get_entries().size());
- EXPECT_EQ(2u, sd_msg.get_options().size());
- for (auto e : sd_msg.get_entries()) {
- EXPECT_TRUE(e->is_service_entry());
- EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
- EXPECT_EQ(0xffffffu, e->get_ttl());
- EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
- EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
- offers_received++;
- }
- } else { // non-sd-message
- vsomeip::message_impl msg;
- EXPECT_TRUE(msg.deserialize(&its_deserializer));
- if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
- EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
- EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
- EXPECT_EQ(0x2222, msg.get_client());
- responses_received++;
- }
- }
+ } else {
+ std::uint32_t its_pos = 0;
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+
+ #if 0
+ std::stringstream str;
+ for (size_t i = 0; i < bytes_transferred; i++) {
+ str << std::hex << std::setw(2) << std::setfill('0') << std::uint32_t(receive_buffer[i]) << " ";
+ }
+ std::cout << __func__ << " received: " << std::dec << bytes_transferred << " bytes: " << str.str() << std::endl;
+ #endif
+ static int offers_received = 0;
+ static int responses_received = 0;
+
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ EXPECT_EQ(2u, sd_msg.get_options().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(0xffffffu, e->get_ttl());
+ EXPECT_EQ(pending_subscription_test::service.service_id, e->get_service());
+ EXPECT_EQ(pending_subscription_test::service.instance_id, e->get_instance());
+ offers_received++;
+ }
+ } else { // non-sd-message
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(pending_subscription_test::service.service_id, msg.get_service());
+ EXPECT_EQ(pending_subscription_test::service.shutdown_method_id, msg.get_method());
+ EXPECT_EQ(0x2222, msg.get_client());
+ responses_received++;
+ }
+ }
- if (responses_received == 1) { // resonse to shutdown method was received as well
- keep_receiving = false;
- } else if (offers_received == 3 ) { // all multiple offers received
- try {
- all_offers_received.set_value(true);
- } catch (const std::future_error& e) {
+ if (responses_received == 1) { // response to shutdown method was received as well
+ keep_receiving = false;
+ } else if (offers_received == 3 ) { // all multiple offers received
+ try {
+ all_offers_received.set_value(true);
+ } catch (const std::future_error& e) {
+ }
+ }
}
}
- if (!error && keep_receiving) {
- receive();
- }
- };
-
- receive = [&]() {
- udp_socket.async_receive(boost::asio::buffer(receive_buffer, receive_buffer.capacity()),
- receive_cbk);
- };
-
- receive();
- while(keep_receiving) {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
diff --git a/test/pending_subscription_tests/pending_subscription_test_service.cpp b/test/pending_subscription_tests/pending_subscription_test_service.cpp
index 6a917ea..29ce3f2 100644
--- a/test/pending_subscription_tests/pending_subscription_test_service.cpp
+++ b/test/pending_subscription_tests/pending_subscription_test_service.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "pending_subscription_test_globals.hpp"
@@ -44,14 +44,19 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(_service_info.eventgroup_id);
app_->offer_event(service_info_.service_id, 0x1,
- service_info_.event_id, its_eventgroups, true);
+ service_info_.event_id,
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
its_eventgroups.clear();
its_eventgroups.insert(static_cast<vsomeip::eventgroup_t>(_service_info.eventgroup_id+1u));
app_->offer_event(service_info_.service_id, 0x1,
static_cast<vsomeip::event_t>(service_info_.event_id+1u),
- its_eventgroups, true);
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
app_->register_message_handler(vsomeip::ANY_SERVICE,
vsomeip::ANY_INSTANCE, service_info_.shutdown_method_id,
@@ -66,11 +71,13 @@ public:
app_->register_async_subscription_handler(service_info_.service_id,
0x1, service_info_.eventgroup_id,
std::bind(&pending_subscription_test_service::subscription_handler_async,
- this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+ std::placeholders::_4, std::placeholders::_5));
app_->register_subscription_handler(service_info_.service_id,
0x1, static_cast<vsomeip::eventgroup_t>(service_info_.eventgroup_id+1u),
std::bind(&pending_subscription_test_service::subscription_handler,
- this, std::placeholders::_1, std::placeholders::_2));
+ this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+ std::placeholders::_4));
app_->start();
}
@@ -158,7 +165,7 @@ public:
}
std::future<bool> itsFuture = notify_method_called_.get_future();
- if (std::future_status::timeout == itsFuture.wait_for(std::chrono::seconds(10))) {
+ if (std::future_status::timeout == itsFuture.wait_for(std::chrono::seconds(30))) {
ADD_FAILURE() << "notify method wasn't called within time!";
} else {
EXPECT_TRUE(itsFuture.get());
@@ -170,8 +177,10 @@ public:
stop();
}
- void subscription_handler_async(vsomeip::client_t _client, bool _subscribed,
- std::function<void(const bool)> _cbk) {
+ void subscription_handler_async(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid,
+ bool _subscribed, const std::function<void(const bool)>& _cbk) {
+ (void)_uid;
+ (void)_gid;
VSOMEIP_WARNING << __func__ << " " << std::hex << _client << " subscribed." << _subscribed;
if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE) {
async_subscription_handler_ = _cbk;
@@ -225,7 +234,7 @@ public:
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
_cbk(true);
- if (count_subscribe == 16 || count_unsubscribe == 14) {
+ if (count_subscribe == 8 || count_unsubscribe == 7) {
subscription_accepted_asynchronous_ = true;
}
} else if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE_RESUBSCRIBE_MIXED) {
@@ -248,8 +257,10 @@ public:
}
}
- bool subscription_handler(vsomeip::client_t _client, bool _subscribed) {
+ bool subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
(void)_subscribed;
+ (void)_uid;
+ (void)_gid;
bool ret(false);
VSOMEIP_WARNING << __func__ << " " << std::hex << _client << " subscribed. " << _subscribed;
if (testmode_ == pending_subscription_test::test_mode_e::SUBSCRIBE) {
@@ -300,10 +311,11 @@ public:
static int count_subscribed = 0;
static int count_unsubscribe = 0;
_subscribed ? count_subscribed++ : count_unsubscribe++;
+
if (count_subscribed == 1) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
- if (count_subscribed == 16 && count_unsubscribe == 14) {
+ if (count_subscribed == 8 && count_unsubscribe == 7) {
subscription_accepted_synchronous_ = true;
}
ret = true;
diff --git a/test/readme.txt b/test/readme.txt
index 9f7985a..2841795 100644
--- a/test/readme.txt
+++ b/test/readme.txt
@@ -520,3 +520,54 @@ Rejecting remote offer for which there is already a local offer
* start application which offers service
* send SD message trying to offer the same service instance as already
offered locally from a remote host -> should be rejected
+
+nPDU tests
+-----------------
+
+This test is intended to test the functionality of the so called nPDU
+feature. The test setup is as followed:
+
+* There are two nodes, one hosting the services, one hosting the clients.
+* On each of the nodes is a routing manager daemon (RMD) started whose only
+ purpose is to provide routing manager functionality and shutdown the clients
+ and services at the end.
+* There are four services created. Each of the services has four methods.
+* All services are listening on the same port. Therefore there only is:
+ * one server endpoint created in the RMD on service side
+ * one client endpoint created in the RMD on client side
+* There are four clients created. Each of the clients will:
+ * Create a thread for each service
+ * Create a thread for each method of each service
+ * Send multiple messages with increasing payload to each of the services'
+ methods from the corresponding thread.
+ * After sending the threads will sleep the correct amount of time to insure
+ applicative debounce > debounce time + max retention time.
+* After all messages have been sent to the services the clients will notify the
+ RMD that they're finished. The RMD then instructs the RMD on service side to
+ shutdown the services and exit afterwards. After that the RMD on client side
+ exits as well.
+* Upon receiving a method call the service will check if the debounce time
+ specified in the json file for this method was undershot and print out a
+ warning.
+* The test first runs in synchronous mode and waits for a response of the
+ service before sending the next message.
+* After that the test runs in a mode where no response from the service are
+ required (message type REQUEST_NO_RETURN) thus the clients send at maximum
+ allowed frequency.
+
+Automatic start from build directory:
+
+ctest -V -R npdu_test_UDP
+ctest -V -R npdu_test_TCP
+
+A message will be shown when the external clients should be started.
+
+Manual start:
+# Service side
+./npdu_test_service_npdu_start.sh
+
+# Client side UDP mode
+./npdu_test_client_npdu_start.sh UDP
+
+# Client side TCP mode
+./npdu_test_client_npdu_start.sh TCP
diff --git a/test/restart_routing_tests/restart_routing_test_client.cpp b/test/restart_routing_tests/restart_routing_test_client.cpp
index a8c0acc..847594e 100644
--- a/test/restart_routing_tests/restart_routing_test_client.cpp
+++ b/test/restart_routing_tests/restart_routing_test_client.cpp
@@ -98,6 +98,7 @@ void routing_restart_test_client::on_message(const std::shared_ptr<vsomeip::mess
if (received_responses_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS) {
VSOMEIP_WARNING << std::hex << app_->get_client()
<< ": Received all messages ~> going down!";
+ all_responses_received_.set_value();
}
}
}
@@ -116,14 +117,18 @@ void routing_restart_test_client::run() {
request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID);
- app_->send(request, true);
+ app_->send(request);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
- std::this_thread::sleep_for(std::chrono::milliseconds(250));
- EXPECT_EQ(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS,
- received_responses_);
+ if (std::future_status::ready == all_responses_received_.get_future().wait_for(std::chrono::milliseconds(10000))) {
+ EXPECT_EQ(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS,
+ received_responses_);
+ VSOMEIP_WARNING << "Received all answers";
+ } else {
+ ADD_FAILURE() << "Didn't receive all responses within time";
+ }
stop();
}
@@ -140,7 +145,7 @@ void routing_restart_test_client::shutdown_service() {
request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->send(request,true);
+ app_->send(request);
}
TEST(someip_restart_routing_test, request_response_over_restart)
diff --git a/test/restart_routing_tests/restart_routing_test_client.hpp b/test/restart_routing_tests/restart_routing_test_client.hpp
index fdc56d4..cd4a12f 100644
--- a/test/restart_routing_tests/restart_routing_test_client.hpp
+++ b/test/restart_routing_tests/restart_routing_test_client.hpp
@@ -17,6 +17,7 @@
#include <mutex>
#include <condition_variable>
#include <atomic>
+#include <future>
class routing_restart_test_client {
public:
@@ -45,6 +46,7 @@ private:
std::thread sender_;
std::atomic<std::uint32_t> received_responses_;
+ std::promise<void> all_responses_received_;
};
#endif // RESTART_ROUTING_TEST_CLIENT_HPP
diff --git a/test/restart_routing_tests/restart_routing_test_client.json b/test/restart_routing_tests/restart_routing_test_client.json
index 0d901d8..93fafab 100644
--- a/test/restart_routing_tests/restart_routing_test_client.json
+++ b/test/restart_routing_tests/restart_routing_test_client.json
@@ -37,7 +37,7 @@
[
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable" : "false",
diff --git a/test/restart_routing_tests/restart_routing_test_service.cpp b/test/restart_routing_tests/restart_routing_test_service.cpp
index cf4bba1..35ab01a 100644
--- a/test/restart_routing_tests/restart_routing_test_service.cpp
+++ b/test/restart_routing_tests/restart_routing_test_service.cpp
@@ -94,7 +94,7 @@ void routing_restart_test_service::on_message(const std::shared_ptr<vsomeip::mes
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
number_of_received_messages_++;
if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_ROUTING_RESTART_TESTS) {
diff --git a/test/restart_routing_tests/restart_routing_test_service.json b/test/restart_routing_tests/restart_routing_test_service.json
index 8ff90cb..9a1d3bf 100644
--- a/test/restart_routing_tests/restart_routing_test_service.json
+++ b/test/restart_routing_tests/restart_routing_test_service.json
@@ -16,7 +16,7 @@
"applications" :
[
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x0815"
},
{
@@ -33,7 +33,7 @@
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable" : "false",
diff --git a/test/restart_routing_tests/restart_routing_test_starter.sh b/test/restart_routing_tests/restart_routing_test_starter.sh
index 0778e98..9d74c36 100755
--- a/test/restart_routing_tests/restart_routing_test_starter.sh
+++ b/test/restart_routing_tests/restart_routing_test_starter.sh
@@ -21,7 +21,7 @@ echo "----------------------------------------------"
export VSOMEIP_CONFIGURATION=restart_routing_test_autoconfig.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
sleep 2
@@ -53,15 +53,15 @@ CLIENT4_PID=$!
sleep 2
echo "----------------------------------------------"
-echo " let vsomeipd crash (kill -9) "
+echo " let routingmanagerd crash (kill -9) "
echo "----------------------------------------------"
kill -9 $DAEMON_PID
echo "----------------------------------------------"
-echo " restart vsomeipd "
+echo " restart routingmanagerd "
echo "----------------------------------------------"
sleep 2
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
wait $SERIVCE_PID || ((FAIL+=1))
@@ -156,7 +156,7 @@ echo "----------------------------------------------"
sleep 2
export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
# Start the service
@@ -191,16 +191,16 @@ CLIENT4_PID=$!
sleep 2
echo "----------------------------------------------"
-echo " let vsomeipd crash (kill -9) "
+echo " let routingmanagerd crash (kill -9) "
echo "----------------------------------------------"
kill -9 $DAEMON_PID
echo "----------------------------------------------"
-echo " restart vsomeipd "
+echo " restart routingmanagerd "
echo "----------------------------------------------"
sleep 2
export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
wait $SERIVCE_PID || ((FAIL+=1))
@@ -230,7 +230,7 @@ echo "----------------------------------------------"
sleep 2
export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
# Start the service
@@ -265,7 +265,7 @@ CLIENT4_PID=$!
sleep 2
echo "----------------------------------------------"
-echo " let vsomeipd crash (kill -9) "
+echo " let routingmanagerd crash (kill -9) "
echo "----------------------------------------------"
kill -9 $DAEMON_PID
sleep 1
@@ -274,12 +274,12 @@ echo " let service crash (kill -9) "
echo "----------------------------------------------"
kill -9 $SERIVCE_PID
echo "----------------------------------------------"
-echo " restart vsomeipd "
+echo " restart routingmanagerd "
echo "----------------------------------------------"
sleep 2
export VSOMEIP_CONFIGURATION=restart_routing_test_service.json
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
DAEMON_PID=$!
echo "----------------------------------------------"
diff --git a/test/routing_tests/conf/local_routing_test_starter.sh.in b/test/routing_tests/conf/local_routing_test_starter.sh.in
index 457c60c..9e10480 100755
--- a/test/routing_tests/conf/local_routing_test_starter.sh.in
+++ b/test/routing_tests/conf/local_routing_test_starter.sh.in
@@ -35,7 +35,7 @@ check_tcp_udp_sockets_are_closed ()
export VSOMEIP_CONFIGURATION=local_routing_test_service.json
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
WAIT_PIDS=()
diff --git a/test/routing_tests/external_local_routing_test_service.cpp b/test/routing_tests/external_local_routing_test_service.cpp
index ce8b9ef..c357165 100644
--- a/test/routing_tests/external_local_routing_test_service.cpp
+++ b/test/routing_tests/external_local_routing_test_service.cpp
@@ -130,7 +130,7 @@ void external_local_routing_test_service::on_message(
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
if(number_received_messages_local_ >= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND
&& number_received_messages_external_ >= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND)
diff --git a/test/routing_tests/external_local_routing_test_starter.sh b/test/routing_tests/external_local_routing_test_starter.sh
index af94ab6..f8fa2df 100755
--- a/test/routing_tests/external_local_routing_test_starter.sh
+++ b/test/routing_tests/external_local_routing_test_starter.sh
@@ -78,10 +78,10 @@ if [ $CLIENT_STILL_THERE -ne 0 ]
then
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external_local_routing_test_starter.sh on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./external_local_routing_test_client_external_start.sh\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./external_local_routing_test_client_external_start.sh\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name elrts --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./external_local_routing_test_client_external_start.sh" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./external_local_routing_test_client_external_start.sh" &
else
cat <<End-of-message
*******************************************************************************
@@ -111,11 +111,6 @@ do
wait $job || ((FAIL+=1))
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop elrts
- docker rm elrts
-fi
-
# Check if client and server both exited sucessfully and the service didnt't
# have any open
if [ $FAIL -eq 0 ]
diff --git a/test/routing_tests/local_routing_test_client.cpp b/test/routing_tests/local_routing_test_client.cpp
index 5bd83fe..26df99f 100644
--- a/test/routing_tests/local_routing_test_client.cpp
+++ b/test/routing_tests/local_routing_test_client.cpp
@@ -8,7 +8,6 @@
local_routing_test_client::local_routing_test_client(bool _use_tcp) :
app_(vsomeip::runtime::get()->create_application()),
request_(vsomeip::runtime::get()->create_request(_use_tcp)),
- running_(true),
blocked_(false),
is_available_(false),
number_of_messages_to_send_(vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND),
@@ -130,7 +129,7 @@ void local_routing_test_client::run()
for (uint32_t i = 0; i < number_of_messages_to_send_; i++)
{
- app_->send(request_, true);
+ app_->send(request_);
VSOMEIP_INFO << "Client/Session [" << std::setw(4) << std::setfill('0')
<< std::hex << request_->get_client() << "/" << std::setw(4)
<< std::setfill('0') << std::hex << request_->get_session()
diff --git a/test/routing_tests/local_routing_test_client.hpp b/test/routing_tests/local_routing_test_client.hpp
index b135dea..7cc442a 100644
--- a/test/routing_tests/local_routing_test_client.hpp
+++ b/test/routing_tests/local_routing_test_client.hpp
@@ -37,7 +37,6 @@ private:
std::shared_ptr<vsomeip::message> request_;
std::mutex mutex_;
std::condition_variable condition_;
- bool running_;
bool blocked_;
bool is_available_;
std::uint32_t number_of_messages_to_send_;
diff --git a/test/routing_tests/local_routing_test_client.json b/test/routing_tests/local_routing_test_client.json
index 2b4bdaa..e3521c8 100644
--- a/test/routing_tests/local_routing_test_client.json
+++ b/test/routing_tests/local_routing_test_client.json
@@ -27,7 +27,7 @@
[
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable" : "false",
diff --git a/test/routing_tests/local_routing_test_service.cpp b/test/routing_tests/local_routing_test_service.cpp
index 4f7962d..81d47eb 100644
--- a/test/routing_tests/local_routing_test_service.cpp
+++ b/test/routing_tests/local_routing_test_service.cpp
@@ -114,7 +114,7 @@ void local_routing_test_service::on_message(const std::shared_ptr<vsomeip::messa
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
if(number_of_received_messages_ >= vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND)
{
diff --git a/test/routing_tests/local_routing_test_service.json b/test/routing_tests/local_routing_test_service.json
index f5da8c6..6b7e11d 100644
--- a/test/routing_tests/local_routing_test_service.json
+++ b/test/routing_tests/local_routing_test_service.json
@@ -30,7 +30,7 @@
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable" : "false",
diff --git a/test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_slave.json.in b/test/second_address_tests/conf/second_address_test_master_client.json.in
index e8e38cf..542480f 100644
--- a/test/debug_diag_job_plugin_tests/conf/debug_diag_job_plugin_test_slave.json.in
+++ b/test/second_address_tests/conf/second_address_test_master_client.json.in
@@ -1,5 +1,5 @@
{
- "unicast":"@TEST_IP_SLAVE@",
+ "unicast":"@TEST_IP_MASTER@",
"logging":
{
"level":"warning",
@@ -11,24 +11,21 @@
},
"dlt":"false"
},
- "applications":
+ "applications" :
[
{
- "name":"debug_diag_job_plugin_test_client",
- "id":"0x9090"
+ "name" : "second_address_test_client",
+ "id" : "0x1210",
+ "max_dispatch_time" : "1000"
}
],
- "routing":"vsomeipd",
+ "routing":"routingmanagerd",
"service-discovery":
{
"enable":"true",
- "multicast":"224.1.1.1",
+ "multicast":"224.0.50.1",
"port":"30490",
"protocol":"udp",
- "initial_delay_min" : "10",
- "initial_delay_max" : "10",
- "repetitions_base_delay" : "30",
- "repetitions_max" : "3",
"cyclic_offer_delay" : "1000",
"ttl" : "3"
}
diff --git a/test/second_address_tests/conf/second_address_test_master_service_udp.json.in b/test/second_address_tests/conf/second_address_test_master_service_udp.json.in
new file mode 100644
index 0000000..1b45898
--- /dev/null
+++ b/test/second_address_tests/conf/second_address_test_master_service_udp.json.in
@@ -0,0 +1,40 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "second_address_test_service",
+ "id" : "0x3489",
+ "max_dispatch_time" : "1000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ }
+ ],
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.50.1",
+ "port":"30490",
+ "protocol":"udp",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/second_address_tests/conf/second_address_test_slave_client.json.in b/test/second_address_tests/conf/second_address_test_slave_client.json.in
new file mode 100644
index 0000000..303bfae
--- /dev/null
+++ b/test/second_address_tests/conf/second_address_test_slave_client.json.in
@@ -0,0 +1,32 @@
+{
+ "unicast":"@TEST_IP_SLAVE_SECOND@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "second_address_test_client",
+ "id" : "0x1210",
+ "max_dispatch_time" : "1000"
+ }
+ ],
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.50.1",
+ "port":"30490",
+ "protocol":"udp",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/second_address_tests/conf/second_address_test_slave_service_udp.json.in b/test/second_address_tests/conf/second_address_test_slave_service_udp.json.in
new file mode 100644
index 0000000..9a7c062
--- /dev/null
+++ b/test/second_address_tests/conf/second_address_test_slave_service_udp.json.in
@@ -0,0 +1,40 @@
+{
+ "unicast":"@TEST_IP_SLAVE_SECOND@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications" :
+ [
+ {
+ "name" : "second_address_test_service",
+ "id" : "0x3489",
+ "max_dispatch_time" : "1000"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ }
+ ],
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.50.1",
+ "port":"30490",
+ "protocol":"udp",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/second_address_tests/conf/second_address_test_slave_starter.sh.in b/test/second_address_tests/conf/second_address_test_slave_starter.sh.in
new file mode 100755
index 0000000..85080aa
--- /dev/null
+++ b/test/second_address_tests/conf/second_address_test_slave_starter.sh.in
@@ -0,0 +1,60 @@
+#!/bin/bash
+# Copyright (C) 2015-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FAIL=0
+
+if [ $# -lt 2 ]
+then
+ echo "Please pass a operation and communication mode to this script."
+ echo "For example: $0 CLIENT UDP"
+ echo "Valid operation modes include [SERVICE, CLIENT]"
+ echo "Valid communication modes include [UDP, TCP]"
+ exit 1
+fi
+
+OPERATIONMODE=$1
+COMMUNICATIONMODE=$2
+
+# Add second IP address to interface
+ip addr add @TEST_IP_SLAVE_SECOND@ dev eth0
+
+if [ "$OPERATIONMODE" = "CLIENT" ]; then
+ SLAVE_APPLICATION=second_address_test_client
+ export VSOMEIP_CONFIGURATION=second_address_test_slave_client.json
+
+elif [ "$OPERATIONMODE" = "SERVICE" ]; then
+ SLAVE_APPLICATION=second_address_test_service
+
+ if [ "$COMMUNICATIONMODE" = "TCP" ]; then
+ export VSOMEIP_CONFIGURATION=second_address_test_slave_service_tcp.json
+ elif [ "$COMMUNICATIONMODE" = "UDP" ]; then
+ export VSOMEIP_CONFIGURATION=second_address_test_slave_service_udp.json
+ fi
+fi
+
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+
+./$SLAVE_APPLICATION $COMMUNICATIONMODE &
+PID_SLAVE=$!
+
+# Wait until all slaves are finished
+for job in $PID_SLAVE
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ echo "waiting for $job"
+ wait $job || FAIL=$(($FAIL+1))
+done
+
+# kill the services
+kill $PID_VSOMEIPD
+sleep 1
+
+# Delete second IP address
+ip addr del @TEST_IP_SLAVE_SECOND@ dev eth0
+
+# Check if everything went well
+exit $FAIL
diff --git a/test/second_address_tests/second_address_test_client.cpp b/test/second_address_tests/second_address_test_client.cpp
new file mode 100644
index 0000000..616346b
--- /dev/null
+++ b/test/second_address_tests/second_address_test_client.cpp
@@ -0,0 +1,353 @@
+// Copyright (C) 2014-2018 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+#include <atomic>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "second_address_test_globals.hpp"
+
+class second_address_test_client {
+public:
+ second_address_test_client(struct second_address_test::service_info _service_info, bool _use_tcp) :
+ service_info_(_service_info),
+ use_tcp_(_use_tcp),
+ app_(vsomeip::runtime::get()->create_application("second_address_test_client")),
+ send_thread_(std::bind(&second_address_test_client::send, this)) {
+
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_state_handler(
+ std::bind(&second_address_test_client::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.request_method_id,
+ std::bind(&second_address_test_client::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.event_id,
+ std::bind(&second_address_test_client::on_notification, this,
+ std::placeholders::_1, false));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.selective_event_id,
+ std::bind(&second_address_test_client::on_notification, this,
+ std::placeholders::_1, true));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.shutdown_method_id,
+ std::bind(&second_address_test_client::on_shutdown_method_called, this,
+ std::placeholders::_1));
+
+ // register availability for all other services and request their event.
+ app_->register_availability_handler(service_info_.service_id,
+ service_info_.instance_id,
+ std::bind(&second_address_test_client::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3));
+
+ app_->request_service(service_info_.service_id,
+ service_info_.instance_id);
+
+ app_->register_subscription_status_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.eventgroup_id,
+ service_info_.event_id,
+ std::bind(&second_address_test_client::on_subscription_status_changed, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4,
+ std::placeholders::_5, false));
+
+ app_->register_subscription_status_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.selective_eventgroup_id,
+ service_info_.selective_event_id,
+ std::bind(&second_address_test_client::on_subscription_status_changed, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4,
+ std::placeholders::_5, true));
+
+ app_->start();
+ }
+
+ ~second_address_test_client() {
+ send_thread_.join();
+ }
+
+ void subscribe() {
+ std::set<vsomeip::eventgroup_t> its_eventgroups;
+ its_eventgroups.insert(service_info_.eventgroup_id);
+
+ app_->request_event(service_info_.service_id,
+ service_info_.instance_id, service_info_.event_id,
+ its_eventgroups, vsomeip::event_type_e::ET_EVENT);
+
+ its_eventgroups.clear();
+ its_eventgroups.insert(service_info_.selective_eventgroup_id);
+
+ app_->request_event(service_info_.service_id,
+ service_info_.instance_id, service_info_.selective_event_id,
+ its_eventgroups, vsomeip::event_type_e::ET_SELECTIVE_EVENT);
+
+ app_->subscribe(service_info_.service_id, service_info_.instance_id,
+ service_info_.eventgroup_id);
+
+ app_->subscribe(service_info_.service_id, service_info_.instance_id,
+ service_info_.selective_eventgroup_id);
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_DEBUG << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered" : "deregistered") << " on client.";
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance,
+ bool _is_available) {
+
+ VSOMEIP_DEBUG << "Service [" << std::setw(4)
+ << std::setfill('0') << std::hex << _service << "." << _instance
+ << "] is " << (_is_available ? "available":"not available") << " on client.";
+
+ if (_is_available) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_service_available_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+ EXPECT_EQ(service_info_.request_method_id, _message->get_method());
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ auto its_payload = _message->get_payload();
+ std::uint32_t data = static_cast<std::uint32_t>(its_payload->get_data()[0]);
+
+ EXPECT_EQ(reply_received_, data);
+
+ wait_until_reply_received_ = false;
+ reply_received_++;
+ condition_.notify_one();
+ }
+
+ void on_notification(const std::shared_ptr<vsomeip::message> &_message,
+ bool _selective) {
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+
+ static vsomeip::length_t length_last_received_msg(0);
+ EXPECT_GT(_message->get_payload()->get_length(), length_last_received_msg);
+ length_last_received_msg = _message->get_payload()->get_length();
+
+ if (_selective) {
+ EXPECT_EQ(service_info_.selective_event_id, _message->get_method());
+
+ if (++number_selective_events_received_ == second_address_test::number_of_events_to_send) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_selective_events_received_ = false;
+ condition_.notify_one();
+ }
+ } else {
+ EXPECT_EQ(service_info_.event_id, _message->get_method());
+
+ if (++number_events_received_ == second_address_test::number_of_events_to_send) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_events_received_ = false;
+ condition_.notify_one();
+ }
+ }
+ }
+
+ void on_subscription_status_changed(const vsomeip::service_t _service,
+ const vsomeip::instance_t _instance,
+ const vsomeip::eventgroup_t _eventgroup,
+ const vsomeip::event_t _event,
+ const uint16_t error_code,
+ bool _selective) {
+
+ VSOMEIP_DEBUG << "Subscription status changed on client";
+
+ EXPECT_EQ(service_info_.service_id, _service);
+ EXPECT_EQ(service_info_.instance_id, _instance);
+ EXPECT_TRUE((error_code == 0x0u || error_code == 0x7u));
+
+ if (_selective) {
+ EXPECT_EQ(service_info_.selective_eventgroup_id, _eventgroup);
+ EXPECT_EQ(service_info_.selective_event_id, _event);
+
+ if (error_code == 0x0u) { // accepted
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_selective_subscription_accepted_ = false;
+ condition_.notify_one();
+ }
+
+ } else {
+ EXPECT_EQ(service_info_.eventgroup_id, _eventgroup);
+ EXPECT_EQ(service_info_.event_id, _event);
+
+ if (error_code == 0x0u) { // accepted
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_subscription_accepted_ = false;
+ condition_.notify_one();
+ }
+ }
+ }
+
+ void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+ EXPECT_EQ(service_info_.shutdown_method_id, _message->get_method());
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_shutdown_reply_received_ = false;
+ condition_.notify_one();
+ }
+
+ void send() {
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_) {
+ condition_.wait(its_lock);
+ }
+
+ while (wait_until_service_available_) {
+ condition_.wait(its_lock);
+ }
+
+ auto its_message = vsomeip::runtime::get()->create_request(use_tcp_);
+ its_message->set_service(service_info_.service_id);
+ its_message->set_instance(service_info_.instance_id);
+ its_message->set_method(service_info_.request_method_id);
+ its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST);
+
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+
+ VSOMEIP_DEBUG << "Client sending request messages";
+
+ for (std::uint32_t index = 0; index < second_address_test::number_of_messages_to_send; index++) {
+ vsomeip::byte_t *msg_payload = reinterpret_cast<vsomeip::byte_t *>(&index);
+ its_payload->set_data(msg_payload, sizeof(index));
+ its_message->set_payload(its_payload);
+ app_->send(its_message);
+
+ wait_until_reply_received_ = true;
+ message_sent_++;
+
+ while (wait_until_reply_received_) {
+ condition_.wait(its_lock);
+ }
+ }
+
+ VSOMEIP_DEBUG << "Client subscribing events";
+
+ subscribe();
+ while (wait_until_subscription_accepted_ || wait_until_selective_subscription_accepted_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "Client requesting event notification";
+
+ its_message->set_method(service_info_.notify_method_id);
+ its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST_NO_RETURN);
+ its_payload->set_data(&second_address_test::number_of_events_to_send, 1);
+ its_message->set_payload(its_payload);
+ app_->send(its_message);
+
+ VSOMEIP_DEBUG << "Client waiting event notification";
+
+ while (wait_until_events_received_ || wait_until_selective_events_received_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "Client shutting down the service";
+
+ // shutdown service
+ its_message->set_method(service_info_.shutdown_method_id);
+ its_message->set_message_type(vsomeip::message_type_e::MT_REQUEST);
+ app_->send(its_message);
+
+ while (wait_until_shutdown_reply_received_) {
+ if (std::cv_status::timeout == condition_.wait_for(its_lock, std::chrono::seconds(30))) {
+ VSOMEIP_ERROR << "Shutdown request wasn't answered in time!";
+ break;
+ }
+ }
+
+ VSOMEIP_INFO << "Client going down";
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+
+private:
+ struct second_address_test::service_info service_info_;
+ bool use_tcp_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_ = true;
+ bool wait_until_service_available_ = true;
+ bool wait_until_subscription_accepted_ = true;
+ bool wait_until_selective_subscription_accepted_ = true;
+ bool wait_until_shutdown_reply_received_ = true;
+ bool wait_until_reply_received_ = true;
+ bool wait_until_events_received_ = true;
+ bool wait_until_selective_events_received_ = true;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+
+ std::thread send_thread_;
+ std::uint32_t message_sent_ = 0;
+ std::uint32_t reply_received_ = 0;
+ std::uint32_t number_events_received_ = 0;
+ std::uint32_t number_selective_events_received_ = 0;
+};
+
+static bool use_tcp = false;
+
+TEST(someip_event_test, communicate_using_second_address)
+{
+ second_address_test_client its_sample(second_address_test::service, use_tcp);
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ if (argc < 2) {
+ std::cerr << "Please specify a communication mode, like: " << argv[0] << " TCP" << std::endl;
+ std::cerr << "Valid communication modes are UDP or TCP" << std::endl;
+ return 1;
+ }
+
+ if (std::string("TCP")== std::string(argv[1])) {
+ use_tcp = true;
+ } else if (std::string("UDP")== std::string(argv[1])) {
+ use_tcp = false;
+ }
+
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/second_address_tests/second_address_test_globals.hpp b/test/second_address_tests/second_address_test_globals.hpp
new file mode 100644
index 0000000..1909fcd
--- /dev/null
+++ b/test/second_address_tests/second_address_test_globals.hpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2014-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef SECOND_ADDRESS_TEST_GLOBALS_HPP_
+#define SECOND_ADDRESS_TEST_GLOBALS_HPP_
+
+namespace second_address_test {
+
+struct service_info {
+ vsomeip::service_t service_id;
+ vsomeip::instance_t instance_id;
+ vsomeip::eventgroup_t eventgroup_id;
+ vsomeip::event_t event_id;
+ vsomeip::eventgroup_t selective_eventgroup_id;
+ vsomeip::event_t selective_event_id;
+ vsomeip::method_t request_method_id;
+ vsomeip::method_t notify_method_id;
+ vsomeip::method_t shutdown_method_id;
+};
+
+struct service_info service = { 0x3333, 0x1, 0x1, 0x3301, 0x2, 0x3302, 0x1111, 0x2222, 0x1404 };
+
+static constexpr std::uint32_t number_of_messages_to_send = 150;
+static constexpr std::uint8_t number_of_events_to_send = 150;
+}
+
+#endif /* SECOND_ADDRESS_TEST_GLOBALS_HPP_ */
diff --git a/test/second_address_tests/second_address_test_master_starter.sh b/test/second_address_tests/second_address_test_master_starter.sh
new file mode 100755
index 0000000..a7bcc0a
--- /dev/null
+++ b/test/second_address_tests/second_address_test_master_starter.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FAIL=0
+
+if [ $# -lt 2 ]
+then
+ echo "Please pass a operation and communication mode to this script."
+ echo "For example: $0 SERVICE UDP"
+ echo "Valid operation modes include [SERVICE, CLIENT]"
+ echo "Valid communication modes include [UDP, TCP]"
+ exit 1
+fi
+
+OPERATIONMODE=$1
+COMMUNICATIONMODE=$2
+
+if [ "$OPERATIONMODE" = "SERVICE" ]; then
+ MASTER_APPLICATION=second_address_test_service
+ SLAVE_OPERATIONMODE="CLIENT"
+
+ if [ "$COMMUNICATIONMODE" = "TCP" ]; then
+ export VSOMEIP_CONFIGURATION=second_address_test_master_service_tcp.json
+ elif [ "$COMMUNICATIONMODE" = "UDP" ]; then
+ export VSOMEIP_CONFIGURATION=second_address_test_master_service_udp.json
+ fi
+
+elif [ "$OPERATIONMODE" = "CLIENT" ]; then
+ MASTER_APPLICATION=second_address_test_client
+ SLAVE_OPERATIONMODE="SERVICE"
+ export VSOMEIP_CONFIGURATION=second_address_test_master_client.json
+fi
+
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+
+./$MASTER_APPLICATION $COMMUNICATIONMODE &
+PID_MASTER=$!
+
+sleep 1
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "starting offer test on slave LXC second_address_test_slave_starter.sh"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./second_address_test_slave_starter.sh $SLAVE_OPERATIONMODE $COMMUNICATIONMODE\"" &
+elif [ ! -z "$USE_DOCKER" ]; then
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS; sleep 10; ./second_address_test_slave_starter.sh $SLAVE_OPERATIONMODE $COMMUNICATIONMODE" &
+else
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** second_address_test_slave_starter.sh $COMMUNICATIONMODE
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** second_address_test_slave_{udp,tcp}.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+# Wait until all slaves are finished
+for job in $PID_MASTER
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ echo "waiting for $job"
+ wait $job || FAIL=$(($FAIL+1))
+done
+
+kill $PID_VSOMEIPD
+sleep 1
+
+# Check if everything went well
+exit $FAIL
diff --git a/test/second_address_tests/second_address_test_service.cpp b/test/second_address_tests/second_address_test_service.cpp
new file mode 100644
index 0000000..374db0a
--- /dev/null
+++ b/test/second_address_tests/second_address_test_service.cpp
@@ -0,0 +1,252 @@
+// Copyright (C) 2014-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+
+#include <gtest/gtest.h>
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+
+#include "second_address_test_globals.hpp"
+
+class second_address_test_service {
+public:
+ second_address_test_service(struct second_address_test::service_info _service_info) :
+ service_info_(_service_info),
+ app_(vsomeip::runtime::get()->create_application("second_address_test_service")),
+ offer_thread_(std::bind(&second_address_test_service::run, this)) {
+
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+
+ app_->register_state_handler(
+ std::bind(&second_address_test_service::on_state, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.request_method_id,
+ std::bind(&second_address_test_service::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.notify_method_id,
+ std::bind(&second_address_test_service::on_notify, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.shutdown_method_id,
+ std::bind(&second_address_test_service::on_shutdown_method_called, this,
+ std::placeholders::_1));
+
+ app_->register_subscription_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.eventgroup_id,
+ std::bind(&second_address_test_service::subscription_handler,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
+
+ app_->register_subscription_handler(service_info_.service_id,
+ service_info_.instance_id, service_info_.selective_eventgroup_id,
+ std::bind(&second_address_test_service::selective_subscription_handler,
+ this, std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
+
+ app_->start();
+ }
+
+ ~second_address_test_service() {
+ offer_thread_.join();
+ }
+
+ void stop() {
+ app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+private:
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered" : "deregistered") << " on service.";
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ app_->send(vsomeip::runtime::get()->create_response(_message));
+
+ VSOMEIP_WARNING << "************************************************************";
+ VSOMEIP_WARNING << "Shutdown method called on service -> going down!";
+ VSOMEIP_WARNING << "************************************************************";
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_shutdown_method_called_ = false;
+ condition_.notify_one();
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message> &_message) {
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.request_method_id, _message->get_method());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+
+ std::shared_ptr<vsomeip::message> response = vsomeip::runtime::get()->create_response(_message);
+ response->set_payload(_message->get_payload());
+ app_->send(response);
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ messages_received_++;
+
+ if (messages_received_ == second_address_test::number_of_messages_to_send) {
+ wait_until_receive_messages_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_notify(const std::shared_ptr<vsomeip::message> &_message) {
+ EXPECT_EQ(service_info_.service_id, _message->get_service());
+ EXPECT_EQ(service_info_.notify_method_id, _message->get_method());
+ EXPECT_EQ(service_info_.instance_id, _message->get_instance());
+
+ auto its_payload = _message->get_payload();
+ notifications_to_send_ = its_payload->get_data()[0];
+
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_notify_method_called_ = false;
+ condition_.notify_one();
+ }
+
+ void offer() {
+ app_->offer_service(service_info_.service_id, service_info_.instance_id);
+
+ std::set<vsomeip::eventgroup_t> its_eventgroups;
+ its_eventgroups.insert(service_info_.eventgroup_id);
+
+ app_->offer_event(service_info_.service_id, service_info_.instance_id,
+ service_info_.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
+
+ its_eventgroups.clear();
+ its_eventgroups.insert(service_info_.selective_eventgroup_id);
+
+ app_->offer_event(service_info_.service_id, service_info_.instance_id,
+ service_info_.selective_event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_SELECTIVE_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
+ }
+
+ void notify() {
+ EXPECT_TRUE(client_subscribed_);
+ EXPECT_TRUE(client_subscribed_selective_);
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+
+ std::uint32_t i = 0;
+
+ for (; i < notifications_to_send_; i++) {
+ its_payload->set_data(std::vector<vsomeip::byte_t>(i+1, 0x55));
+ app_->notify(service_info_.service_id, service_info_.instance_id,
+ service_info_.event_id, its_payload);
+ }
+
+ for (; i < 2 * notifications_to_send_; i++) {
+ its_payload->set_data(std::vector<vsomeip::byte_t>(i+1, 0x55));
+ app_->notify_one(service_info_.service_id, service_info_.instance_id,
+ service_info_.selective_event_id, its_payload, client_id_);
+ }
+ }
+
+ void run() {
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Running";
+
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
+ offer();
+
+ while (wait_until_receive_messages_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "Service waiting for notify method has been called";
+ while (wait_until_notify_method_called_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "Service notifying events";
+ notify();
+
+ while (wait_until_shutdown_method_called_) {
+ condition_.wait(its_lock);
+ }
+
+ its_lock.unlock();
+ stop();
+ }
+
+ bool subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
+ (void)_uid;
+ (void)_gid;
+ VSOMEIP_DEBUG << __func__ << ": client 0x" << std::hex << std::setw(4) << std::setfill('0') << _client
+ << ((_subscribed) ? " subscribed" : "unsubscribed") << " on service.";
+ client_subscribed_ = _subscribed;
+ return true;
+ }
+
+ bool selective_subscription_handler(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
+ (void)_uid;
+ (void)_gid;
+ VSOMEIP_DEBUG << __func__ << ": client 0x" << std::hex << std::setw(4) << std::setfill('0') << _client
+ << ((_subscribed) ? " subscribed" : "unsubscribed") << " on service.";
+ client_subscribed_selective_ = _subscribed;
+ client_id_ = _client;
+ return true;
+ }
+
+private:
+ struct second_address_test::service_info service_info_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_ = true;
+ bool wait_until_receive_messages_ = true;
+ bool wait_until_notify_method_called_ = true;
+ bool wait_until_shutdown_method_called_ = true;
+ bool client_subscribed_ = false;
+ bool client_subscribed_selective_ = false;
+ vsomeip::client_t client_id_ = 0;
+ std::uint32_t messages_received_ = 0;
+ std::uint8_t notifications_to_send_ = 0;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::thread offer_thread_;
+};
+
+TEST(someip_second_address_test, test_communication_with_client)
+{
+ second_address_test_service its_sample(second_address_test::service);
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/security_config_plugin_tests/conf/security_config_plugin_test_local.json.in b/test/security_config_plugin_tests/conf/security_config_plugin_test_local.json.in
deleted file mode 100644
index a1497dc..0000000
--- a/test/security_config_plugin_tests/conf/security_config_plugin_test_local.json.in
+++ /dev/null
@@ -1,128 +0,0 @@
-{
- "unicast":"127.0.0.1",
- "logging":
- {
- "level":"debug",
- "console":"true",
- "file":
- {
- "enable":"false",
- "path":"/tmp/vsomeip.log"
- },
- "dlt":"false"
- },
- "diagnosis" : "0x63",
- "applications":
- [
- {
- "name":"vsomeipd",
- "id" : "0x6310",
- "plugins" :
- [
- {
- "application_plugin" : "vsomeip-security-config-plugin-mgu"
- }
- ]
- }
- ],
- "security": {
- "policies": [
- {
- "credentials": {
- "deny": [
- {
- "uid": [{"first" : "@TEST_UID@", "last" : "@TEST_UID@"}],
- "gid": [{"first" : "@TEST_GID@", "last" : "@TEST_GID@"}]
- }
- ]
- },
- "deny": {}
- },
- {
- "credentials": {
- "allow": [
- {
- "uid": ["@TEST_UID@"],
- "gid": ["@TEST_GID@"]
- }
- ]
- },
- "allow" :
- {
- "offers":
- [
- {
- "service" : "0xF90F",
- "instance" : "0x01"
- },
- {
- "service" : "0x0101",
- "instance" : "0x63"
- },
- {
- "service" : "0x0103",
- "instance" : "0x63"
- }
- ],
- "requests":
- [
- {
- "service" : "0xF90F",
- "instances" :
- [
- {
- "ids" : ["0x01"],
- "methods" : [ "0x01", "0x02" ]
- }
- ]
- },
- {
- "service" : "0x0103",
- "instances" :
- [
- {
- "ids" : ["0x63"],
- "methods" : [ "0x03", "0x7777" ]
- }
- ]
- },
- {
- "service" : "0x0101",
- "instances" :
- [
- {
- "ids" : ["0x63"],
- "methods" : [ "0x88" ]
- }
- ]
- }
- ]
- }
- }
- ],
- "check_credentials" : "true"
- },
- "security-update-whitelist" :
- {
- "uids" :
- [
- "@TEST_UID@"
- ],
- "services" :
- [
- {"first" : "0x101", "last" : "0x103"},
- "0xf90f"
- ],
- "check-whitelist" : "true"
- },
- "routing":"vsomeipd",
- "routing-credentials" :
- {
- "uid" : "@TEST_UID@",
- "gid" : "@TEST_GID@"
- },
- "service-discovery":
- {
- "enable":"false"
- }
-}
diff --git a/test/security_config_plugin_tests/security_config_plugin_test_client.cpp b/test/security_config_plugin_tests/security_config_plugin_test_client.cpp
deleted file mode 100755
index 9438738..0000000
--- a/test/security_config_plugin_tests/security_config_plugin_test_client.cpp
+++ /dev/null
@@ -1,1045 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include <chrono>
-#include <condition_variable>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <thread>
-#include <map>
-#include <algorithm>
-#include <cstring>
-
-#include <gtest/gtest.h>
-
-#ifndef _WIN32
-#include <signal.h>
-#endif
-
-#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/utility/include/utility.hpp"
-#include "../../implementation/logging/include/logger.hpp"
-#include "../../implementation/configuration/include/policy.hpp"
-
-#include "../security_config_plugin_tests/security_config_plugin_test_globals.hpp"
-class security_config_plugin_test_client;
-static security_config_plugin_test_client* the_client;
-extern "C" void signal_handler(int _signum);
-
-#define GET_LONG_BYTE0(x) ((x) & 0xFF)
-#define GET_LONG_BYTE1(x) (((x) >> 8) & 0xFF)
-#define GET_LONG_BYTE2(x) (((x) >> 16) & 0xFF)
-#define GET_LONG_BYTE3(x) (((x) >> 24) & 0xFF)
-
-class security_config_plugin_test_client {
-public:
- security_config_plugin_test_client(bool _update_only, bool _remove_only, bool _subscribe_only) :
- update_only_(_update_only),
- remove_only_(_remove_only),
- subscribe_only_(_subscribe_only),
- app_(vsomeip::runtime::get()->create_application()),
- wait_until_registered_(true),
- wait_until_security_config_service_available_(true),
- wait_until_control_service_available_(true),
- wait_until_updated_service_101_available_(true),
- wait_until_updated_service_102_available_(true),
- wait_until_method_1_responses_received_(true),
- wait_until_method_2_responses_received_(true),
- number_of_received_responses_method_1(0),
- number_of_received_responses_method_2(0),
- number_of_received_events_1(0),
- number_of_received_events_2(0),
- number_of_received_events_4(0),
- wait_until_notifications_1_received_(true),
- wait_until_notifications_2_received_(true),
- wait_for_stop_(true),
- update_ok_(false),
- removal_ok_(false),
- stop_thread_(std::bind(&security_config_plugin_test_client::wait_for_stop, this)),
- run_thread_(std::bind(&security_config_plugin_test_client::run, this)) {
- if (!app_->init()) {
- ADD_FAILURE() << "Couldn't initialize application";
- return;
- }
-
- // register signal handler
- the_client = this;
- struct sigaction sa_new, sa_old;
- sa_new.sa_handler = signal_handler;
- sa_new.sa_flags = 0;
- sigemptyset(&sa_new.sa_mask);
- ::sigaction(SIGUSR1, &sa_new, &sa_old);
- ::sigaction(SIGINT, &sa_new, &sa_old);
- ::sigaction(SIGTERM, &sa_new, &sa_old);
- ::sigaction(SIGABRT, &sa_new, &sa_old);
-
- app_->register_state_handler(
- std::bind(&security_config_plugin_test_client::on_state, this,
- std::placeholders::_1));
-
- // handle plugin messages
- app_->register_message_handler(security_config_plugin_test::security_config_plugin_serviceinfo.service_id,
- security_config_plugin_test::security_config_plugin_serviceinfo.instance_id,
- vsomeip::ANY_METHOD,
- std::bind(&security_config_plugin_test_client::on_plugin_message, this,
- std::placeholders::_1));
-
- // handle service 0x0101 messages
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- vsomeip::ANY_METHOD,
- std::bind(&security_config_plugin_test_client::on_service_1_message, this,
- std::placeholders::_1));
-
- // handle service 0x0102 messages
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- vsomeip::ANY_METHOD,
- std::bind(&security_config_plugin_test_client::on_service_2_message, this,
- std::placeholders::_1));
-
- // request acl plugin interface service
- app_->register_availability_handler(
- security_config_plugin_test::security_config_plugin_serviceinfo.service_id,
- security_config_plugin_test::security_config_plugin_serviceinfo.instance_id,
- std::bind(&security_config_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3),
- security_config_plugin_test::security_config_plugin_major_version_);
- app_->request_service(
- security_config_plugin_test::security_config_plugin_serviceinfo.service_id,
- security_config_plugin_test::security_config_plugin_serviceinfo.instance_id,
- security_config_plugin_test::security_config_plugin_major_version_, vsomeip::ANY_MINOR);
-
- // request control service which is globally allowed
- app_->register_availability_handler(
- security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id,
- std::bind(&security_config_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3));
- app_->request_service(
- security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
-
- // request service 0x0101 which is globally blacklisted and shall get available after aclUpdate
- app_->register_availability_handler(
- security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- std::bind(&security_config_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3));
- app_->request_service(
- security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
-
-
- // request service 0x0102 which is globally blacklisted and shall get available after aclUpdate
- app_->register_availability_handler(
- security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- std::bind(&security_config_plugin_test_client::on_availability, this,
- std::placeholders::_1, std::placeholders::_2,
- std::placeholders::_3));
- app_->request_service(
- security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
-
- // offer service 0x0100 which is not allowed to be offered at any time
- // (log message "Skip offer!" should be printed by daemon)
- app_->offer_service(0x666, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id);
-
- app_->start();
- }
-
- ~security_config_plugin_test_client() {
- run_thread_.join();
- stop_thread_.join();
-
- }
-
- void on_state(vsomeip::state_type_e _state) {
- VSOMEIP_INFO << "Application " << app_->get_name() << " is "
- << (_state == vsomeip::state_type_e::ST_REGISTERED ?
- "registered." : "deregistered.");
-
- if (_state == vsomeip::state_type_e::ST_REGISTERED) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_registered_ = false;
- condition_.notify_one();
- }
- }
-
- void on_availability(vsomeip::service_t _service,
- vsomeip::instance_t _instance, bool _is_available) {
- if(_is_available) {
- // check plugin interface availability
- if (_service == security_config_plugin_test::security_config_plugin_serviceinfo.service_id &&
- _instance == security_config_plugin_test::security_config_plugin_serviceinfo.instance_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_security_config_service_available_ = false;
- condition_.notify_one();
- }
-
- // check control service availability
- if (_service == security_config_plugin_test::security_config_test_serviceinfo_3.service_id &&
- _instance == security_config_plugin_test::security_config_test_serviceinfo_3.instance_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_control_service_available_ = false;
- condition_.notify_one();
- }
-
- // check updated policy makes service 0x0101 available
- if (_service == security_config_plugin_test::security_config_test_serviceinfo_1.service_id &&
- _instance == security_config_plugin_test::security_config_test_serviceinfo_1.instance_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_updated_service_101_available_ = false;
- condition_.notify_one();
- }
-
- // check updated policy makes service 0x0102 available
- if (_service == security_config_plugin_test::security_config_test_serviceinfo_2.service_id &&
- _instance == security_config_plugin_test::security_config_test_serviceinfo_2.instance_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_updated_service_102_available_ = false;
- condition_.notify_one();
- }
- } else {
-
- }
- }
-
- void on_service_1_message(const std::shared_ptr<vsomeip::message> &_message) {
- if(_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
-
- number_of_received_events_1++;
-
- // event which should never be received
- if (_message->get_method() == 0x8004)
- number_of_received_events_4++;
-
- other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())]++;
- VSOMEIP_INFO
- << "on_service_1_message Received a notification with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _message->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_session() << "] from Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method() <<"] (now have: "
- << std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())] << ")";
-
- std::shared_ptr<vsomeip::payload> its_payload(_message->get_payload());
- EXPECT_EQ(2u, its_payload->get_length());
- EXPECT_EQ((_message->get_service() & 0xFF00 ) >> 8, its_payload->get_data()[0]);
- EXPECT_EQ((_message->get_service() & 0xFF), its_payload->get_data()[1]);
- bool notify = all_notifications_received();
-
- if(notify) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_notifications_1_received_ = false;
- condition_.notify_one();
- }
- } else if (_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- if(_message->get_method() == security_config_plugin_test::security_config_test_serviceinfo_1.method_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- number_of_received_responses_method_1++;
- wait_until_method_1_responses_received_ = false;
- condition_.notify_one();
- }
- }
- }
-
- void on_service_2_message(const std::shared_ptr<vsomeip::message> &_message) {
- if(_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
-
- number_of_received_events_2++;
- other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())]++;
- VSOMEIP_INFO
- << "on_service_2_message Received a notification with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _message->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_session() << "] from Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method() <<"] (now have: "
- << std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
- _message->get_method())] << ")";
-
- std::shared_ptr<vsomeip::payload> its_payload(_message->get_payload());
- EXPECT_EQ(2u, its_payload->get_length());
- EXPECT_EQ((_message->get_service() & 0xFF00 ) >> 8, its_payload->get_data()[0]);
- EXPECT_EQ((_message->get_service() & 0xFF), its_payload->get_data()[1]);
- bool notify = all_notifications_received();
-
- if(notify) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- wait_until_notifications_2_received_ = false;
- condition_.notify_one();
- }
- } else if (_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- if(_message->get_method() == security_config_plugin_test::security_config_test_serviceinfo_2.method_id) {
- std::lock_guard<std::mutex> its_lock(mutex_);
- number_of_received_responses_method_2++;
- wait_until_method_2_responses_received_ = false;
- condition_.notify_one();
- }
- }
- }
-
- void on_plugin_message(const std::shared_ptr<vsomeip::message> &_message) {
- if (_message->get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
- VSOMEIP_INFO
- << "Received a response with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _message->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_session() << "] from Service/Method ["
- << std::setw(4) << std::setfill('0') << std::hex
- << _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method();
-
- std::shared_ptr<vsomeip::payload> pl = _message->get_payload();
- EXPECT_EQ( vsomeip::return_code_e::E_OK, _message->get_return_code());
-
- uint32_t length = pl->get_length();
- EXPECT_EQ(length, (uint32_t) 0x01);
-
- // expect status_success_ returned by plugin interface
- bool success(false);
- uint8_t* dataptr = pl->get_data();
- for(uint32_t i = 0; i< pl->get_length(); i++) {
- std::cout << "payload data: " << std::hex << (uint32_t) dataptr[i] << std::endl;
- EXPECT_EQ(dataptr[i], 0);
- if (dataptr[i] == 0x00) {
- success = true;
- }
- }
- if (success) {
- // updateAcl answer
- if (_message->get_service() == security_config_plugin_test::security_config_plugin_serviceinfo.service_id
- &&_message->get_method() == security_config_plugin_test::security_config_plugin_serviceinfo.method_id) {
- update_ok_ = true;
- }
-
- // removeAcl answer
- if (_message->get_service() == security_config_plugin_test::security_config_plugin_serviceinfo.service_id
- &&_message->get_method() == security_config_plugin_test::security_config_plugin_serviceinfo_reset.method_id) {
- removal_ok_ = true;
- }
- }
- }
- }
-
- bool all_notifications_received() {
- return std::all_of(
- other_services_received_notification_.cbegin(),
- other_services_received_notification_.cend(),
- [&](const std::map<std::pair<vsomeip::service_t,
- vsomeip::method_t>, std::uint32_t>::value_type& v)
- {
- if (v.second == security_config_plugin_test::notifications_to_send) {
- return true;
- } else {
- if (v.second >= security_config_plugin_test::notifications_to_send) {
- VSOMEIP_WARNING
- << " Received multiple initial events from service/instance: "
- << std::setw(4) << std::setfill('0') << std::hex << v.first.first
- << "."
- << std::setw(4) << std::setfill('0') << std::hex << v.first.second
- << " number of received events: " << v.second
- << ". This is caused by StopSubscribe/Subscribe messages and/or"
- << " service offered via UDP and TCP";
- return false;
- } else {
- return false;
- }
- }
- }
- );
- }
-
- void handle_signal(int _signum) {
- VSOMEIP_DEBUG << "Catched signal, going down ("
- << std::dec <<_signum << ")";
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
- wait_for_stop_ = false;
- stop_condition_.notify_one();
- }
-
- void wait_for_stop() {
- {
- std::unique_lock<std::mutex> its_lock(stop_mutex_);
- while (wait_for_stop_) {
- stop_condition_.wait(its_lock);
- }
-
- EXPECT_TRUE(update_ok_);
-
- // Todo if policy was removed, the plugin answer is not allowed to be sent back as plugin service is blacklisted again
- //EXPECT_TRUE(removal_ok_);
-
- VSOMEIP_INFO << "Received all responses from plugin, going down";
- }
- app_->clear_all_handler();
- app_->stop();
- }
-
- void call_acl_deployment_interface(bool _updateAcl) {
-
- uint32_t user_id = (uint32_t) getuid();
- uint32_t group_id = (uint32_t) getgid();
-
- if(update_only_ || remove_only_) {
- user_id = 1001;
- group_id = 1001;
- }
-
- uint8_t uid_byte_0 = (uint8_t) GET_LONG_BYTE3(user_id);
- uint8_t uid_byte_1 = GET_LONG_BYTE2(user_id);
- uint8_t uid_byte_2 = GET_LONG_BYTE1(user_id);
- uint8_t uid_byte_3 = GET_LONG_BYTE0(user_id);
-
- uint8_t gid_byte_0 = (uint8_t) GET_LONG_BYTE3(group_id);
- uint8_t gid_byte_1 = GET_LONG_BYTE2(group_id);
- uint8_t gid_byte_2 = GET_LONG_BYTE1(group_id);
- uint8_t gid_byte_3 = GET_LONG_BYTE0(group_id);
-
- // send policy payload which also contains part of global security json to allow answer for removeAcl calls
- // updateAcl payload:
- /*
- Security configuration: UID: 0x3e8
- Security configuration: GID: 0x3e8
- Security configuration: RQUESTS POLICY SIZE: 4
- ALLOWED REQUESTS Service: 0x101
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x1 last: 0x5
- first: 0x8001 last: 0x8003
- ALLOWED REQUESTS Service: 0x102
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x1 last: 0x5
- first: 0x8001 last: 0x8003
- ALLOWED REQUESTS Service: 0x103
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x3 last: 0x3
- first: 0x7777 last: 0x7777
- ALLOWED REQUESTS Service: 0xF90F
- Instances:
- first: 0x1 last: 0x1
- Methods:
- first: 0x1 last: 0x1
- first: 0x2 last: 0x2
- Security configuration: OFFER POLICY SIZE: 4
- ALLOWED OFFERS Service: 0x101
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0x102
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0x103
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0xF90F
- Instances:
- first: 0x1 last: 0x1
- */
- std::array<unsigned char, 280> update_payload =
- {{ uid_byte_0, uid_byte_1, uid_byte_2, uid_byte_3, gid_byte_0, gid_byte_1, gid_byte_2, gid_byte_3,
- 0x00, 0x00, 0x00, 0xb8, 0xF9, 0x0F, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00,
- 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x01, 0x77, 0x77, 0x01, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x80, 0x01, 0x80, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02,
- 0x80, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x40, 0xF9, 0x0F, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x01, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63}};
-
- // removeAcl payload for UID 12345 GID 4567 or UID: 1000 -> 0x03, 0xe8,
- std::array<unsigned char, 8> remove_payload = {{uid_byte_0, uid_byte_1, uid_byte_2, uid_byte_3, gid_byte_0, gid_byte_1, gid_byte_2, gid_byte_3}};
-
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
- its_request->set_service(security_config_plugin_test::security_config_plugin_serviceinfo.service_id);
- its_request->set_instance(security_config_plugin_test::security_config_plugin_serviceinfo.instance_id);
- std::vector<vsomeip::byte_t> its_payload;
-
- if (_updateAcl) {
- its_request->set_method(security_config_plugin_test::security_config_plugin_serviceinfo.method_id);
- for (uint32_t i=0; i < update_payload.size(); i++) {
- its_payload.push_back(update_payload[i]);
- }
- } else {
- its_request->set_method(security_config_plugin_test::security_config_plugin_serviceinfo_reset.method_id);
- for (uint32_t i=0; i < remove_payload.size(); i++) {
- its_payload.push_back(remove_payload[i]);
- }
- }
- its_request->set_payload(vsomeip::runtime::get()->create_payload(its_payload));
- app_->send(its_request);
- }
-
- void call_try_offer() {
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
- its_request->set_service(security_config_plugin_test::security_config_test_serviceinfo_3.service_id);
- its_request->set_instance(security_config_plugin_test::security_config_test_serviceinfo_3.instance_id);
- its_request->set_method(security_config_plugin_test::security_config_test_serviceinfo_3.method_id);
- app_->send(its_request);
- }
-
- void call_method(vsomeip::service_t _service, vsomeip::instance_t _instance, vsomeip::method_t _method) {
- std::shared_ptr<vsomeip::message> its_request = vsomeip::runtime::get()->create_request();
- its_request->set_service(_service);
- its_request->set_instance(_instance);
- its_request->set_method(_method);
- app_->send(its_request);
- }
-
- void run() {
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_registered_) {
- condition_.wait(its_lock);
- }
- }
-
- // payload for testing utility::parse_policy()
- /*
- Security configuration: UID: 0x01
- Security configuration: GID: 0x01
- Security configuration: RQUESTS POLICY SIZE: 4
- ALLOWED REQUESTS Service: 0x101
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x1 last: 0x5
- first: 0x8001 last: 0x8003
- ALLOWED REQUESTS Service: 0x102
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x1 last: 0x5
- first: 0x8001 last: 0x8003
- ALLOWED REQUESTS Service: 0x103
- Instances:
- first: 0x63 last: 0x63
- Methods:
- first: 0x3 last: 0x3
- first: 0x7777 last: 0x7777
- ALLOWED REQUESTS Service: 0xF90F
- Instances:
- first: 0x1 last: 0x1
- Methods:
- first: 0x1 last: 0x1
- first: 0x2 last: 0x2
- Security configuration: OFFER POLICY SIZE: 4
- ALLOWED OFFERS Service: 0x101
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0x102
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0x103
- Instances:
- first: 0x63 last: 0x63
- ALLOWED OFFERS Service: 0xF90F
- Instances:
- first: 0x1 last: 0x1
- */
- std::array<unsigned char, 280> policy_update_payload =
- {{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, // uid / gid
- 0x00, 0x00, 0x00, 0xb8,
- 0xF9, 0x0F, // 0xf90f -> service ID at array index 12 - 13
- 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a,
- 0x00, 0x00, 0x00, 0x02, // -> union length = 2 byte
- 0x00, 0x00, 0x00, 0x01, // -> union type is single instance ID
- 0x00, 0x01, // -> single instance id 0x1 at array index 30 - 31
- 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00,
- 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x01, 0x77, 0x77, 0x01, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x18,
- 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x02, // -> union type is ID range
- 0x00, 0x01, // first 0x01 at array index 132 - 133
- 0x00, 0x05, // last 0x05 at array index 134 - 135
- 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x80, 0x01, 0x80, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02,
- 0x80, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x40, 0xF9, 0x0F, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x01, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63}};
-
- // Check if parse_policy() correctly handles invalid service, instance and method ID's / ranges.
- uint32_t its_uid = 0x00;
- uint32_t its_gid = 0x00;
- uint32_t its_remaining_bytes_ = policy_update_payload.size();
- std::shared_ptr<vsomeip::policy> its_policy(std::make_shared<vsomeip::policy>());
- const vsomeip::byte_t* its_buffer_ptr = policy_update_payload.data();
-
- // valid policy
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set request service ID to invalid value 0x00
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_service = policy_update_payload;
- // set service ID from 0xf90f to 0x00
- policy_invalid_service[12] = 0x00;
- policy_invalid_service[13] = 0x00;
- its_buffer_ptr = policy_invalid_service.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- // set request service ID to invalid value 0xFFFF
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_service_2 = policy_update_payload;
- // set service ID from 0xf90f to 0x00
- policy_invalid_service_2[12] = 0xFF;
- policy_invalid_service_2[13] = 0xFF;
- its_buffer_ptr = policy_invalid_service_2.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- // set request single instance ID to invalid value 0x00 which shall be ignored
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_instance = policy_update_payload;
- // set instance ID of service 0xf90f to 0x00
- policy_invalid_instance[30] = 0x00;
- policy_invalid_instance[31] = 0x00;
- its_buffer_ptr = policy_invalid_instance.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set request single instance ID to valid value 0xFFFF
- // meaning ANY_INSTANCE range from 0x01 to 0xFFFE
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_valid_instance = policy_update_payload;
- // set instance ID of service 0xf90f to 0xFFFF
- policy_valid_instance[30] = 0xFF;
- policy_valid_instance[31] = 0xFF;
- its_buffer_ptr = policy_valid_instance.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set first of range to 0x00 and last to 0x05 which is invalid
- // the range shall be adjusted to be 0x01 to 0x05 without giving an error
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_method = policy_update_payload;
- policy_invalid_method[132] = 0x00;
- policy_invalid_method[133] = 0x00;
- its_buffer_ptr = policy_invalid_method.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set first of range to 0x01 and last to 0x00 which is invalid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_method_2 = policy_update_payload;
- policy_invalid_method_2[134] = 0x00;
- policy_invalid_method_2[135] = 0x00;
- its_buffer_ptr = policy_invalid_method_2.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- // set first of range to 0x06 and last to 0x05 which is invalid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_method_3 = policy_update_payload;
- policy_invalid_method_3[132] = 0x00;
- policy_invalid_method_3[133] = 0x06;
- its_buffer_ptr = policy_invalid_method_3.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- // set first of range to 0x01 and last to 0xFFFF which is invalid as first and last
- // must be set to 0xFFFF if ANY_METHOD / ANY_INSTANCE shall be specified
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_method_4 = policy_update_payload;
- policy_invalid_method_4[134] = 0xFF;
- policy_invalid_method_4[135] = 0xFF;
- its_buffer_ptr = policy_invalid_method_4.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- // set first of range to 0xFFFF and last to 0xFFFF which is valid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_valid_method = policy_update_payload;
- policy_valid_method[132] = 0xFF;
- policy_valid_method[133] = 0xFF;
- policy_valid_method[134] = 0xFF;
- policy_valid_method[135] = 0xFF;
- its_buffer_ptr = policy_valid_method.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set first of range to 0x01 and last to 0x01 which is valid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_valid_method_2 = policy_update_payload;
- policy_valid_method_2[132] = 0x00;
- policy_valid_method_2[133] = 0x01;
- policy_valid_method_2[134] = 0x00;
- policy_valid_method_2[135] = 0x01;
- its_buffer_ptr = policy_valid_method_2.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set first of range to 0x01 and last to 0xFFFE which is valid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_valid_method_3 = policy_update_payload;
- policy_valid_method_3[132] = 0x00;
- policy_valid_method_3[133] = 0x01;
- policy_valid_method_3[134] = 0xFF;
- policy_valid_method_3[135] = 0xFE;
- its_buffer_ptr = policy_valid_method_3.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), true);
-
- // set first of range to 0xFFFF and last to 0x05 which is invalid
- its_remaining_bytes_ = policy_update_payload.size();
- std::array<unsigned char, 280> policy_invalid_method_6 = policy_update_payload;
- policy_invalid_method_6[132] = 0xFF;
- policy_invalid_method_6[133] = 0xFF;
- its_buffer_ptr = policy_invalid_method_6.data();
- EXPECT_EQ(::vsomeip::utility::parse_policy(its_buffer_ptr, its_remaining_bytes_, its_uid, its_gid, its_policy), false);
-
- VSOMEIP_INFO << "waiting until security_config plugin service is available!";
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_security_config_service_available_) {
- condition_.wait(its_lock);
- }
- wait_until_security_config_service_available_ = true;
- VSOMEIP_INFO << "security config plugin service is available";
- }
-
- if (update_only_) {
- VSOMEIP_INFO << "ONLY Calling updateAcl with user ID 1001 and exit -> shall allow method calls and events...";
- call_acl_deployment_interface(true);
- sleep(1);
- exit(0);
- } else if (remove_only_) {
- VSOMEIP_INFO << "ONLY Calling removeAcl with user ID 1001 and exit -> removes complete allow policy (disables all method calls / events)";
- call_acl_deployment_interface(false);
- sleep(1);
- exit(0);
- } else if (subscribe_only_) {
- VSOMEIP_INFO << "Subscribe to still blacklisted event 0x8004 and do not expect an event!";
- // check that events for service 0x101 and event 0x8004 are never received as policy does not allow it
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id);
- app_->request_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8004),
- its_eventgroups, true);
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(0x8004));
- sleep(1);
- EXPECT_EQ(number_of_received_events_4, (uint32_t) 0);
- exit(0);
- }
-
- VSOMEIP_INFO << "Do method calls to blacklisted service/methods 0x101/0x01 and 0x102/0x02 and do not expect any response";
-
- // do method calls to blacklisted services -> no response expected
- call_method(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.method_id);
-
- call_method(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.method_id);
-
-
- // check that no events are received before policy allows subscribing
- VSOMEIP_INFO << "Subscribe to blacklisted service/event 0x101/0x8001 and do not expect any event";
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id);
-
- app_->request_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_1.event_id),
- its_eventgroups, true);
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_1.event_id));
-
- sleep(1);
-
- EXPECT_EQ(number_of_received_responses_method_1, (uint32_t) 0);
- EXPECT_EQ(number_of_received_responses_method_2, (uint32_t) 0);
- EXPECT_EQ(number_of_received_events_1, (uint32_t) 0);
- EXPECT_EQ(number_of_received_events_2, (uint32_t) 0);
-
- VSOMEIP_INFO << "Calling updateAcl which shall allow method calls and events...";
- call_acl_deployment_interface(true);
- VSOMEIP_INFO << "wait until control service is available ...";
-
- // wait until control service is available
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_control_service_available_) {
- condition_.wait(its_lock);
- }
- wait_until_control_service_available_ = true;
- VSOMEIP_INFO << "local control service 0x0103 available";
- }
- // Todo wait until plugin has answered the acl update
- sleep(1);
-
- // Send message_try_offer request in order to trigger stopoffer and reoffering of now allowed services
- VSOMEIP_INFO << "trigger stopoffer / reoffer of service 0x0101 and 0x0102 ...";
- call_try_offer();
-
- // try requesting the services 0x0101 and 0x0102 again
- // (initial request service was rejected before which causes no routing info to be sent after policy update)
- app_->request_service(
- security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
-
- app_->request_service(
- security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id,
- vsomeip::ANY_MAJOR, vsomeip::ANY_MINOR);
-
- // check that services 0x0101 get available after acl update
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_updated_service_101_available_) {
- condition_.wait(its_lock);
- }
- wait_until_updated_service_101_available_ = true;
- VSOMEIP_INFO << "By policy update allowed service 0x0101 got available";
- }
-
- // check that services 0x0102 get available after acl update
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_updated_service_102_available_) {
- condition_.wait(its_lock);
- }
- wait_until_updated_service_102_available_ = true;
- VSOMEIP_INFO << "By policy update allowed service 0x0102 got available";
- }
-
- VSOMEIP_INFO << "Call now allowed service/methods 0x101/0x01 and 0x102/0x02 after allow policy update and expect responses!";
-
- // call method ids which should now be allowed to be requested
- call_method(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.method_id);
-
- // check that method calls are working
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_method_1_responses_received_) {
- condition_.wait(its_lock);
- }
- wait_until_method_1_responses_received_ = true;
- VSOMEIP_INFO << "By policy update allowed response to request of service/instance/method "
- << std::hex << security_config_plugin_test::security_config_test_serviceinfo_1.service_id
- << "/" << security_config_plugin_test::security_config_test_serviceinfo_1.instance_id
- << "/" << security_config_plugin_test::security_config_test_serviceinfo_1.method_id << " received";
- }
-
- call_method(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.method_id);
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_method_2_responses_received_) {
- condition_.wait(its_lock);
- }
- wait_until_method_2_responses_received_ = true;
- VSOMEIP_INFO << "By policy update allowed response to request of service/instance/method "
- << std::hex << security_config_plugin_test::security_config_test_serviceinfo_2.service_id
- << "/" << security_config_plugin_test::security_config_test_serviceinfo_2.instance_id
- << "/" << security_config_plugin_test::security_config_test_serviceinfo_2.method_id << " received";
- }
-
- EXPECT_EQ(number_of_received_responses_method_1, (uint32_t) 1);
- EXPECT_EQ(number_of_received_responses_method_2, (uint32_t) 1);
-
- // check that events are received now
- VSOMEIP_INFO << "Subscribe to service 0x101 / 0x102 events 0x8001 / 0x8002 and expect initial events";
- app_->request_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_1.event_id),
- its_eventgroups, true);
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_1.event_id));
-
- // check that from first service events were received
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_notifications_1_received_) {
- condition_.wait(its_lock);
- }
- wait_until_notifications_1_received_ = true;
- VSOMEIP_INFO << "notifications from service 0x0101 received";
- }
-
- app_->request_event(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_2.event_id),
- its_eventgroups, true);
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(security_config_plugin_test::security_config_test_serviceinfo_2.event_id));
-
- // check that from second service events were received
- {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (wait_until_notifications_2_received_) {
- condition_.wait(its_lock);
- }
- wait_until_notifications_2_received_ = true;
- VSOMEIP_INFO << "notifications from service 0x0102 received";
- }
-
- VSOMEIP_INFO << "Subscribe to still blacklisted event 0x8004 and do not expect an event!";
- // check that events for service 0x101 and event 0x8004 are never received as policy does not allow it
- app_->request_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8004),
- its_eventgroups, true);
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(0x8004));
- sleep(1);
- EXPECT_EQ(number_of_received_events_4, (uint32_t) 0);
-
-
- // unsusbcribe
- app_->unsubscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id);
-
- app_->unsubscribe(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.eventgroup_id);
-
- // tigger removeAcl (removes the whole configuration for uid 1000)
- VSOMEIP_INFO << "Calling removeAcl which removes complete allow policy (disables all method calls / events)";
- call_acl_deployment_interface(false);
-
- //Todo wait for plugin response
- sleep(1);
-
- VSOMEIP_INFO << "Call now blacklisted methods after complete allow policy removal and do not expect any response!";
- // no response expected as policy was removed
- call_method(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.method_id);
-
- call_method(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.method_id);
-
- // check that no more initial events are received now on resubscribe
- VSOMEIP_INFO << "Subscribe to now blacklisted events after complete allow policy removal and do not expect initial events!";
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id);
-
- app_->subscribe(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.eventgroup_id);
-
- sleep(1);
-
- EXPECT_EQ(number_of_received_responses_method_1, (uint32_t) 1);
- EXPECT_EQ(number_of_received_responses_method_2, (uint32_t) 1);
- EXPECT_EQ(number_of_received_events_1, (uint32_t) 1);
- EXPECT_EQ(number_of_received_events_2, (uint32_t) 1);
-
- {
- std::lock_guard<std::mutex> its_lock(stop_mutex_);
- sleep(1);
- wait_for_stop_ = false;
- stop_condition_.notify_one();
- }
- }
-
-private:
- bool update_only_;
- bool remove_only_;
- bool subscribe_only_;
- std::shared_ptr<vsomeip::application> app_;
- bool wait_until_registered_;
- bool wait_until_security_config_service_available_;
- bool wait_until_control_service_available_;
- bool wait_until_updated_service_101_available_;
- bool wait_until_updated_service_102_available_;
- bool wait_until_method_1_responses_received_;
- bool wait_until_method_2_responses_received_;
- uint32_t number_of_received_responses_method_1;
- uint32_t number_of_received_responses_method_2;
- uint32_t number_of_received_events_1;
- uint32_t number_of_received_events_2;
- uint32_t number_of_received_events_4;
- bool wait_until_notifications_1_received_;
- bool wait_until_notifications_2_received_;
- std::mutex mutex_;
- std::condition_variable condition_;
-
- bool wait_for_stop_;
- bool update_ok_;
- bool removal_ok_;
-
- std::mutex stop_mutex_;
- std::condition_variable stop_condition_;
- std::thread stop_thread_;
-
- std::thread run_thread_;
- std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_notification_;
-
-};
-
-#if 1
-static bool only_update;
-static bool only_remove;
-static bool only_subscribe;
-#endif
-
-extern "C" void signal_handler(int signum) {
- the_client->handle_signal(signum);
-}
-
-TEST(someip_security_config_plugin_test, update_remove_security_config_policy)
-{
- security_config_plugin_test_client its_sample(only_update, only_remove, only_subscribe);
-}
-
-#ifndef _WIN32
-int main(int argc, char** argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
-#if 1
- only_update = false;
- only_remove = false;
- only_subscribe = false;
- if (argc > 1) {
- if(std::string("UPDATE") == std::string(argv[1])) {
- only_update = true;
- } else if(std::string("REMOVE") == std::string(argv[1])) {
- only_remove = true;
- } else if (std::string("SUBSCRIBE") == std::string(argv[1])) {
- only_subscribe = true;
- }
- }
-
-#endif
-
- return RUN_ALL_TESTS();
-}
-#endif
diff --git a/test/security_config_plugin_tests/security_config_plugin_test_globals.hpp b/test/security_config_plugin_tests/security_config_plugin_test_globals.hpp
deleted file mode 100755
index 0e2f456..0000000
--- a/test/security_config_plugin_tests/security_config_plugin_test_globals.hpp
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#ifndef SECURITY_CONFIG_PLUGIN_TEST_GLOBALS_HPP_
-#define SECURITY_CONFIG_PLUGIN_TEST_GLOBALS_HPP_
-
-namespace security_config_plugin_test {
-
-struct service_info {
- vsomeip::service_t service_id;
- vsomeip::instance_t instance_id;
- vsomeip::method_t method_id;
- vsomeip::event_t event_id;
- vsomeip::eventgroup_t eventgroup_id;
-};
-
-// ACL interface of plugin (this service is allowed to be offered in global security config)
-static constexpr service_info security_config_plugin_serviceinfo = { 0xF90F, 0x01, 0x1, 0x0, 0x0 };
-static constexpr vsomeip::major_version_t security_config_plugin_major_version_ = 0x01;
-static constexpr vsomeip::minor_version_t security_config_plugin_minor_version_ = 0x00;
-
-static constexpr service_info security_config_plugin_serviceinfo_reset = { 0xF90F, 0x01, 0x2, 0x0, 0x0 };
-
-// services to test policy (these services are denied to be offered in global security config and will be allowed via updateAcl)
-static constexpr service_info security_config_test_serviceinfo_1 = { 0x0101, 0x63, 0x1, 0x8001, 0x1 };
-static constexpr service_info security_config_test_serviceinfo_2 = { 0x0102, 0x63, 0x2, 0x8002, 0x1 };
-
-// service to control offering of above service instances via client method call (this service is allowed to be offered in global security config)
-static constexpr service_info security_config_test_serviceinfo_3 = { 0x0103, 0x63, 0x3, 0x0, 0x0 };
-
-
-static constexpr int notifications_to_send = 1;
-}
-
-#endif /* SECURITY_CONFIG_PLUGIN_TEST_GLOBALS_HPP_ */
diff --git a/test/security_config_plugin_tests/security_config_plugin_test_local_starter.sh b/test/security_config_plugin_tests/security_config_plugin_test_local_starter.sh
deleted file mode 100755
index dd1939c..0000000
--- a/test/security_config_plugin_tests/security_config_plugin_test_local_starter.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# Purpose: This script is needed to start the services with
-# one command. This is necessary as ctest - which is used to run the
-# tests - isn't able to start multiple binaries for one testcase. Therefore
-# the testcase simply executes this script. This script then runs the services
-# and checks that all exit successfully.
-
-FAIL=0
-
-cat <<End-of-message
-*******************************************************************************
-*******************************************************************************
-** Running first test
-*******************************************************************************
-*******************************************************************************
-End-of-message
-
-# Array for client pids
-CLIENT_PIDS=()
-export VSOMEIP_CONFIGURATION=security_config_plugin_test_local.json
-
-export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(readlink -f ../plugins/mgu)
-# start daemon
-../daemon/./vsomeipd &
-PID_VSOMEIPD=$!
-
-sleep 1
-
-# Start the service
-export VSOMEIP_APPLICATION_NAME=service-sample
-./security_config_plugin_test_service &
-PID_SERVICE=$!
-
-sleep 1
-
-# Start the client
-export VSOMEIP_APPLICATION_NAME=client-sample
-./security_config_plugin_test_client &
-CLIENT_PIDS+=($!)
-
-# Wait until all clients are finished
-for job in ${CLIENT_PIDS[*]}
-do
- # Fail gets incremented if a client exits with a non-zero exit code
- wait $job || FAIL=$(($FAIL+1))
-done
-
-kill $PID_VSOMEIPD
-sleep 1
-
-kill $PID_SERVICE
-sleep 1
-
-# Check if everything went well
-if [ $FAIL -eq 0 ]
-then
- exit 0
-else
- exit 1
-fi
diff --git a/test/security_config_plugin_tests/security_config_plugin_test_service.cpp b/test/security_config_plugin_tests/security_config_plugin_test_service.cpp
deleted file mode 100644
index 40a7f8c..0000000
--- a/test/security_config_plugin_tests/security_config_plugin_test_service.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (C) 2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-#include "security_config_plugin_test_service.hpp"
-#include "../security_config_plugin_tests/security_config_plugin_test_globals.hpp"
-
-security_config_plugin_test_service::security_config_plugin_test_service() :
- app_(vsomeip::runtime::get()->create_application()),
- is_registered_(false),
- blocked_(false),
- number_of_received_messages_(0),
- offer_thread_(std::bind(&security_config_plugin_test_service::run, this)) {
-}
-
-bool security_config_plugin_test_service::init() {
- std::lock_guard<std::mutex> its_lock(mutex_);
-
- if (!app_->init()) {
- ADD_FAILURE() << "Couldn't initialize application";
- return false;
- }
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- vsomeip::ANY_METHOD,
- std::bind(&security_config_plugin_test_service::on_message, this,
- std::placeholders::_1));
-
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- vsomeip::ANY_METHOD,
- std::bind(&security_config_plugin_test_service::on_message, this,
- std::placeholders::_1));
-
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.method_id,
- std::bind(&security_config_plugin_test_service::on_message_try_offer, this,
- std::placeholders::_1));
-
- app_->register_message_handler(security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id,
- vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN,
- std::bind(&security_config_plugin_test_service::on_message_shutdown, this,
- std::placeholders::_1));
-
- app_->register_state_handler(
- std::bind(&security_config_plugin_test_service::on_state, this,
- std::placeholders::_1));
-
- // offer allowed field 0x8001 eventgroup 0x01
- std::set<vsomeip::eventgroup_t> its_eventgroups;
- its_eventgroups.insert(security_config_plugin_test::security_config_test_serviceinfo_1.eventgroup_id);
-
- app_->offer_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8001), its_eventgroups, true);
-
- // offer never allowed field 0x8004 eventgroup 0x01
- app_->offer_event(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8004), its_eventgroups, true);
-
-
- // offer allowed field 0x8002 eventgroup 0x01
- app_->offer_event(security_config_plugin_test::security_config_test_serviceinfo_2.service_id, security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- static_cast<vsomeip::event_t>(0x8002), its_eventgroups, true);
-
- // set value to fields
- std::shared_ptr<vsomeip::payload> its_payload =
- vsomeip::runtime::get()->create_payload();
- vsomeip::byte_t its_data[2] = {static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_1.service_id & 0xFF00) >> 8),
- static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_1.service_id & 0xFF))};
- its_payload->set_data(its_data, 2);
-
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8001), its_payload);
-
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8004), its_payload);
-
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_2.service_id, security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- static_cast<vsomeip::event_t>(0x8002), its_payload);
-
- return true;
-}
-
-void security_config_plugin_test_service::start() {
- VSOMEIP_INFO << "Starting...";
- app_->start();
-}
-
-void security_config_plugin_test_service::stop() {
- VSOMEIP_INFO << "Stopping...";
- app_->clear_all_handler();
- app_->stop();
-}
-
-void security_config_plugin_test_service::join_offer_thread() {
- if (offer_thread_.joinable()) {
- offer_thread_.join();
- }
-}
-
-void security_config_plugin_test_service::offer() {
- // offer the initially in global security config file denied service / instance
- app_->offer_service(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id);
-
- // offer the initially in global security config file denied service / instance
- app_->offer_service(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id);
-
- // offer the allowed control service / instance
- app_->offer_service(security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id);
-}
-
-void security_config_plugin_test_service::stop_offer() {
- app_->stop_offer_service(security_config_plugin_test::security_config_test_serviceinfo_1.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_1.instance_id);
- app_->stop_offer_service(security_config_plugin_test::security_config_test_serviceinfo_2.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_2.instance_id);
- app_->stop_offer_service(security_config_plugin_test::security_config_test_serviceinfo_3.service_id,
- security_config_plugin_test::security_config_test_serviceinfo_3.instance_id);
-}
-
-void security_config_plugin_test_service::on_state(vsomeip::state_type_e _state) {
- VSOMEIP_INFO << "Application " << app_->get_name() << " is "
- << (_state == vsomeip::state_type_e::ST_REGISTERED ? "registered." :
- "deregistered.");
-
- if(_state == vsomeip::state_type_e::ST_REGISTERED) {
- if(!is_registered_) {
- is_registered_ = true;
- std::lock_guard<std::mutex> its_lock(mutex_);
- blocked_ = true;
- // "start" the run method thread
- condition_.notify_one();
- }
- }
- else {
- is_registered_ = false;
- }
-}
-
-void security_config_plugin_test_service::on_message(const std::shared_ptr<vsomeip::message>& _request) {
- VSOMEIP_INFO << "Received a message with Client/Session [" << std::setw(4)
- << std::setfill('0') << std::hex << _request->get_client() << "/"
- << std::setw(4) << std::setfill('0') << std::hex
- << _request->get_session() << "] method: " << _request->get_method() ;
-
- // send response
- std::shared_ptr<vsomeip::message> its_response =
- vsomeip::runtime::get()->create_response(_request);
-
- app_->send(its_response, true);
-
- number_of_received_messages_++;
- if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_SECURITY_TESTS) {
- VSOMEIP_INFO << "Received all messages!";
- }
-}
-
-void security_config_plugin_test_service::on_message_shutdown(
- const std::shared_ptr<vsomeip::message>& _request) {
- (void)_request;
- VSOMEIP_INFO << "Shutdown method was called, going down now.";
- stop();
-}
-
-void security_config_plugin_test_service::on_message_try_offer(
- const std::shared_ptr<vsomeip::message>& _request) {
- (void)_request;
- VSOMEIP_INFO << "Try offering method was called.";
- stop_offer();
- offer();
-
- // set value to fields
- std::shared_ptr<vsomeip::payload> its_payload =
- vsomeip::runtime::get()->create_payload();
- vsomeip::byte_t its_data[2] = {static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_1.service_id & 0xFF00) >> 8),
- static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_1.service_id & 0xFF))};
- its_payload->set_data(its_data, 2);
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8001), its_payload);
-
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_1.service_id, security_config_plugin_test::security_config_test_serviceinfo_1.instance_id,
- static_cast<vsomeip::event_t>(0x8004), its_payload);
-
- // set value to fields
- std::shared_ptr<vsomeip::payload> its_payload_2 =
- vsomeip::runtime::get()->create_payload();
- vsomeip::byte_t its_data_2[2] = {static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_2.service_id & 0xFF00) >> 8),
- static_cast<vsomeip::byte_t>((security_config_plugin_test::security_config_test_serviceinfo_2.service_id & 0xFF))};
- its_payload_2->set_data(its_data_2, 2);
- app_->notify(security_config_plugin_test::security_config_test_serviceinfo_2.service_id, security_config_plugin_test::security_config_test_serviceinfo_2.instance_id,
- static_cast<vsomeip::event_t>(0x8002), its_payload_2);
-
-}
-
-void security_config_plugin_test_service::run() {
- std::unique_lock<std::mutex> its_lock(mutex_);
- while (!blocked_)
- condition_.wait(its_lock);
-
- offer();
-}
-
-TEST(someip_security_test, basic_security_update_) {
- security_config_plugin_test_service test_service;
- if (test_service.init()) {
- test_service.start();
- test_service.join_offer_thread();
- }
-}
-
-#ifndef _WIN32
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-#endif
diff --git a/test/security_tests/conf/security_test_config_client_external_allow.json.in b/test/security_tests/conf/security_test_config_client_external_allow.json.in
index 531c620..e73f3db 100644
--- a/test/security_tests/conf/security_test_config_client_external_allow.json.in
+++ b/test/security_tests/conf/security_test_config_client_external_allow.json.in
@@ -15,7 +15,7 @@
"id" : "0x1255"
},
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x2222"
}
],
@@ -67,7 +67,7 @@
}
]
},
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"routing-credentials" :
{
"uid" : "@TEST_UID@",
diff --git a/test/security_tests/conf/security_test_config_client_external_deny.json.in b/test/security_tests/conf/security_test_config_client_external_deny.json.in
index 0cd96fb..1161f4f 100644
--- a/test/security_tests/conf/security_test_config_client_external_deny.json.in
+++ b/test/security_tests/conf/security_test_config_client_external_deny.json.in
@@ -15,7 +15,7 @@
"id" : "0x1255"
},
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x2222"
}
],
@@ -67,7 +67,7 @@
}
]
},
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"routing-credentials" :
{
"uid" : "@TEST_UID@",
diff --git a/test/security_tests/conf/security_test_config_service_external_allow.json.in b/test/security_tests/conf/security_test_config_service_external_allow.json.in
index e95b942..4d9129a 100644
--- a/test/security_tests/conf/security_test_config_service_external_allow.json.in
+++ b/test/security_tests/conf/security_test_config_service_external_allow.json.in
@@ -15,7 +15,7 @@
"id" : "0x1277"
},
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x1111"
}
],
@@ -61,7 +61,7 @@
}
]
},
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"routing-credentials" :
{
"uid" : "@TEST_UID@",
diff --git a/test/security_tests/conf/security_test_config_service_external_deny.json.in b/test/security_tests/conf/security_test_config_service_external_deny.json.in
index 8caf0af..769b04f 100644
--- a/test/security_tests/conf/security_test_config_service_external_deny.json.in
+++ b/test/security_tests/conf/security_test_config_service_external_deny.json.in
@@ -15,7 +15,7 @@
"id" : "0x1277"
},
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x1111"
}
],
@@ -61,7 +61,7 @@
}
]
},
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"routing-credentials" :
{
"uid" : "@TEST_UID@",
diff --git a/test/security_tests/conf/security_test_local_config.json.in b/test/security_tests/conf/security_test_local_config.json.in
index aab7f39..60036f8 100644
--- a/test/security_tests/conf/security_test_local_config.json.in
+++ b/test/security_tests/conf/security_test_local_config.json.in
@@ -18,7 +18,7 @@
"id" : "0x1255"
},
{
- "name" : "vsomeipd",
+ "name" : "routingmanagerd",
"id" : "0x1111"
}
],
@@ -55,7 +55,7 @@
}
]
},
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"routing-credentials" :
{
"uid" : "@TEST_UID@",
diff --git a/test/security_tests/security_test_client.cpp b/test/security_tests/security_test_client.cpp
index 2841f23..e96d48a 100644
--- a/test/security_tests/security_test_client.cpp
+++ b/test/security_tests/security_test_client.cpp
@@ -92,18 +92,16 @@ void security_test_client::on_state(vsomeip::state_type_e _state) {
its_eventgroups.insert(0x01);
app_->request_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
static_cast<vsomeip::event_t>(0x8001),
- its_eventgroups, true);
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD);
app_->request_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
static_cast<vsomeip::event_t>(0x8002),
- its_eventgroups, true);
+ its_eventgroups, vsomeip::event_type_e::ET_FIELD);
app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x01,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(0x8001));
+ vsomeip::DEFAULT_MAJOR, static_cast<vsomeip::event_t>(0x8001));
app_->subscribe(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID, 0x01,
- vsomeip::DEFAULT_MAJOR, vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE,
- static_cast<vsomeip::event_t>(0x8002));
+ vsomeip::DEFAULT_MAJOR, static_cast<vsomeip::event_t>(0x8002));
}
}
@@ -184,11 +182,11 @@ void security_test_client::run() {
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID);
// send a request which is allowed by policy -> expect answer
- app_->send(request, true);
+ app_->send(request);
// send a request with a not allowed method ID -> expect no answer
request->set_method(0x888);
- app_->send(request, true);
+ app_->send(request);
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
@@ -222,7 +220,7 @@ void security_test_client::shutdown_service() {
request->set_service(vsomeip_test::TEST_SERVICE_SERVICE_ID);
request->set_instance(vsomeip_test::TEST_SERVICE_INSTANCE_ID);
request->set_method(vsomeip_test::TEST_SERVICE_METHOD_ID_SHUTDOWN);
- app_->send(request,true);
+ app_->send(request);
}
TEST(someip_security_test, basic_subscribe_request_response)
diff --git a/test/security_tests/security_test_external_master_start.sh b/test/security_tests/security_test_external_master_start.sh
index 855654b..75d8667 100755
--- a/test/security_tests/security_test_external_master_start.sh
+++ b/test/security_tests/security_test_external_master_start.sh
@@ -24,9 +24,9 @@ ALLOW_DENY=$2
FAIL=0
export VSOMEIP_CONFIGURATION=$1
-export VSOMEIP_APPLICATION_NAME=vsomeipd
+export VSOMEIP_APPLICATION_NAME=routingmanagerd
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
export VSOMEIP_CONFIGURATION=$1
@@ -37,7 +37,7 @@ PID_CLIENT=$!
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting external security test on slave LXC"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2\"" &
elif [ ! -z "$USE_DOCKER" ]; then
docker run --name citms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./security_test_external_slave_start.sh $SERVICE_JSON_FILE $2" &
else
diff --git a/test/security_tests/security_test_external_slave_start.sh b/test/security_tests/security_test_external_slave_start.sh
index 2b2391f..41b6251 100755
--- a/test/security_tests/security_test_external_slave_start.sh
+++ b/test/security_tests/security_test_external_slave_start.sh
@@ -23,9 +23,9 @@ ALLOW_DENY=$2
FAIL=0
export VSOMEIP_CONFIGURATION=$1
-export VSOMEIP_APPLICATION_NAME=vsomeipd
+export VSOMEIP_APPLICATION_NAME=routingmanagerd
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
export VSOMEIP_CONFIGURATION=$1
diff --git a/test/security_tests/security_test_local_start.sh b/test/security_tests/security_test_local_start.sh
index 886b412..fb8273d 100755
--- a/test/security_tests/security_test_local_start.sh
+++ b/test/security_tests/security_test_local_start.sh
@@ -6,9 +6,9 @@
export VSOMEIP_CONFIGURATION=security_test_local_config.json
-export VSOMEIP_APPLICATION_NAME=vsomeipd
+export VSOMEIP_APPLICATION_NAME=routingmanagerd
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
sleep 1
diff --git a/test/security_tests/security_test_service.cpp b/test/security_tests/security_test_service.cpp
index baaa60d..347a01b 100644
--- a/test/security_tests/security_test_service.cpp
+++ b/test/security_tests/security_test_service.cpp
@@ -43,11 +43,15 @@ bool security_test_service::init() {
its_eventgroups.insert(0x01);
app_->offer_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- static_cast<vsomeip::event_t>(0x8001), its_eventgroups, true);
+ static_cast<vsomeip::event_t>(0x8001), its_eventgroups,
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
// also offer field 0x8002 which is not allowed to be received by client
app_->offer_event(vsomeip_test::TEST_SERVICE_SERVICE_ID, vsomeip_test::TEST_SERVICE_INSTANCE_ID,
- static_cast<vsomeip::event_t>(0x8002), its_eventgroups, true);
+ static_cast<vsomeip::event_t>(0x8002), its_eventgroups,
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
// set value to fields
std::shared_ptr<vsomeip::payload> its_payload =
@@ -128,7 +132,7 @@ void security_test_service::on_message(const std::shared_ptr<vsomeip::message>&
std::shared_ptr<vsomeip::message> its_response =
vsomeip::runtime::get()->create_response(_request);
- app_->send(its_response, true);
+ app_->send(its_response);
number_of_received_messages_++;
if(number_of_received_messages_ == vsomeip_test::NUMBER_OF_MESSAGES_TO_SEND_SECURITY_TESTS) {
diff --git a/test/someip_test_globals.hpp b/test/someip_test_globals.hpp
index 8e7af4b..4380cd3 100644
--- a/test/someip_test_globals.hpp
+++ b/test/someip_test_globals.hpp
@@ -7,8 +7,7 @@
#define SOMEIP_TEST_GLOBALS_HPP_
#include <vsomeip/vsomeip.hpp>
-
-#include "../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
namespace vsomeip_test
{
diff --git a/test/someip_tp_tests/conf/someip_tp_test_master.json.in b/test/someip_tp_tests/conf/someip_tp_test_master.json.in
new file mode 100644
index 0000000..a2f67a1
--- /dev/null
+++ b/test/someip_tp_tests/conf/someip_tp_test_master.json.in
@@ -0,0 +1,45 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications" :
+ [
+ {
+ "name" : "someip_tp_test_service",
+ "id" : "0xCAFE"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4545",
+ "instance":"0x1",
+ "unreliable":"30001",
+ "someip-tp" : {
+ "service-to-client": [ "0x4545", "0x8001"]
+ }
+ },
+ {
+ "service":"0x6767",
+ "instance":"0x1",
+ "unicast" : "@TEST_IP_SLAVE@",
+ "unreliable":"40001",
+ "someip-tp" : {
+ "client-to-service": [ "0x6767", "0x8001" ]
+ }
+ }
+ ],
+ "max-payload-size-unreliable" : "8352",
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.77.1",
+ "port":"30490",
+ "protocol":"udp",
+ "cyclic_offer_delay" : "1000"
+ }
+} \ No newline at end of file
diff --git a/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in b/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in
new file mode 100755
index 0000000..c01feea
--- /dev/null
+++ b/test/someip_tp_tests/conf/someip_tp_test_master_starter.sh.in
@@ -0,0 +1,65 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FAIL=0
+
+if [ $# -lt 1 ]
+then
+ echo "Please pass a test mode to this script."
+ echo "For example: $0 IN_SEQUENCE"
+ echo "Valid subscription types include:"
+ echo " [IN_SEQUENCE, MIXED, INCOMPLETE, DUPLICATE, OVERLAP, OVERLAP_FRONT_BACK]"
+ exit 1
+fi
+TESTMODE=$1
+export VSOMEIP_CONFIGURATION=someip_tp_test_master.json
+# start daemon
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+# Start the services
+./someip_tp_test_service $1 &
+PID_SERIVCE=$!
+
+sleep 1
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./someip_tp_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE\"" &
+ echo "remote ssh pid: $!"
+elif [ ! -z "$USE_DOCKER" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./someip_tp_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE" &
+else
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** someip_tp_test_msg_sender @TEST_IP_MASTER@ @TEST_IP_SLAVE@ $TESTMODE
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** someip_tp_test_master.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+# Wait until all clients and services are finished
+for job in $PID_SERIVCE
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ echo "waiting for $job"
+ wait $job || FAIL=$(($FAIL+1))
+done
+
+# kill the services
+kill $PID_VSOMEIPD
+sleep 1
+
+# Check if everything went well
+exit $FAIL
diff --git a/test/someip_tp_tests/someip_tp_test_globals.hpp b/test/someip_tp_tests/someip_tp_test_globals.hpp
new file mode 100644
index 0000000..723cfe1
--- /dev/null
+++ b/test/someip_tp_tests/someip_tp_test_globals.hpp
@@ -0,0 +1,40 @@
+// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef SOMEIP_TP_TEST_GLOBALS_HPP_
+#define SOMEIP_TP_TEST_GLOBALS_HPP_
+
+#include <vsomeip/primitive_types.hpp>
+
+namespace someip_tp_test {
+
+struct service_info {
+ vsomeip::service_t service_id;
+ vsomeip::instance_t instance_id;
+ vsomeip::method_t method_id;
+ vsomeip::event_t event_id;
+ vsomeip::eventgroup_t eventgroup_id;
+ vsomeip::method_t shutdown_method_id;
+ vsomeip::method_t notify_method_id;
+};
+
+struct service_info service = { 0x4545, 0x1, 0x4545, 0x8001, 0x1, 0x4501, 0x4502 };
+struct service_info service_slave = { 0x6767, 0x1, 0x6767, 0x8001, 0x1, 0x6701, 0x6702 };
+
+enum test_mode_e {
+ IN_SEQUENCE,
+ MIXED,
+ INCOMPLETE,
+ DUPLICATE,
+ OVERLAP,
+ OVERLAP_FRONT_BACK
+};
+
+const std::uint32_t number_of_fragments = 6;
+const std::uint32_t max_segment_size = 1392;
+
+}
+
+#endif /* SOMEIP_TP_TEST_GLOBALS_HPP_ */
diff --git a/test/someip_tp_tests/someip_tp_test_master.json b/test/someip_tp_tests/someip_tp_test_master.json
new file mode 100644
index 0000000..9a08e77
--- /dev/null
+++ b/test/someip_tp_tests/someip_tp_test_master.json
@@ -0,0 +1,45 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"info",
+ "console":"true"
+ },
+ "applications" :
+ [
+ {
+ "name" : "someip_tp_test_service",
+ "id" : "0xCAFE"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4545",
+ "instance":"0x1",
+ "unreliable":"30001",
+ "someip-tp" : {
+ "service-to-client": [ "0x4545", "0x8001"]
+ }
+ },
+ {
+ "service":"0x6767",
+ "instance":"0x1",
+ "unicast" : "10.0.3.2",
+ "unreliable":"40001",
+ "someip-tp" : {
+ "client-to-service": [ "0x6767", "0x8001" ]
+ }
+ }
+ ],
+ "max-payload-size-unreliable" : "8352",
+ "routing":"routingmanagerd",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.77.1",
+ "port":"30490",
+ "protocol":"udp",
+ "cyclic_offer_delay" : "1000"
+ }
+}
diff --git a/test/someip_tp_tests/someip_tp_test_master_starter.sh b/test/someip_tp_tests/someip_tp_test_master_starter.sh
new file mode 100755
index 0000000..20c8c2a
--- /dev/null
+++ b/test/someip_tp_tests/someip_tp_test_master_starter.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+# Copyright (C) 2015-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+FAIL=0
+
+if [ $# -lt 1 ]
+then
+ echo "Please pass a test mode to this script."
+ echo "For example: $0 IN_SEQUENCE"
+ echo "Valid subscription types include:"
+ echo " [IN_SEQUENCE, MIXED, INCOMPLETE, DUPLICATE, OVERLAP, OVERLAP_FRONT_BACK]"
+ exit 1
+fi
+TESTMODE=$1
+export VSOMEIP_CONFIGURATION=someip_tp_test_master.json
+# start daemon
+../examples/routingmanagerd/./routingmanagerd &
+PID_VSOMEIPD=$!
+# Start the services
+./someip_tp_test_service $1 &
+PID_SERIVCE=$!
+
+sleep 1
+
+if [ ! -z "$USE_LXC_TEST" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./someip_tp_test_msg_sender 10.0.3.1 10.0.3.2 $TESTMODE\"" &
+ echo "remote ssh pid: $!"
+elif [ ! -z "$USE_DOCKER" ]; then
+ echo "Waiting for 5s"
+ sleep 5
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./someip_tp_test_msg_sender 10.0.3.1 10.0.3.2 $TESTMODE" &
+else
+cat <<End-of-message
+*******************************************************************************
+*******************************************************************************
+** Please now run:
+** someip_tp_test_msg_sender 10.0.3.1 10.0.3.2 $TESTMODE
+** from an external host to successfully complete this test.
+**
+** You probably will need to adapt the 'unicast' settings in
+** someip_tp_test_master.json to your personal setup.
+*******************************************************************************
+*******************************************************************************
+End-of-message
+fi
+
+# Wait until all clients and services are finished
+for job in $PID_SERIVCE
+do
+ # Fail gets incremented if a client exits with a non-zero exit code
+ echo "waiting for $job"
+ wait $job || FAIL=$(($FAIL+1))
+done
+
+# kill the services
+kill $PID_VSOMEIPD
+sleep 1
+
+# Check if everything went well
+exit $FAIL
diff --git a/test/someip_tp_tests/someip_tp_test_msg_sender.cpp b/test/someip_tp_tests/someip_tp_test_msg_sender.cpp
new file mode 100644
index 0000000..c930acb
--- /dev/null
+++ b/test/someip_tp_tests/someip_tp_test_msg_sender.cpp
@@ -0,0 +1,1387 @@
+// Copyright (C) 2015-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iostream>
+#include <memory>
+#include <thread>
+#include <chrono>
+#include <cstring>
+#include <future>
+#include <numeric>
+#include <random>
+#include <algorithm>
+#include <list>
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+
+#include <gtest/gtest.h>
+
+#include <boost/asio.hpp>
+
+#include <vsomeip/vsomeip.hpp>
+
+#include "../../implementation/utility/include/byteorder.hpp"
+#include "../../implementation/message/include/deserializer.hpp"
+#include "../../implementation/message/include/serializer.hpp"
+#include "../../implementation/service_discovery/include/service_discovery.hpp"
+#include "../../implementation/service_discovery/include/message_impl.hpp"
+#include "../../implementation/service_discovery/include/constants.hpp"
+#include "../../implementation/service_discovery/include/enumeration_types.hpp"
+#include "../../implementation/service_discovery/include/eventgroupentry_impl.hpp"
+#include "../../implementation/service_discovery/include/serviceentry_impl.hpp"
+#include "../../implementation/message/include/message_impl.hpp"
+#include "../../implementation/service_discovery/include/option_impl.hpp"
+#include "../../implementation/service_discovery/include/ipv4_option_impl.hpp"
+#include "../../implementation/endpoints/include/tp.hpp"
+#include "../../implementation/endpoints/include/tp_reassembler.hpp"
+#include "../../implementation/message/include/payload_impl.hpp"
+
+#include "someip_tp_test_globals.hpp"
+
+static char* remote_address;
+static char* local_address;
+
+std::vector<someip_tp_test::test_mode_e> its_modes({
+ someip_tp_test::test_mode_e::IN_SEQUENCE,
+ someip_tp_test::test_mode_e::MIXED,
+ someip_tp_test::test_mode_e::INCOMPLETE,
+ someip_tp_test::test_mode_e::DUPLICATE,
+ someip_tp_test::test_mode_e::OVERLAP,
+ someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK,
+});
+
+class someip_tp : public ::testing::TestWithParam<someip_tp_test::test_mode_e> {
+public:
+ someip_tp() :
+ work_(std::make_shared<boost::asio::io_service::work>(io_)),
+ io_thread_(std::bind(&someip_tp::io_run, this)),
+ session_(0x0),
+ sd_session_(0x0),
+ address_remote_(boost::asio::ip::address::from_string(std::string(remote_address))),
+ address_local_(boost::asio::ip::address::from_string(std::string(local_address))),
+ runtime_(vsomeip::runtime::get()) {}
+protected:
+ void TearDown() {
+ work_.reset();
+ io_thread_.join();
+ io_.stop();
+ }
+
+ void call_shutdown_method() {
+ boost::system::error_code ec;
+ std::uint8_t shutdown_call[] = {
+ 0x45, 0x45, 0x45, 0x01,
+ 0x00, 0x00, 0x00, 0x08,
+ 0xDD, 0xDD, 0x00, 0x01,
+ 0x01, 0x00, 0x00, 0x00 };
+ boost::asio::ip::udp::socket::endpoint_type target_service(address_remote_,
+ 30001);
+ boost::asio::ip::udp::socket udp_socket2(io_, boost::asio::ip::udp::v4());
+ udp_socket2.send_to(boost::asio::buffer(shutdown_call), target_service);
+ udp_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_socket2.close(ec);
+ }
+
+ void io_run() {
+ io_.run();
+ }
+
+ void offer_service(boost::asio::ip::udp::socket* const _udp_socket) {
+ // offer the service
+ std::uint8_t its_offer_service_message[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x01, 0x00, 0x00, 0x20,
+ 0x67, 0x67, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x00, // minor
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x11, 0x9c, 0x41,
+ };
+ std::memcpy(&its_offer_service_message[48], &address_local_.to_v4().to_bytes()[0], 4);
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_offer_service_message[10], &its_session, sizeof(its_session));
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ _udp_socket->send_to(boost::asio::buffer(its_offer_service_message), target_sd);
+ }
+
+ void subscribe_at_master(boost::asio::ip::udp::socket* const _udp_socket) {
+ std::uint8_t its_subscription[] = {
+ 0xff, 0xff, 0x81, 0x00,
+ 0x00, 0x00, 0x00, 0x30, // length
+ 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x02, 0x00,
+ 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, // length entries array
+ 0x06, 0x00, 0x00, 0x10,
+ 0x45, 0x45, 0x00, 0x01, // service / instance
+ 0x00, 0xff, 0xff, 0xff, // major / ttl
+ 0x00, 0x00, 0x00, 0x01, // counter
+ 0x00, 0x00, 0x00, 0x0c, // length options array
+ 0x00, 0x09, 0x04, 0x00,
+ 0xff, 0xff, 0xff, 0xff, // slave address
+ 0x00, 0x11, 0x75, 0x31, // port 30001
+ };
+ std::memcpy(&its_subscription[48], &address_local_.to_v4().to_bytes()[0], 4);
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_subscription[10], &its_session, sizeof(its_session));
+
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ _udp_socket->send_to(boost::asio::buffer(its_subscription), target_sd);
+ }
+
+ /*
+ * @brief custom version of tp::tp_split_message with adjustable segment size
+ * needed to send overlapping segments within the 1392 byte segment size limit
+ */
+ vsomeip::tp::tp_split_messages_t split_message(const std::uint8_t * const _data,
+ std::uint32_t _size , std::uint32_t _segment_size) {
+ using namespace vsomeip::tp;
+ using namespace vsomeip;
+ tp_split_messages_t split_messages;
+
+ if (_size < VSOMEIP_MAX_UDP_MESSAGE_SIZE) {
+ std::cerr << __func__ << " called with size: " << std::dec << _size;
+ return split_messages;
+ }
+
+ const auto data_end = _data + _size;
+
+ for (auto current_offset = _data + 16; current_offset < data_end;) {
+ auto msg = std::make_shared<message_buffer_t>();
+ msg->reserve(VSOMEIP_FULL_HEADER_SIZE + sizeof(tp_header_t) + _segment_size);
+ // copy the header
+ msg->insert(msg->end(), _data, _data + VSOMEIP_FULL_HEADER_SIZE);
+ // change the message type
+ (*msg)[VSOMEIP_MESSAGE_TYPE_POS] = (*msg)[VSOMEIP_MESSAGE_TYPE_POS] | 0x20;
+ // check if last segment
+ const auto segment_end = current_offset + _segment_size;
+ const bool is_last_segment = (segment_end >= data_end);
+ // insert tp_header
+ const tp_header_t header = htonl(
+ static_cast<tp_header_t>((current_offset - VSOMEIP_FULL_HEADER_SIZE - _data)) |
+ static_cast<tp_header_t>((is_last_segment) ? 0x0u : 0x1u));
+
+ const byte_t * const headerp = reinterpret_cast<const byte_t*>(&header);
+ msg->insert(msg->end(), headerp, headerp + sizeof(tp_header_t));
+
+ // insert payload
+ if (is_last_segment) {
+ msg->insert(msg->end(), current_offset, data_end);
+ current_offset = data_end;
+ } else {
+ msg->insert(msg->end(), current_offset, segment_end);
+ current_offset += _segment_size;
+ }
+ // update length
+ const length_t its_length = static_cast<length_t>(msg->size()
+ - VSOMEIP_SOMEIP_HEADER_SIZE);
+ *(reinterpret_cast<length_t*>(&(*msg)[VSOMEIP_LENGTH_POS_MIN])) = htonl(its_length);
+ split_messages.emplace_back(std::move(msg));
+ }
+
+ return split_messages;
+ }
+
+ void create_fragments(std::uint32_t _count, vsomeip::service_t _service,
+ vsomeip::instance_t _instance,
+ vsomeip::method_t _method,
+ vsomeip::message_type_e _message_type,
+ vsomeip::client_t _client,
+ vsomeip::session_t _session,
+ std::vector<vsomeip::message_buffer_ptr_t>* _target,
+ std::uint32_t _segment_size) {
+ vsomeip::message_impl msg;
+ msg.set_reliable(false);
+ msg.set_service(_service);
+ msg.set_instance(_instance);
+ msg.set_method(_method);
+ msg.set_message_type(_message_type);
+ msg.set_return_code(vsomeip::return_code_e::E_OK);
+ if (_client == vsomeip::ANY_CLIENT) {
+ msg.set_client(0xDDDD);
+ } else {
+ msg.set_client(_client);
+ }
+ if (_session == 0xFFFF) {
+ msg.set_session(++session_);
+ } else {
+ msg.set_session(_session);
+ }
+ std::vector<vsomeip::byte_t> its_payload_data;
+ for (uint32_t i = 0; i < _count; i++) {
+ its_payload_data.resize((i * _segment_size) + _segment_size, static_cast<std::uint8_t>(i));
+ }
+ std::shared_ptr<vsomeip::payload> payload = std::make_shared<vsomeip::payload_impl>(its_payload_data);
+ msg.set_payload(payload);
+ vsomeip::serializer its_serializer(0);
+ msg.serialize(&its_serializer);
+
+ *_target = split_message(its_serializer.get_data(), its_serializer.get_size(), _segment_size);
+ its_serializer.reset();
+
+ }
+
+ vsomeip::message_buffer_t create_full_message(
+ const std::vector<vsomeip::message_buffer_ptr_t>& _fragments) {
+ auto its_reassembler = std::make_shared<vsomeip::tp::tp_reassembler>(
+ std::numeric_limits<std::uint32_t>::max(), io_);
+ vsomeip::message_buffer_t its_reassemlbed_msg;
+ for (const auto& frag : _fragments) {
+ const auto res = its_reassembler->process_tp_message(&(*frag)[0],
+ std::uint32_t(frag->size()), address_local_, 12345);
+ if (res.first) {
+ its_reassemlbed_msg = res.second;
+ }
+ }
+ its_reassembler->stop();
+ return its_reassemlbed_msg;
+ }
+
+ std::vector<int> create_shuffled_seqeuence(std::uint32_t _count) {
+ std::vector<int> its_indexes(_count);
+ std::iota(its_indexes.begin(), its_indexes.end(), 0);
+ std::random_device rd;
+ std::mt19937 its_twister(rd());
+ std::shuffle(its_indexes.begin(), its_indexes.end(), its_twister);
+ return its_indexes;
+ }
+ void increase_segment_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ _seg->resize(_seg->size() + _amount, 0xff);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void increase_segment_front(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ // increase segment by amount
+ _seg->insert(_seg->begin() + VSOMEIP_TP_PAYLOAD_POS, _amount, 0xff);
+
+ // decrease offset by amount
+ const vsomeip::tp::tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MAX]);
+ std::uint32_t its_offset = vsomeip::tp::tp::get_offset(its_tp_header);
+ its_offset -= _amount;
+ const vsomeip::tp::tp_header_t its_new_tp_header =
+ htonl(static_cast<vsomeip::tp::tp_header_t>(its_offset |
+ static_cast<vsomeip::tp::tp_header_t>(its_tp_header & 0x1)));
+ *(reinterpret_cast<vsomeip::tp::tp_header_t*>(
+ &((*_seg)[VSOMEIP_TP_HEADER_POS_MIN]))) = its_new_tp_header;
+
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void increase_segment_front_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ increase_segment_front(_seg, _amount);
+ increase_segment_back(_seg, _amount);
+ }
+
+ void decrease_segment_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ _seg->resize(_seg->size() - _amount, 0xff);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void decrease_segment_front(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ if (_amount % 16 != 0) {
+ std::cerr << __func__ << ":" << __LINE__ << std::endl;
+ return;
+ }
+ _seg->erase(_seg->begin() + VSOMEIP_TP_PAYLOAD_POS, _seg->begin() + VSOMEIP_TP_PAYLOAD_POS + _amount);
+ // increase offset by amount
+ const vsomeip::tp::tp_header_t its_tp_header = VSOMEIP_BYTES_TO_LONG(
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 1],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MIN + 2],
+ (*_seg)[VSOMEIP_TP_HEADER_POS_MAX]);
+ std::uint32_t its_offset = vsomeip::tp::tp::get_offset(its_tp_header);
+ its_offset += _amount;
+ const vsomeip::tp::tp_header_t its_new_tp_header =
+ htonl(static_cast<vsomeip::tp::tp_header_t>(its_offset |
+ static_cast<vsomeip::tp::tp_header_t>(its_tp_header & 0x1)));
+ *(reinterpret_cast<vsomeip::tp::tp_header_t*>(
+ &((*_seg)[VSOMEIP_TP_HEADER_POS_MIN]))) = its_new_tp_header;
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*_seg)[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(_seg->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ }
+
+ void decrease_segment_front_back(const vsomeip::message_buffer_ptr_t& _seg,
+ std::uint32_t _amount) {
+ if (_amount % 16 != 0) {
+ std::cerr << __func__ << ":" << __LINE__ << std::endl;
+ return;
+ }
+ decrease_segment_back(_seg, _amount);
+ decrease_segment_front(_seg, _amount);
+ }
+
+
+ enum order_e {
+ ASCENDING,
+ DESCENDING,
+ MIXED_PREDEFINED,
+ MIXED_RANDOM,
+ };
+
+ boost::asio::io_service io_;
+ std::shared_ptr<boost::asio::io_service::work> work_;
+ std::thread io_thread_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_request_to_master_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_response_of_master_;
+
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_received_as_server_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_response_to_master_;
+
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_event_from_master_;
+ std::vector<vsomeip::message_buffer_ptr_t> fragments_event_to_master_;
+
+ std::atomic<std::uint16_t> session_;
+ std::atomic<std::uint16_t> sd_session_;
+ boost::asio::ip::address address_remote_;
+ boost::asio::ip::address address_local_;
+ std::shared_ptr<vsomeip::runtime> runtime_;
+ someip_tp_test::test_mode_e test_mode_ = GetParam();
+};
+
+INSTANTIATE_TEST_CASE_P(send_in_mode,
+ someip_tp,
+ ::testing::ValuesIn(its_modes));
+
+
+/*
+ * @test Send a big fragmented UDP request to the master and wait for the
+ * response. Check that the received response is the same as the request (server
+ * just echos the requests).
+ * Wait for a big fragmented UDP message request from the master and send back
+ * the response in the same size. Check that the request and response are
+ * identical.
+ * Do this two times one with fragments ordered ascending and one time descending.
+ * Wait for the master to subscribe and send back two big, fragmented
+ * notifications one with fragments ordered ascending and one descending
+ * Subscribe at master and wait for one fragmented event.
+ * With testmode INCOMPLETE incomplete fragments are send as well
+ * With testmode MIXED instead of ascending/descedning order the fragments are
+ * send in a predefined or in a random order
+ */
+TEST_P(someip_tp, send_in_mode)
+{
+ std::promise<void> remote_client_subscribed;
+ std::atomic<std::uint16_t> remote_client_subscription_port(0);
+ std::promise<void> offer_received;
+
+ std::mutex udp_sd_socket_mutex;
+ boost::asio::ip::udp::socket udp_sd_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30490));
+
+ boost::asio::ip::udp::socket udp_client_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30001));
+
+ boost::asio::ip::udp::socket udp_server_socket(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 40001));
+
+ std::thread sd_receive_thread([&](){
+ std::atomic<bool> keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ std::vector<vsomeip::event_t> its_received_events;
+ std::atomic<bool> service_offered(false);
+ std::atomic<bool> client_subscribed(false);
+
+ // join the sd multicast group 224.0.77.1
+ udp_sd_socket.set_option(boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("224.0.77.1").to_v4()));
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_sd_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ vsomeip::deserializer its_deserializer(&receive_buffer[0], bytes_transferred, 0);
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[VSOMEIP_METHOD_POS_MAX]);
+ if (its_service == vsomeip::sd::service && its_method == vsomeip::sd::method) {
+ vsomeip::sd::message_impl sd_msg;
+ EXPECT_TRUE(sd_msg.deserialize(&its_deserializer));
+ EXPECT_EQ(1u, sd_msg.get_entries().size());
+ for (const auto& e : sd_msg.get_entries()) {
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP && !client_subscribed) {
+ EXPECT_TRUE(e->is_eventgroup_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP, e->get_type());
+ EXPECT_EQ(1,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, e->get_service());
+ EXPECT_EQ(someip_tp_test::service_slave.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP) {
+ std::shared_ptr<vsomeip::sd::eventgroupentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::eventgroupentry_impl>(e);
+ EXPECT_EQ(someip_tp_test::service_slave.eventgroup_id,
+ its_casted_entry->get_eventgroup());
+ std::shared_ptr<vsomeip::sd::option_impl> its_option =
+ sd_msg.get_options().at(its_casted_entry->get_options(1)[0]);
+ EXPECT_TRUE(its_option > 0);
+ if(its_option->get_type() == vsomeip::sd::option_type_e::IP4_ENDPOINT) {
+ std::shared_ptr<vsomeip::sd::ipv4_option_impl> its_ipv4_option =
+ std::dynamic_pointer_cast<vsomeip::sd::ipv4_option_impl> (its_option);
+ EXPECT_TRUE(its_ipv4_option > 0);
+ EXPECT_EQ(vsomeip::sd::layer_four_protocol_e::UDP, its_ipv4_option->get_layer_four_protocol());
+ EXPECT_EQ(address_remote_,
+ boost::asio::ip::address(
+ boost::asio::ip::address_v4(its_ipv4_option->get_address())));
+ remote_client_subscription_port = its_ipv4_option->get_port();
+ }
+ std::vector<vsomeip::byte_t> its_sub_ack(&receive_buffer[0], &receive_buffer[0] + VSOMEIP_FULL_HEADER_SIZE + 8 + (sd_msg.get_entries().size() * 16));
+ its_sub_ack[24] = static_cast<vsomeip::byte_t>(vsomeip::sd::entry_type_e::SUBSCRIBE_EVENTGROUP_ACK);
+ // fix length
+ const std::uint32_t its_length = htonl(static_cast<std::uint32_t>(its_sub_ack.size()) - VSOMEIP_SOMEIP_HEADER_SIZE);
+ std::memcpy(&its_sub_ack[4], &its_length, sizeof(its_length));
+ // set number of options to zero
+ its_sub_ack[27] = 0x0;
+ // update session
+ std::uint16_t its_session = htons(++sd_session_);
+ std::memcpy(&its_sub_ack[10], &its_session, sizeof(its_session));
+ boost::asio::ip::udp::socket::endpoint_type target_sd(address_remote_,30490);
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ udp_sd_socket.send_to(boost::asio::buffer(its_sub_ack), target_sd);
+ }
+ std::cout << __LINE__ << ": master subscribed" << std::endl;
+ remote_client_subscribed.set_value();
+ client_subscribed = true;
+ }
+ } else if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE && !service_offered) {
+ EXPECT_TRUE(e->is_service_entry());
+ EXPECT_EQ(vsomeip::sd::entry_type_e::OFFER_SERVICE, e->get_type());
+ EXPECT_EQ(1u,e->get_num_options(1));
+ EXPECT_EQ(std::uint32_t(0xFFFFFF), e->get_ttl());
+ EXPECT_EQ(someip_tp_test::service.service_id, e->get_service());
+ EXPECT_EQ(someip_tp_test::service.instance_id, e->get_instance());
+ EXPECT_EQ(1u, sd_msg.get_options().size());
+ if (e->get_type() == vsomeip::sd::entry_type_e::OFFER_SERVICE) {
+ std::shared_ptr<vsomeip::sd::serviceentry_impl> its_casted_entry =
+ std::static_pointer_cast<vsomeip::sd::serviceentry_impl>(e);
+ EXPECT_EQ(0u, its_casted_entry->get_minor_version());
+ }
+ offer_received.set_value();
+ service_offered = true;
+ }
+ }
+ if (service_offered && client_subscribed) {
+ keep_receiving = false;
+ }
+ } else {
+ ADD_FAILURE() << " received non-sd message";
+ return;
+ }
+ }
+ }
+ });
+
+ std::thread send_thread([&]() {
+ boost::system::error_code ec;
+ try {
+
+ // wait until a offer was received
+ if (std::future_status::timeout == offer_received.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Didn't receive offer within time";
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ subscribe_at_master(&udp_sd_socket);
+ }
+
+ std::mutex all_fragments_received_mutex_;
+ std::condition_variable all_fragments_received_cond_;
+ bool wait_for_all_response_fragments_received_(true);
+ std::uint32_t received_responses(0);
+ bool wait_for_all_event_fragments_received_(true);
+
+ std::thread udp_client_receive_thread([&]() {
+ bool keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ std::size_t bytes_transferred = udp_client_socket.receive(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ std::uint32_t its_pos = 0;
+
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ std::cout << __LINE__ << ": received response " << its_message_size << std::endl;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (msg.get_message_type() == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(vsomeip::message_type_e::MT_RESPONSE, msg.get_message_type());
+ EXPECT_EQ(someip_tp_test::service.service_id, msg.get_service());
+ } else if (msg.get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ std::cout << __LINE__ << ": received event" << std::endl;
+ } else if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) &&
+ vsomeip::tp::tp::tp_flag_unset(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) == vsomeip::message_type_e::MT_RESPONSE) {
+ EXPECT_EQ(someip_tp_test::service.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service.method_id, its_method);
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+
+ fragments_response_of_master_.push_back(its_buffer);
+ if (fragments_response_of_master_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_mutex_);
+ wait_for_all_response_fragments_received_ = false;
+ std::cout << __LINE__ << ": received all response fragments as client" << std::endl;
+ all_fragments_received_cond_.notify_one();
+ if (++received_responses == 2 && !wait_for_all_event_fragments_received_) {
+ std::cout << __LINE__ << ": received all responses as client --> Finished" << std::endl;
+ keep_receiving = false;
+ }
+ }
+ } else if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) &&
+ vsomeip::tp::tp::tp_flag_unset(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS]) == vsomeip::message_type_e::MT_NOTIFICATION) {
+ std::cout << __LINE__ << ": received event fragment" << std::endl;
+ EXPECT_EQ(someip_tp_test::service.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service.event_id, its_method);
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+ fragments_event_from_master_.push_back(its_buffer);
+ if (fragments_event_from_master_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_mutex_);
+ wait_for_all_event_fragments_received_ = false;
+ std::cout << __LINE__ << ": received all event fragments as client --> Finished" << std::endl;
+ all_fragments_received_cond_.notify_one();
+ if (received_responses == 2) {
+ keep_receiving = false;
+ }
+ }
+
+ }
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+ }
+ }
+ }
+ });
+
+ // send SOMEI-TP message fragmented into 6 parts to service:
+ boost::asio::ip::udp::socket::endpoint_type target_service(address_remote_, 30001);
+
+ std::unique_lock<std::mutex> its_lock(all_fragments_received_mutex_);
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ create_fragments(someip_tp_test::number_of_fragments, someip_tp_test::service.service_id,
+ someip_tp_test::service.instance_id,
+ someip_tp_test::service.method_id,
+ vsomeip::message_type_e::MT_REQUEST,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &fragments_request_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ } else {
+ auto its_indexes = {4, 1, 3, 5, 2, 0};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,1,3,5,2,4};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase third segment by 16 byte at front and back
+ increase_segment_front_back(fragments_request_to_master_[2], 16);
+ increase_segment_front(fragments_request_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_request_to_master_.begin();
+ iter != fragments_request_to_master_.end(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ // send insert 2nd fragment twice
+ if (iter == fragments_request_to_master_.begin() + 1) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 3) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send a request fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_request_to_master_[2]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x33;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x33;
+ udp_client_socket.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ // send a request from a different src port as well to test cleanup
+ boost::asio::ip::udp::socket udp_client_socket2(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30004));
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xcc;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xcc;
+ udp_client_socket2.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ boost::system::error_code ec;
+ udp_client_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket2.close(ec);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ increase_segment_back(fragments_request_to_master_[1], 16);
+ }
+ for (const auto& fragment : fragments_request_to_master_) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragment), target_service);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,4,1,0};
+ std::cout << __LINE__ << ": using following predefined sequence to send request to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase third segment by 16 byte at front and back
+ increase_segment_front_back(fragments_request_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_client_socket.send_to(boost::asio::buffer(*fragments_request_to_master_[i]), target_service);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_request_to_master_.rbegin();
+ iter != fragments_request_to_master_.rend(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_request_to_master_.rbegin() + 1) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send a request fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_request_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x77;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x77;
+ udp_client_socket.send_to(boost::asio::buffer(msg_incomplete), target_service);
+
+ // send a request from a different src port as well to test cleanup
+ boost::asio::ip::udp::socket udp_client_socket2(io_,
+ boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 30005));
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xdd;
+ udp_client_socket2.send_to(boost::asio::buffer(msg_incomplete), target_service);
+ boost::system::error_code ec;
+ udp_client_socket2.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket2.close(ec);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_request_to_master_[4], 16);
+ }
+ for (auto iter = fragments_request_to_master_.rbegin(); iter != fragments_request_to_master_.rend(); iter++) {
+ udp_client_socket.send_to(boost::asio::buffer(*(*iter)), target_service);
+ }
+ }
+ }
+ {
+ while (wait_for_all_response_fragments_received_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_cond_.wait_for(its_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive response to"
+ " fragmented message within time: " << std::uint32_t(mode);
+ return;
+ } else {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_request_to_master_.size());
+ // create complete message from request
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (mode == ASCENDING) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // decrease second segment by 16 byte
+ decrease_segment_back(fragments_request_to_master_[1], 16);
+ } else if (mode == DESCENDING) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // decrease fourth segment by 16 byte
+ decrease_segment_back(fragments_request_to_master_[4], 16);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ // remove the additional inserted bytes which weren't accepted on
+ // test masterside as they were overlapping
+ if (mode == ASCENDING) {
+ decrease_segment_front_back(fragments_request_to_master_[2], 16);
+ decrease_segment_front(fragments_request_to_master_[4], 16);
+ } else {
+ decrease_segment_front_back(fragments_request_to_master_[4], 16);
+ }
+ }
+ vsomeip::message_buffer_t its_request = create_full_message(fragments_request_to_master_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_request.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_request.size());
+ }
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP && mode == ASCENDING) {
+ // response contains the additional 16 bytes of 2nd fragment instead
+ // of beginning of the 3rd fragment
+ for (std::uint32_t i = 0; i < 16; i++) {
+ its_request[VSOMEIP_PAYLOAD_POS + 2 * (someip_tp_test::max_segment_size - 160) + i] = 0xff;
+ }
+ }
+
+ // create complete message from response
+ vsomeip::message_buffer_t its_response = create_full_message(fragments_response_of_master_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_response.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_response.size());
+ }
+ // change message type of response to request again
+ its_response[VSOMEIP_MESSAGE_TYPE_POS] = static_cast<vsomeip::byte_t>(vsomeip::message_type_e::MT_REQUEST);
+ // request and response should now be equal
+ EXPECT_EQ(its_response.size(), its_request.size());
+ EXPECT_EQ(its_response, its_request);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_response[0]),
+ static_cast<void*>(&its_request[0]),
+ its_response.size()));
+ fragments_response_of_master_.clear();
+ }
+ }
+ wait_for_all_response_fragments_received_ = true;
+ }
+ fragments_request_to_master_.clear();
+ }
+
+ while (wait_for_all_event_fragments_received_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_cond_.wait_for(its_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive fragmented event from "
+ " master within time";
+ }
+ }
+ // check if received event is correct
+ {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_event_from_master_.size());
+ // create complete message from event
+ vsomeip::message_buffer_t its_event = create_full_message(fragments_event_from_master_);
+ vsomeip::session_t its_event_session =
+ VSOMEIP_BYTES_TO_WORD(its_event[VSOMEIP_SESSION_POS_MIN],
+ its_event[VSOMEIP_SESSION_POS_MAX]);
+
+ std::vector<vsomeip::message_buffer_ptr_t> its_cmp_event_fragments;
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service.service_id,
+ someip_tp_test::service.instance_id,
+ someip_tp_test::service.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ 0x0, its_event_session, &its_cmp_event_fragments,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ vsomeip::message_buffer_t its_cmp_event = create_full_message(its_cmp_event_fragments);
+ EXPECT_EQ(its_cmp_event.size(), its_event.size());
+ EXPECT_EQ(its_cmp_event, its_event);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_cmp_event[0]),
+ static_cast<void*>(&its_event[0]),
+ its_cmp_event.size()));
+ }
+ its_lock.unlock();
+ udp_client_receive_thread.join();
+ } catch (const std::exception& _e) {
+ ADD_FAILURE() << "catched exception: " << _e.what();
+ }
+ });
+
+ std::mutex all_fragments_received_as_server_mutex_;
+ std::unique_lock<std::mutex> all_fragments_received_as_server_lock(all_fragments_received_as_server_mutex_);
+ std::condition_variable all_fragments_received_as_server_cond_;
+ bool wait_for_all_fragments_received_as_server_(true);
+ std::atomic<std::uint16_t> remote_client_request_port(0);
+
+ std::thread udp_server_send_thread([&]() {
+ // wait until client subscribed
+ if (std::future_status::timeout == remote_client_subscribed.get_future().wait_for(std::chrono::seconds(10))) {
+ ADD_FAILURE() << "Client didn't subscribe within time";
+ return;
+ }
+
+ // send fragmented event to the master
+ boost::asio::ip::udp::socket::endpoint_type master_client(address_remote_, remote_client_subscription_port);
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &fragments_event_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160 :
+ vsomeip::tp::tp::tp_max_segment_length_);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {2, 3, 5, 1, 4, 0};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,2,4,5,1,3};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase second segment by 16 byte at front and back
+ increase_segment_front_back(fragments_event_to_master_[1], 16);
+ increase_segment_front(fragments_event_to_master_[3], 16);
+
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_event_to_master_.begin();
+ iter != fragments_event_to_master_.end(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd fragment twice
+ if (iter == fragments_event_to_master_.begin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send oversized fragment as well
+ increase_segment_back(*iter, 4);
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ decrease_segment_back(*iter, 4);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 3) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_event_to_master_[2]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x44;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x44;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xdd;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xdd;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second segment by 16 byte
+ increase_segment_back(fragments_event_to_master_[1], 16);
+
+ // send one oversize message as well
+ std::vector<vsomeip::message_buffer_ptr_t> oversized_event;
+ create_fragments(someip_tp_test::number_of_fragments + 1,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id,
+ vsomeip::message_type_e::MT_NOTIFICATION,
+ vsomeip::ANY_CLIENT, 0xffff,
+ &oversized_event,
+ vsomeip::tp::tp::tp_max_segment_length_);
+ for (const auto& fragment : oversized_event) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragment), master_client);
+ }
+ }
+ for (const auto& fragment : fragments_event_to_master_) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragment), master_client);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for ( int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,1,0,4};
+ std::cout << __LINE__ << ": using following predefined sequence to send event to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase second last segment by 16 byte at front and back
+ increase_segment_front_back(fragments_event_to_master_[4], 16);
+ // update length
+ *(reinterpret_cast<vsomeip::length_t*>(&((*fragments_event_to_master_[4])[VSOMEIP_LENGTH_POS_MIN]))) =
+ htonl(static_cast<vsomeip::length_t>(fragments_event_to_master_[4]->size() - VSOMEIP_SOMEIP_HEADER_SIZE));
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_event_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_event_to_master_.rbegin();
+ iter != fragments_event_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_event_to_master_.rbegin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_event_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x55;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x55;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xbb;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xbb;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xbb;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xbb;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_event_to_master_[4], 16);
+ }
+ for (auto iter = fragments_event_to_master_.rbegin(); iter != fragments_event_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ }
+ std::cout << __LINE__ << ": send event to master " << std::uint32_t(mode) << std::endl;
+ }
+
+ for (const order_e mode : {order_e::ASCENDING, order_e::DESCENDING}) {
+ while (wait_for_all_fragments_received_as_server_) {
+ if (std::cv_status::timeout ==
+ all_fragments_received_as_server_cond_.wait_for(all_fragments_received_as_server_lock,
+ std::chrono::seconds(20))) {
+ ADD_FAILURE() << "Didn't receive request from client within time: " << std::uint32_t(mode);
+ return;
+ } else {
+ EXPECT_EQ(someip_tp_test::number_of_fragments, fragments_received_as_server_.size());
+ // create complete message from request of client
+ vsomeip::message_buffer_t its_request = create_full_message(fragments_received_as_server_);
+ if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * (someip_tp_test::max_segment_size - 160),
+ its_request.size());
+ } else {
+ EXPECT_EQ(VSOMEIP_FULL_HEADER_SIZE +
+ someip_tp_test::number_of_fragments * someip_tp_test::max_segment_size,
+ its_request.size());
+ }
+ const vsomeip::client_t its_request_client =
+ VSOMEIP_BYTES_TO_WORD(its_request[VSOMEIP_CLIENT_POS_MIN],
+ its_request[VSOMEIP_CLIENT_POS_MAX]);
+ const vsomeip::session_t its_request_session =
+ VSOMEIP_BYTES_TO_WORD(its_request[VSOMEIP_SESSION_POS_MIN],
+ its_request[VSOMEIP_SESSION_POS_MAX]);
+ create_fragments(someip_tp_test::number_of_fragments,
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.method_id,
+ vsomeip::message_type_e::MT_RESPONSE,
+ its_request_client,
+ its_request_session,
+ &fragments_response_to_master_,
+ (test_mode_ == someip_tp_test::test_mode_e::OVERLAP ||
+ test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ vsomeip::tp::tp::tp_max_segment_length_ - 160:
+ vsomeip::tp::tp::tp_max_segment_length_);
+ // create complete message from response
+ vsomeip::message_buffer_t its_response = create_full_message(fragments_response_to_master_);
+ // change the message type of the response to request for comparison
+ its_response[VSOMEIP_MESSAGE_TYPE_POS] = static_cast<vsomeip::byte_t>(vsomeip::message_type_e::MT_REQUEST);
+
+ EXPECT_EQ(its_response.size(), its_request.size());
+ EXPECT_EQ(its_response, its_request);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_response[0]),
+ static_cast<void*>(&its_request[0]),
+ its_response.size()));
+ // send back response
+ fragments_received_as_server_.clear();
+ EXPECT_GT(remote_client_request_port, 0);
+ boost::asio::ip::udp::socket::endpoint_type master_client(address_remote_, remote_client_request_port);
+ if (mode == order_e::ASCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {4,2,0,1,3,5};
+ std::cout << __LINE__ << ": using following predefined sequence to send back response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {0,2,4,3,5,1};
+ std::cout << __LINE__ << ": using following predefined sequence to send response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase fourth segment by 16 byte at front and back
+ increase_segment_front_back(fragments_response_to_master_[3], 16);
+ increase_segment_front(fragments_response_to_master_[1], 16);
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_response_to_master_.begin();
+ iter != fragments_response_to_master_.end(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send 2nd fragment twice
+ if (iter == fragments_response_to_master_.begin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send a fragment with invalid segment size as well
+ decrease_segment_back(*iter, 16);
+ increase_segment_back(*iter, 7);
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ increase_segment_back(*iter, 9);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_response_to_master_[4]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x99;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x99;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xaa;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xaa;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xaa;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xaa;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second segment by 16 byte
+ increase_segment_back(fragments_response_to_master_[1], 16);
+ }
+ for (const auto& frag : fragments_response_to_master_) {
+ udp_server_socket.send_to(boost::asio::buffer(*frag), master_client);
+ }
+ }
+ } else if (mode == order_e::DESCENDING) {
+ if (test_mode_ == someip_tp_test::test_mode_e::MIXED) {
+ std::vector<int> its_indexes = create_shuffled_seqeuence(someip_tp_test::number_of_fragments);
+ std::cout << __LINE__ << ": using following random sequence to send back response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ for ( int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) {
+ if (someip_tp_test::number_of_fragments != 6) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ } else {
+ auto its_indexes = {5,3,2,1,4,0};
+ std::cout << __LINE__ << ": using following predefined sequence to send response to master: ";
+ for (auto i : its_indexes) { std::cout << i << ", "; }
+ std::cout << std::endl;
+ // increase fith segment by 16 byte at front and back
+ increase_segment_front_back(fragments_response_to_master_[4], 16);
+ for (int i : its_indexes) {
+ udp_server_socket.send_to(boost::asio::buffer(*fragments_response_to_master_[i]), master_client);
+ }
+ }
+ } else if (test_mode_ == someip_tp_test::test_mode_e::DUPLICATE) {
+ if (someip_tp_test::number_of_fragments < 2) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ for (auto iter = fragments_response_to_master_.rbegin();
+ iter != fragments_response_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ // send insert 2nd last fragment twice
+ if (iter == fragments_response_to_master_.rbegin() + 1) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ } else {
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ if (someip_tp_test::number_of_fragments < 4) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // send an event fragment with a different session ID first
+ vsomeip::message_buffer_t msg_incomplete(*fragments_response_to_master_[3]);
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0x66;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0x66;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ // send a request with a different service ID as well to test cleanup
+ msg_incomplete[VSOMEIP_SERVICE_POS_MIN] = 0xef;
+ msg_incomplete[VSOMEIP_SERVICE_POS_MAX] = 0xef;
+ msg_incomplete[VSOMEIP_SESSION_POS_MIN] = 0xef;
+ msg_incomplete[VSOMEIP_SESSION_POS_MAX] = 0xef;
+ udp_server_socket.send_to(boost::asio::buffer(msg_incomplete), master_client);
+ } else if (test_mode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (someip_tp_test::number_of_fragments < 5) {
+ ADD_FAILURE() << "line: " << __LINE__ << " needs adaption as number_of_fragments changed";
+ return;
+ }
+ // increase second last segment by 16 byte
+ increase_segment_back(fragments_response_to_master_[4], 16);
+ }
+ for (auto iter = fragments_response_to_master_.rbegin();
+ iter != fragments_response_to_master_.rend(); iter++) {
+ udp_server_socket.send_to(boost::asio::buffer(*(*iter)), master_client);
+ }
+ }
+ }
+ }
+ }
+ wait_for_all_fragments_received_as_server_ = true;
+ }
+ });
+
+ std::thread udp_server_receive_thread([&]() {
+ {
+ std::lock_guard<std::mutex> its_lock(udp_sd_socket_mutex);
+ offer_service(&udp_sd_socket);
+ }
+
+ bool keep_receiving(true);
+ std::vector<std::uint8_t> receive_buffer(4096);
+ while (keep_receiving) {
+ boost::system::error_code error;
+ boost::asio::ip::udp::socket::endpoint_type its_remote_endpoint;
+ std::size_t bytes_transferred = udp_server_socket.receive_from(
+ boost::asio::buffer(receive_buffer, receive_buffer.capacity()), its_remote_endpoint, 0, error);
+ if (error) {
+ keep_receiving = false;
+ ADD_FAILURE() << __func__ << " error: " << error.message();
+ return;
+ } else {
+ remote_client_request_port = its_remote_endpoint.port();
+ std::uint32_t its_pos = 0;
+ while (bytes_transferred > 0) {
+ const std::uint32_t its_message_size = VSOMEIP_BYTES_TO_LONG(
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 1],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 2],
+ receive_buffer[its_pos + VSOMEIP_LENGTH_POS_MIN + 3]) + VSOMEIP_SOMEIP_HEADER_SIZE;
+ std::cout << __LINE__ << ": received request from master " << its_message_size << std::endl;
+ vsomeip::deserializer its_deserializer(&receive_buffer[its_pos], its_message_size, 0);
+
+ vsomeip::service_t its_service = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_SERVICE_POS_MAX]);
+ vsomeip::method_t its_method = VSOMEIP_BYTES_TO_WORD(receive_buffer[its_pos + VSOMEIP_METHOD_POS_MIN],
+ receive_buffer[its_pos + VSOMEIP_METHOD_POS_MAX]);
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, its_service);
+ EXPECT_EQ(someip_tp_test::service_slave.method_id, its_method);
+ vsomeip::message_impl msg;
+ EXPECT_TRUE(msg.deserialize(&its_deserializer));
+ if (vsomeip::tp::tp::tp_flag_is_set(receive_buffer[its_pos + VSOMEIP_MESSAGE_TYPE_POS])) {
+ auto its_buffer = std::make_shared<vsomeip::message_buffer_t>(&receive_buffer[its_pos], &receive_buffer[its_pos] + its_message_size);
+
+ fragments_received_as_server_.push_back(its_buffer);
+ if (fragments_received_as_server_.size() == someip_tp_test::number_of_fragments) {
+ std::lock_guard<std::mutex> its_lock(all_fragments_received_as_server_mutex_);
+ wait_for_all_fragments_received_as_server_ = false;
+ std::cout << __LINE__ << ": received all fragments as server" << std::endl;
+ all_fragments_received_as_server_cond_.notify_one();
+ static int received_requests = 0;
+ if (++received_requests == 2) {
+ std::cout << __LINE__ << ": received all requests as server --> Finished" << std::endl;
+ keep_receiving = false;
+ }
+ }
+ }
+ its_pos += its_message_size;
+ bytes_transferred -= its_message_size;
+ }
+ }
+ }
+ });
+
+ send_thread.join();
+ sd_receive_thread.join();
+ udp_server_receive_thread.join();
+ udp_server_send_thread.join();
+
+ if (test_mode_ == someip_tp_test::test_mode_e::INCOMPLETE) {
+ std::cout << "Sleeping to let cleanup for unfinished TP message "
+ "trigger on master side..." << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(11));
+ }
+ // shutdown the server
+ call_shutdown_method();
+
+ boost::system::error_code ec;
+ udp_sd_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_sd_socket.close(ec);
+ udp_client_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_client_socket.close(ec);
+ udp_server_socket.shutdown(boost::asio::socket_base::shutdown_both, ec);
+ udp_server_socket.close(ec);
+}
+
+#ifndef _WIN32
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ if(argc < 3) {
+ std::cerr << "Please pass an target, local IP address and test mode to this binary like: "
+ << argv[0] << " 10.0.3.1 10.0.3.202 TP_IN_SEQUENCE" << std::endl;
+ std::cerr << "Testmodes are [ IN_SEQUENCE, MIXED, INCOMPLETE, OVERLAP, OVERLAP_FRONT_BACK ]" << std::endl;
+ } else {
+ remote_address = argv[1];
+ local_address = argv[2];
+ std::string its_testmode = argv[3];
+ if (its_testmode == std::string("IN_SEQUENCE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/0";
+ } else if (its_testmode == std::string("MIXED")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/1";
+ } else if (its_testmode == std::string("INCOMPLETE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/2";
+ } else if (its_testmode == std::string("DUPLICATE")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/3";
+ } else if (its_testmode == std::string("OVERLAP")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/4";
+ } else if (its_testmode == std::string("OVERLAP_FRONT_BACK")) {
+ ::testing::GTEST_FLAG(filter) = "*send_in_mode/5";
+ }
+ }
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/someip_tp_tests/someip_tp_test_service.cpp b/test/someip_tp_tests/someip_tp_test_service.cpp
new file mode 100644
index 0000000..dd94b6c
--- /dev/null
+++ b/test/someip_tp_tests/someip_tp_test_service.cpp
@@ -0,0 +1,412 @@
+// Copyright (C) 2014-2019 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <chrono>
+#include <condition_variable>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <thread>
+#include <map>
+#include <algorithm>
+#include <atomic>
+#include <future>
+#include <cstring>
+
+#include <gtest/gtest.h>
+
+#include <vsomeip/vsomeip.hpp>
+#include <vsomeip/internal/logger.hpp>
+#include "../../implementation/endpoints/include/tp.hpp"
+
+#include "someip_tp_test_globals.hpp"
+
+class someip_tp_test_service {
+public:
+ someip_tp_test_service(struct someip_tp_test::service_info _service_info, someip_tp_test::test_mode_e _testmode) :
+ service_info_(_service_info),
+ testmode_(_testmode),
+ app_(vsomeip::runtime::get()->create_application("someip_tp_test_service")),
+ wait_until_registered_(true),
+ wait_until_shutdown_method_called_(true),
+ wait_for_slave_subscription_(true),
+ number_notifications_of_slave_(0x0),
+ wait_for_slave_service_available_(true),
+ wait_for_two_responses_of_slave_(true),
+ number_responses_of_slave_(0),
+ wait_for_two_requests_of_slave_(true),
+ number_requests_from_slave_(0),
+ wait_for_two_notifications_of_slave_(true),
+ offer_thread_(std::bind(&someip_tp_test_service::run, this)) {
+ if (!app_->init()) {
+ ADD_FAILURE() << "Couldn't initialize application";
+ return;
+ }
+ app_->register_state_handler(
+ std::bind(&someip_tp_test_service::on_state, this,
+ std::placeholders::_1));
+
+ // offer field
+ std::set<vsomeip::eventgroup_t> its_eventgroups;
+ its_eventgroups.insert(_service_info.eventgroup_id);
+ app_->offer_event(service_info_.service_id, service_info_.instance_id,
+ service_info_.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, service_info_.shutdown_method_id,
+ std::bind(&someip_tp_test_service::on_shutdown_method_called, this,
+ std::placeholders::_1));
+
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, service_info_.notify_method_id,
+ std::bind(&someip_tp_test_service::on_notify_method_called, this,
+ std::placeholders::_1));
+ app_->register_message_handler(vsomeip::ANY_SERVICE,
+ vsomeip::ANY_INSTANCE, service_info_.method_id,
+ std::bind(&someip_tp_test_service::on_message, this,
+ std::placeholders::_1));
+
+ app_->register_async_subscription_handler(service_info_.service_id,
+ 0x1, service_info_.eventgroup_id,
+ std::bind(&someip_tp_test_service::subscription_handler_async,
+ this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+ std::placeholders::_4, std::placeholders::_5));
+
+ // request remote service
+ app_->request_service(someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id);
+ its_eventgroups.clear();
+ its_eventgroups.insert(someip_tp_test::service_slave.eventgroup_id);
+ app_->request_event(someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_EVENT);
+ app_->register_message_handler(someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.event_id,
+ std::bind(&someip_tp_test_service::on_notification, this,
+ std::placeholders::_1));
+ app_->subscribe(someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.eventgroup_id, 0x0,
+ someip_tp_test::service_slave.event_id);
+ app_->register_availability_handler(someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ std::bind(&someip_tp_test_service::on_availability, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ app_->register_message_handler(
+ someip_tp_test::service_slave.service_id,
+ someip_tp_test::service_slave.instance_id,
+ someip_tp_test::service_slave.method_id,
+ std::bind(&someip_tp_test_service::on_response_from_slave, this,
+ std::placeholders::_1));
+ app_->start();
+ }
+
+ ~someip_tp_test_service() {
+ offer_thread_.join();
+ }
+
+ void offer() {
+ app_->offer_service(service_info_.service_id, 0x1);
+ }
+
+ void stop() {
+ app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
+ app_->clear_all_handler();
+ app_->stop();
+ }
+
+ void on_state(vsomeip::state_type_e _state) {
+ VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ << (_state == vsomeip::state_type_e::ST_REGISTERED ?
+ "registered." : "deregistered.");
+
+ if (_state == vsomeip::state_type_e::ST_REGISTERED) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_registered_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _available) {
+ if (_service == someip_tp_test::service_slave.service_id &&
+ _instance == someip_tp_test::service_slave.instance_id &&
+ _available) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_for_slave_service_available_ = false;
+ condition_.notify_one();
+ VSOMEIP_INFO << "Service available Service/Instance ["
+ << std::setw(4) << std::setfill('0') << std::hex << _service << "/"
+ << std::setw(4) << std::setfill('0') << std::hex << _instance << "]";
+ }
+ }
+
+ void on_message(const std::shared_ptr<vsomeip::message>& _message) {
+ VSOMEIP_INFO << "Received a message with Client/Session ["
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_session()
+ << "] size: " << std::dec << _message->get_payload()->get_length();
+ auto response = vsomeip::runtime::get()->create_response(_message);
+ auto payload = vsomeip::runtime::get()->create_payload(_message->get_payload()->get_data(), _message->get_payload()->get_length());
+ response->set_payload(payload);
+ app_->send(response);
+ if (++number_requests_from_slave_ == 2) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_for_two_requests_of_slave_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_notification(const std::shared_ptr<vsomeip::message>& _message) {
+ VSOMEIP_INFO << "Received a notification with Client/Session ["
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_session()
+ << "] size: " << std::dec << _message->get_payload()->get_length();
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, _message->get_service());
+ EXPECT_EQ(someip_tp_test::service_slave.event_id, _message->get_method());
+ std::vector<vsomeip::byte_t> its_cmp_data =
+ generate_payload(someip_tp_test::number_of_fragments,
+ (testmode_ == someip_tp_test::test_mode_e::OVERLAP
+ || testmode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ someip_tp_test::max_segment_size - 160 :
+ someip_tp_test::max_segment_size);
+
+ std::vector<vsomeip::byte_t> its_rcv_data(_message->get_payload()->get_data(),
+ _message->get_payload()->get_data() + _message->get_payload()->get_length());
+ EXPECT_EQ(its_cmp_data.size(), its_rcv_data.size());
+ if (testmode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (number_notifications_of_slave_ == 0) { //ASCENDING with 2nd segment too big
+ for (std::uint32_t i = 0; i < 16; i++) {
+ its_cmp_data[2 * (someip_tp_test::max_segment_size - 160) + i] = 0xff;
+ }
+ } else if (number_notifications_of_slave_ == 1) {
+ // DESCENDING with 2nd last segment too big
+ // no action as successive 4 byte at end of message would
+ // overwrite the beginning of the last segment which was received first
+ }
+ }
+ EXPECT_EQ(its_cmp_data, its_rcv_data);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_cmp_data[0]),
+ static_cast<void*>(&its_rcv_data[0]),
+ its_cmp_data.size()));
+ if (++number_notifications_of_slave_ == 2) {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_for_two_notifications_of_slave_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ void on_shutdown_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ app_->send(vsomeip::runtime::get()->create_response(_message));
+ VSOMEIP_WARNING << "************************************************************";
+ VSOMEIP_WARNING << "Shutdown method called -> going down!";
+ VSOMEIP_WARNING << "************************************************************";
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_until_shutdown_method_called_ = false;
+ condition_.notify_one();
+ }
+
+ void on_notify_method_called(const std::shared_ptr<vsomeip::message> &_message) {
+ (void)_message;
+ std::vector<vsomeip::byte_t> its_data = generate_payload(someip_tp_test::number_of_fragments,
+ (testmode_ == someip_tp_test::test_mode_e::OVERLAP) ?
+ someip_tp_test::max_segment_size - 160 :
+ someip_tp_test::max_segment_size);
+ std::shared_ptr<vsomeip::payload> its_payload = vsomeip::runtime::get()->create_payload();
+ its_payload->set_data(its_data);
+ app_->notify(service_info_.service_id, service_info_.instance_id,
+ service_info_.event_id, its_payload);
+ VSOMEIP_INFO << __func__ << " send event";
+ notify_method_called_.set_value(true);
+ }
+
+ void send_fragmented_request_to_slave() {
+ auto its_req = vsomeip::runtime::get()->create_request();
+ its_req->set_service(someip_tp_test::service_slave.service_id);
+ its_req->set_instance(someip_tp_test::service_slave.instance_id);
+ its_req->set_method(someip_tp_test::service_slave.method_id);
+ std::vector<vsomeip::byte_t> its_data = generate_payload(someip_tp_test::number_of_fragments,
+ (testmode_ == someip_tp_test::test_mode_e::OVERLAP
+ || testmode_ == someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK) ?
+ someip_tp_test::max_segment_size - 160 :
+ someip_tp_test::max_segment_size);
+ auto its_payload = vsomeip::runtime::get()->create_payload();
+ its_payload->set_data(its_data);
+ its_req->set_payload(its_payload);
+ request_send_to_slave_ = its_req;
+ app_->send(its_req);
+ }
+
+ void on_response_from_slave(const std::shared_ptr<vsomeip::message> &_message) {
+ VSOMEIP_INFO << "Received a response from the slave with Client/Session ["
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_client() << "/"
+ << std::setw(4) << std::setfill('0') << std::hex << _message->get_session()
+ << "] size: " << std::dec << _message->get_payload()->get_length();
+ EXPECT_EQ(someip_tp_test::service_slave.service_id, _message->get_service());
+ EXPECT_EQ(someip_tp_test::service_slave.instance_id, _message->get_instance());
+ EXPECT_EQ(someip_tp_test::service_slave.method_id, _message->get_method());
+ std::vector<vsomeip::byte_t> its_resp_payload(_message->get_payload()->get_data(),
+ _message->get_payload()->get_data() + _message->get_payload()->get_length());
+ std::vector<vsomeip::byte_t> its_req_payload(request_send_to_slave_->get_payload()->get_data(),
+ request_send_to_slave_->get_payload()->get_data() + request_send_to_slave_->get_payload()->get_length());
+ if (testmode_ == someip_tp_test::test_mode_e::OVERLAP) {
+ if (number_responses_of_slave_ == 0) { //ASCENDING with 2nd segment too big
+ for (std::uint32_t i = 0; i < 16; i++) {
+ its_req_payload[2 * (someip_tp_test::max_segment_size - 160) + i] = 0xff;
+ }
+ } else if (number_responses_of_slave_ == 1) {
+ // DESCENDING with 2nd last segment too big
+ // no action as successive 4 byte at end of message would
+ // overwrite the beginning of the last segment which was received first
+ }
+ }
+
+ EXPECT_EQ(its_req_payload.size(), its_resp_payload.size());
+ EXPECT_EQ(its_req_payload, its_resp_payload);
+ EXPECT_EQ(0, std::memcmp(static_cast<void*>(&its_req_payload[0]),
+ static_cast<void*>(&its_resp_payload[0]),
+ its_req_payload.size()));
+
+ if (++number_responses_of_slave_ < 2) {
+ send_fragmented_request_to_slave();
+ } else {
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_for_two_responses_of_slave_ = false;
+ condition_.notify_one();
+ }
+ }
+
+ std::vector<vsomeip::byte_t> generate_payload(std::uint32_t _number_of_fragments,
+ std::uint32_t _segment_size) {
+ std::vector<vsomeip::byte_t> its_data;
+ for (std::uint32_t i = 0; i < _number_of_fragments; i++) {
+ its_data.resize((i * _segment_size) + _segment_size,
+ static_cast<std::uint8_t>(i));
+ }
+ return its_data;
+ }
+
+ void run() {
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Running";
+ std::unique_lock<std::mutex> its_lock(mutex_);
+ while (wait_until_registered_) {
+ condition_.wait(its_lock);
+ }
+
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
+ << service_info_.service_id << "] Offering";
+ offer();
+
+ while (wait_for_slave_service_available_) {
+ condition_.wait(its_lock);
+ }
+ send_fragmented_request_to_slave();
+
+ while (wait_for_two_responses_of_slave_) {
+ condition_.wait(its_lock);
+ }
+ EXPECT_EQ(2u, number_responses_of_slave_);
+
+ while (wait_for_two_requests_of_slave_) {
+ condition_.wait(its_lock);
+ }
+ EXPECT_EQ(2u, number_requests_from_slave_);
+
+ while (wait_for_two_notifications_of_slave_) {
+ condition_.wait(its_lock);
+ }
+ EXPECT_EQ(2u, number_notifications_of_slave_);
+
+ while (wait_for_slave_subscription_) {
+ condition_.wait(its_lock);
+ }
+ // slave subscribed --> sent a notification
+ on_notify_method_called(vsomeip::runtime::get()->create_message());
+
+ while (wait_until_shutdown_method_called_) {
+ condition_.wait(its_lock);
+ }
+ stop();
+ }
+
+ void subscription_handler_async(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid,
+ bool _subscribed, const std::function<void(const bool)>& _cbk) {
+ (void)_uid;
+ (void)_gid;
+ VSOMEIP_WARNING << __func__ << " " << std::hex << _client << " subscribed." << _subscribed;
+ static int was_called = 0;
+ was_called++;
+ EXPECT_EQ(1, was_called);
+ EXPECT_TRUE(_subscribed);
+ _cbk(true);
+ std::lock_guard<std::mutex> its_lock(mutex_);
+ wait_for_slave_subscription_ = false;
+ condition_.notify_one();
+ }
+
+
+private:
+ struct someip_tp_test::service_info service_info_;
+ someip_tp_test::test_mode_e testmode_;
+ std::shared_ptr<vsomeip::application> app_;
+
+ bool wait_until_registered_;
+ bool wait_until_shutdown_method_called_;
+ std::mutex mutex_;
+ std::condition_variable condition_;
+ std::atomic<bool> wait_for_slave_subscription_;
+ std::atomic<std::uint32_t> number_notifications_of_slave_;
+ std::promise<bool> notify_method_called_;
+ bool wait_for_slave_service_available_;
+ bool wait_for_two_responses_of_slave_;
+ std::uint32_t number_responses_of_slave_;
+ bool wait_for_two_requests_of_slave_;
+ std::uint32_t number_requests_from_slave_;
+ bool wait_for_two_notifications_of_slave_;
+ std::shared_ptr<vsomeip::message> request_send_to_slave_;
+ std::thread offer_thread_;
+};
+
+someip_tp_test::test_mode_e its_testmode(someip_tp_test::test_mode_e::IN_SEQUENCE);
+
+TEST(someip_someip_tp_test, echo_requests)
+{
+ someip_tp_test_service its_sample(someip_tp_test::service, its_testmode);
+}
+
+
+#ifndef _WIN32
+int main(int argc, char** argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ if (argc < 2) {
+ std::cerr << "Please pass a test mode to this binary like: "
+ << argv[0] << " IN_SEQUENCE" << std::endl;
+ std::cerr << "Testmodes are [ IN_SEQUENCE, MIXED, INCOMPLETE, DUPLICATE, OVERLAP, OVERLAP_FRONT_BACK ]" << std::endl;
+ exit(1);
+ }
+
+ std::string its_pased_testmode = argv[1];
+ if (its_pased_testmode == std::string("IN_SEQUENCE")) {
+ its_testmode = someip_tp_test::test_mode_e::IN_SEQUENCE;
+ } else if (its_pased_testmode == std::string("MIXED")) {
+ its_testmode = someip_tp_test::test_mode_e::MIXED;
+ } else if (its_pased_testmode == std::string("INCOMPLETE")) {
+ its_testmode = someip_tp_test::test_mode_e::INCOMPLETE;
+ } else if (its_pased_testmode == std::string("DUPLICATE")) {
+ its_testmode = someip_tp_test::test_mode_e::DUPLICATE;
+ } else if (its_pased_testmode == std::string("OVERLAP")) {
+ its_testmode = someip_tp_test::test_mode_e::OVERLAP;
+ } else if (its_pased_testmode == std::string("OVERLAP_FRONT_BACK")) {
+ its_testmode = someip_tp_test::test_mode_e::OVERLAP_FRONT_BACK;
+ }
+
+ return RUN_ALL_TESTS();
+}
+#endif
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
index c551b55..a9adfe0 100755
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_master_starter.sh
@@ -10,70 +10,47 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP subscribe_notify_one_test_diff_client_ids_diff_ports_master.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
- echo "For example: $0 UDP subscribe_notify_one_test_diff_client_ids_diff_ports_master.json"
- exit 1
-fi
-
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $1 ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
+ echo "For example: $0 subscribe_notify_one_test_diff_client_ids_diff_ports_master.json"
exit 1
fi
# replace master with slave to be able display the correct json file to be used
# with the slave script
-MASTER_JSON_FILE=$2
+MASTER_JSON_FILE=$1
CLIENT_JSON_FILE=${MASTER_JSON_FILE/master/slave}
FAIL=0
# Start the services
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_one
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_one_test_service 1 $1 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_one_test_service 1 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_two
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_one_test_service 2 $1 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_one_test_service 2 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_three
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_one_test_service 3 $1 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_one_test_service 3 &
sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
- echo "starting subscribe_notify_one_test_slave_starter.sh on slave LXC with parameters $1 $CLIENT_JSON_FILE"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./subscribe_notify_one_test_slave_starter.sh $1 $CLIENT_JSON_FILE\"" &
+ echo "starting subscribe_notify_one_test_slave_starter.sh on slave LXC with parameters $CLIENT_JSON_FILE"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./subscribe_notify_one_test_slave_starter.sh $CLIENT_JSON_FILE\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name snotms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./subscribe_notify_one_test_slave_starter.sh $1 $CLIENT_JSON_FILE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_one_test_slave_starter.sh $CLIENT_JSON_FILE" &
else
cat <<End-of-message
*******************************************************************************
*******************************************************************************
** Please now run:
-** subscribe_notify_one_test_slave_starter.sh $1 $CLIENT_JSON_FILE
+** subscribe_notify_one_test_slave_starter.sh $CLIENT_JSON_FILE
** from an external host to successfully complete this test.
**
** You probably will need to adapt the 'unicast' settings in
@@ -92,11 +69,6 @@ do
wait $job || ((FAIL+=1))
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop snotms
- docker rm snotms
-fi
-
# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
index f738b38..923ba1c 100644
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_service.cpp
@@ -17,17 +17,15 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "subscribe_notify_one_test_globals.hpp"
class subscribe_notify_one_test_service {
public:
- subscribe_notify_one_test_service(struct subscribe_notify_one_test::service_info _service_info,
- vsomeip::subscription_type_e _subscription_type) :
+ subscribe_notify_one_test_service(struct subscribe_notify_one_test::service_info _service_info) :
service_info_(_service_info),
- subscription_type_(_subscription_type),
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
wait_until_other_services_available_(true),
@@ -51,7 +49,9 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(service_info_.eventgroup_id);
app_->offer_event(service_info_.service_id, service_info_.instance_id,
- service_info_.event_id, its_eventgroups, false);
+ service_info_.event_id, its_eventgroups, vsomeip::event_type_e::ET_SELECTIVE_EVENT,
+ std::chrono::milliseconds::zero(), false, true, nullptr,
+ vsomeip::reliability_type_e::RT_UNKNOWN);
app_->register_message_handler(service_info_.service_id,
service_info_.instance_id, service_info_.method_id,
@@ -63,7 +63,8 @@ public:
app_->register_subscription_handler(service_info_.service_id,
service_info_.instance_id, service_info_.eventgroup_id,
std::bind(&subscribe_notify_one_test_service::on_subscription, this,
- std::placeholders::_1, std::placeholders::_2));
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
// register availability for all other services and request their event.
for(const auto& i : subscribe_notify_one_test::service_infos) {
@@ -81,19 +82,19 @@ public:
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3));
- app_->request_service(i.service_id, i.instance_id, vsomeip::DEFAULT_MAJOR, vsomeip::DEFAULT_MINOR, true);
+ app_->request_service(i.service_id, i.instance_id, vsomeip::DEFAULT_MAJOR, vsomeip::DEFAULT_MINOR);
auto handler = std::bind(&subscribe_notify_one_test_service::on_subscription_state_change, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
- app_->register_subscription_status_handler(i.service_id, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler, true);
+ app_->register_subscription_status_handler(i.service_id, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
app_->register_subscription_status_handler(vsomeip::ANY_SERVICE, i.instance_id, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
app_->register_subscription_status_handler(i.service_id, vsomeip::ANY_INSTANCE, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
app_->register_subscription_status_handler(vsomeip::ANY_SERVICE, vsomeip::ANY_INSTANCE, i.eventgroup_id, vsomeip::ANY_EVENT, handler);
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(i.eventgroup_id);
- app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, false);
+ app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, vsomeip::event_type_e::ET_SELECTIVE_EVENT);
other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false;
other_services_received_notification_[std::make_pair(i.service_id, i.method_id)] = 0;
@@ -112,11 +113,12 @@ public:
}
void stop_offer() {
+ app_->stop_offer_event(service_info_.service_id, service_info_.instance_id, service_info_.event_id);
app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
}
void on_state(vsomeip::state_type_e _state) {
- VSOMEIP_INFO << "Application " << app_->get_name() << " is "
+ VSOMEIP_DEBUG << "Application " << app_->get_name() << " is "
<< (_state == vsomeip::state_type_e::ST_REGISTERED ?
"registered." : "deregistered.");
@@ -134,7 +136,7 @@ public:
if(its_service != other_services_available_.end()) {
if(its_service->second != _is_available) {
its_service->second = true;
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] Service ["
<< std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
<< "] is available.";
@@ -164,14 +166,18 @@ public:
subscription_state_handler_called_++;
} else {
subscription_error_occured_ = true;
- VSOMEIP_WARNING << std::hex << app_->get_client()
+ VSOMEIP_ERROR << std::hex << app_->get_client()
<< " : on_subscription_state_change: for service " << std::hex
<< _service << " received a subscription error!";
}
+
}
- bool on_subscription(vsomeip::client_t _client, bool _subscribed) {
+ bool on_subscription(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid, bool _subscribed) {
+ (void)_uid;
+ (void)_gid;
std::lock_guard<std::mutex> its_subscribers_lock(subscribers_mutex_);
+
// check if all other services have subscribed:
// -1 for placeholder in array and -1 for the service itself
if (subscribers_.size() == subscribe_notify_one_test::service_infos.size() - 2) {
@@ -187,9 +193,10 @@ public:
VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id << "] " << "Client: " << _client
<< " subscribed, now have " << std::dec << subscribers_.size()
- << " subscribers" ;
+ << " subscribers. Expecting " << std::dec
+ << subscribe_notify_one_test::service_infos.size() - 2;
- if(subscribers_.size() == subscribe_notify_one_test::service_infos.size() - 2)
+ if (subscribers_.size() == subscribe_notify_one_test::service_infos.size() - 2)
{
// notify the notify thread to start sending out notifications
std::lock_guard<std::mutex> its_lock(notify_mutex_);
@@ -212,7 +219,7 @@ public:
}
void on_message(const std::shared_ptr<vsomeip::message> &_message) {
- if(_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
+ if (_message->get_message_type() == vsomeip::message_type_e::MT_NOTIFICATION) {
other_services_received_notification_[std::make_pair(_message->get_service(),
_message->get_method())]++;
@@ -229,21 +236,7 @@ public:
<< std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
_message->get_method())] << ")";
-
- bool notify(false);
- switch(subscription_type_) {
- case vsomeip::subscription_type_e::SU_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_RELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE:
- if (all_notifications_received()) {
- notify = true;
- }
- break;
- }
-
- if(notify) {
+ if (all_notifications_received()) {
std::lock_guard<std::mutex> its_lock(stop_mutex_);
wait_for_stop_ = false;
stop_condition_.notify_one();
@@ -319,7 +312,7 @@ public:
++subscribe_count;
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_);
+ vsomeip::DEFAULT_MAJOR);
VSOMEIP_DEBUG << "[" << std::hex << service_info_.service_id
<< "] subscribing to Service/Instance/Eventgroup ["
@@ -342,7 +335,7 @@ public:
// 4 * subscribe count cause we installed three additional wild-card handlers
ASSERT_EQ(subscribe_count * 4, subscription_state_handler_called_);
} else {
- VSOMEIP_WARNING << "Subscription state handler check skipped: CallCount="
+ VSOMEIP_ERROR << "Subscription state handler check skipped: CallCount="
<< std::dec << subscription_state_handler_called_;
}
}
@@ -360,9 +353,6 @@ public:
// on the remote node
std::this_thread::sleep_for(std::chrono::milliseconds(500));
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
- << service_info_.service_id << "] Starting to notify";
-
for(uint32_t i = 0; i < subscribe_notify_one_test::notifications_to_send; i++) {
std::shared_ptr<vsomeip::payload> its_payload =
vsomeip::runtime::get()->create_payload();
@@ -389,7 +379,7 @@ public:
while (wait_for_stop_) {
stop_condition_.wait(its_lock);
}
- VSOMEIP_INFO << "[" << std::setw(4) << std::setfill('0') << std::hex
+ VSOMEIP_DEBUG << "[" << std::setw(4) << std::setfill('0') << std::hex
<< service_info_.service_id
<< "] Received notifications from all other services, going down";
@@ -426,8 +416,8 @@ public:
|| (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
continue;
}
- app_->register_subscription_status_handler(i.service_id, i.instance_id,
- i.eventgroup_id, vsomeip::ANY_EVENT, nullptr);
+ app_->unregister_subscription_status_handler(i.service_id, i.instance_id,
+ i.eventgroup_id, vsomeip::ANY_EVENT);
app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
app_->release_event(i.service_id, i.instance_id, i.event_id);
app_->release_service(i.service_id, i.instance_id);
@@ -439,7 +429,6 @@ public:
private:
subscribe_notify_one_test::service_info service_info_;
- vsomeip::subscription_type_e subscription_type_;
std::shared_ptr<vsomeip::application> app_;
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_notification_;
@@ -468,45 +457,25 @@ private:
std::mutex subscribers_mutex_;
};
-static int service_number;
-static vsomeip::subscription_type_e subscription_type;
+static unsigned long service_number;
TEST(someip_subscribe_notify_one_test, send_ten_notifications_to_service)
{
subscribe_notify_one_test_service its_sample(
- subscribe_notify_one_test::service_infos[service_number], subscription_type);
+ subscribe_notify_one_test::service_infos[service_number]);
}
#ifndef _WIN32
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
- if(argc < 3) {
+ if(argc < 2) {
std::cerr << "Please specify a service number and subscription type, like: " << argv[0] << " 2 UDP" << std::endl;
std::cerr << "Valid service numbers are in the range of [1,6]" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
return 1;
}
- service_number = std::stoi(std::string(argv[1]), nullptr);
-
- if(std::string("TCP_AND_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE;
- } else if(std::string("PREFER_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE;
- } else if(std::string("PREFER_TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_RELIABLE;
- } else if(std::string("UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_UNRELIABLE;
- } else if(std::string("TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE;
- } else {
- std::cerr << "Wrong subscription type passed, exiting" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
- return 1;
- }
+ service_number = std::stoul(std::string(argv[1]), nullptr);
return RUN_ALL_TESTS();
}
#endif
diff --git a/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh b/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
index 47d0b2d..10014ae 100755
--- a/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
+++ b/test/subscribe_notify_one_tests/subscribe_notify_one_test_slave_starter.sh
@@ -10,49 +10,25 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
- echo "For example: $0 UDP subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json"
+ echo "For example: $0 subscribe_notify_one_test_diff_client_ids_diff_ports_slave.json"
exit 1
fi
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $1 ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
- exit 1
-fi
-
-
FAIL=0
# Start the services
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_four
-export VSOMEIP_CONFIGURATION=$2
+export VSOMEIP_CONFIGURATION=$1
./subscribe_notify_one_test_service 4 $1 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_five
-export VSOMEIP_CONFIGURATION=$2
+export VSOMEIP_CONFIGURATION=$1
./subscribe_notify_one_test_service 5 $1 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_one_test_service_six
-export VSOMEIP_CONFIGURATION=$2
+export VSOMEIP_CONFIGURATION=$1
./subscribe_notify_one_test_service 6 $1 &
# Wait until all applications are finished
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_tcp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_tcp.json.in
index 785bec0..99bf69a 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_tcp.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_tcp.json.in
@@ -31,56 +31,29 @@
{
"service":"0x1111",
"instance":"0x0001",
- "unreliable":"30001",
"reliable":
{
"port":"40001",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x1111",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x2222",
"instance":"0x0001",
- "unreliable":"30002",
"reliable":
{
"port":"40002",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x2222",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x3333",
"instance":"0x0001",
- "unreliable":"30003",
"reliable":
{
"port":"40003",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x3333",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
}
],
"routing":"subscribe_notify_test_service_one",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json.in
new file mode 100644
index 0000000..cb1ff9e
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json.in
@@ -0,0 +1,61 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"subscribe_notify_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"subscribe_notify_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30002"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30003"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json.in
index fa4c5a3..4de283c 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json.in
@@ -31,32 +31,17 @@
{
"service":"0x1111",
"instance":"0x0001",
- "unreliable":"30001",
- "reliable":
- {
- "port":"40001",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30001"
},
{
"service":"0x1111",
"instance":"0x0002",
- "unreliable":"30002",
- "reliable":
- {
- "port":"40002",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30002"
},
{
"service":"0x1111",
"instance":"0x0003",
- "unreliable":"30003",
- "reliable":
- {
- "port":"40003",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30003"
}
],
"routing":"subscribe_notify_test_service_one",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json.in
index 66f1a83..5dd9299 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json.in
@@ -31,32 +31,17 @@
{
"service":"0x2222",
"instance":"0x0001",
- "unreliable":"30004",
- "reliable":
- {
- "port":"40004",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30004"
},
{
"service":"0x2222",
"instance":"0x0002",
- "unreliable":"30005",
- "reliable":
- {
- "port":"40005",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30005"
},
{
"service":"0x2222",
"instance":"0x0003",
- "unreliable":"30006",
- "reliable":
- {
- "port":"40006",
- "enable-magic-cookies":"false"
- }
+ "unreliable":"30006"
}
],
"routing":"subscribe_notify_test_service_four",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_tcp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_tcp.json.in
index d431acf..628734c 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_tcp.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_tcp.json.in
@@ -31,56 +31,29 @@
{
"service":"0x4444",
"instance":"0x0001",
- "unreliable":"30004",
"reliable":
{
"port":"40004",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x4444",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x5555",
"instance":"0x0001",
- "unreliable":"30005",
"reliable":
{
"port":"40005",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x5555",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x6666",
"instance":"0x0001",
- "unreliable":"30006",
"reliable":
{
"port":"40006",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x6666",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
}
],
"routing":"subscribe_notify_test_service_four",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json.in
new file mode 100644
index 0000000..5b96b0e
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json.in
@@ -0,0 +1,61 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"subscribe_notify_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"subscribe_notify_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30004"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30005"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30006"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_tcp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_tcp.json.in
index 376642e..3969684 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_tcp.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_tcp.json.in
@@ -31,56 +31,29 @@
{
"service":"0x1111",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x1111",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x2222",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x2222",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x3333",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x3333",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
}
],
"routing":"subscribe_notify_test_service_one",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json.in
new file mode 100644
index 0000000..72b53fc
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json.in
@@ -0,0 +1,61 @@
+{
+ "unicast":"@TEST_IP_MASTER@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"subscribe_notify_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"subscribe_notify_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_tcp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_tcp.json.in
index a0a4b2c..3f9aa0b 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_tcp.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_tcp.json.in
@@ -31,56 +31,29 @@
{
"service":"0x4444",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x4444",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x5555",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x5555",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
},
{
"service":"0x6666",
"instance":"0x0001",
- "unreliable":"30000",
"reliable":
{
"port":"40000",
"enable-magic-cookies":"false"
- },
- "events" :
- [
- {
- "event" : "0x6666",
- "is_field" : "true",
- "is_reliable" : "true"
- }
- ]
+ }
}
],
"routing":"subscribe_notify_test_service_four",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json.in
new file mode 100644
index 0000000..e485690
--- /dev/null
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json.in
@@ -0,0 +1,61 @@
+{
+ "unicast":"@TEST_IP_SLAVE@",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"subscribe_notify_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"subscribe_notify_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+} \ No newline at end of file
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
index 0b0051a..d0ce9cc 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_master.json.in
@@ -14,7 +14,7 @@
"id" : "0x9999"
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable":"true",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
index 558a873..318cf3c 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_tcp_slave.json.in
@@ -22,7 +22,7 @@
"reliable" : { "port":"30509", "enable-magic-cookies":"false" }
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable":"true",
diff --git a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
index 1828a7a..fa3e4f5 100644
--- a/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
+++ b/test/subscribe_notify_tests/conf/subscribe_notify_test_one_event_two_eventgroups_udp_slave.json.in
@@ -22,7 +22,7 @@
"unreliable" : "30509"
}
],
- "routing" : "vsomeipd",
+ "routing" : "routingmanagerd",
"service-discovery" :
{
"enable":"true",
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json
new file mode 100644
index 0000000..e09d807
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_master_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"subscribe_notify_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"subscribe_notify_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30002"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30003"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json
new file mode 100644
index 0000000..91e9ef8
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_master_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"subscribe_notify_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"subscribe_notify_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30001"
+ },
+ {
+ "service":"0x1111",
+ "instance":"0x0002",
+ "unreliable":"30002"
+ },
+ {
+ "service":"0x1111",
+ "instance":"0x0003",
+ "unreliable":"30003"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json
new file mode 100644
index 0000000..83e6963
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_same_service_id_slave_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"subscribe_notify_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"subscribe_notify_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30004"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0002",
+ "unreliable":"30005"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0003",
+ "unreliable":"30006"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json
new file mode 100644
index 0000000..f379642
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_diff_ports_slave_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"subscribe_notify_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"subscribe_notify_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30004"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30005"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30006"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json
new file mode 100644
index 0000000..a6dde19
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_master_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.1",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_one",
+ "id":"0x1111"
+ },
+ {
+ "name":"subscribe_notify_test_service_two",
+ "id":"0x2222"
+ },
+ {
+ "name":"subscribe_notify_test_service_three",
+ "id":"0x3333"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x1111",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x2222",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x3333",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_one",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json
new file mode 100644
index 0000000..7e65f41
--- /dev/null
+++ b/test/subscribe_notify_tests/subscribe_notify_test_diff_client_ids_same_ports_slave_udp.json
@@ -0,0 +1,61 @@
+{
+ "unicast":"10.0.3.2",
+ "logging":
+ {
+ "level":"warning",
+ "console":"true",
+ "file":
+ {
+ "enable":"false",
+ "path":"/tmp/vsomeip.log"
+ },
+ "dlt":"false"
+ },
+ "applications":
+ [
+ {
+ "name":"subscribe_notify_test_service_four",
+ "id":"0x4444"
+ },
+ {
+ "name":"subscribe_notify_test_service_five",
+ "id":"0x5555"
+ },
+ {
+ "name":"subscribe_notify_test_service_six",
+ "id":"0x6666"
+ }
+ ],
+ "services":
+ [
+ {
+ "service":"0x4444",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x5555",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ },
+ {
+ "service":"0x6666",
+ "instance":"0x0001",
+ "unreliable":"30000"
+ }
+ ],
+ "routing":"subscribe_notify_test_service_four",
+ "service-discovery":
+ {
+ "enable":"true",
+ "multicast":"224.0.0.1",
+ "port":"30490",
+ "protocol":"udp",
+ "initial_delay_min" : "10",
+ "initial_delay_max" : "10",
+ "repetitions_base_delay" : "30",
+ "repetitions_max" : "3",
+ "cyclic_offer_delay" : "1000",
+ "ttl" : "3"
+ }
+}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
index 1e41c8e..9e009b4 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_master_starter.sh
@@ -10,71 +10,48 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP subscribe_notify_test_diff_client_ids_diff_ports_master.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
- echo "For example: $0 UDP subscribe_notify_test_diff_client_ids_diff_ports_master.json"
+ echo "For example: $0 subscribe_notify_test_diff_client_ids_diff_ports_master.json"
echo "To use the same service id but different instances on the node pass SAME_SERVICE_ID as third parameter"
exit 1
fi
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $1 ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
- exit 1
-fi
-
# replace master with slave to be able display the correct json file to be used
# with the slave script
-MASTER_JSON_FILE=$2
+MASTER_JSON_FILE=$1
CLIENT_JSON_FILE=${MASTER_JSON_FILE/master/slave}
FAIL=0
# Start the services
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_one
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 1 $1 $3 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_test_service 1 $2 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_two
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 2 $1 $3 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_test_service 2 $2 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_three
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 3 $1 $3 &
+export VSOMEIP_CONFIGURATION=$MASTER_JSON_FILE
+./subscribe_notify_test_service 3 $2 &
sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
- echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $1 $CLIENT_JSON_FILE $3"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./subscribe_notify_test_slave_starter.sh $1 $CLIENT_JSON_FILE $3\"" &
+ echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $CLIENT_JSON_FILE $2"
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./subscribe_notify_test_slave_starter.sh $CLIENT_JSON_FILE $2\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name sntms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./subscribe_notify_test_slave_starter.sh $1 $CLIENT_JSON_FILE $3" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_test_slave_starter.sh $CLIENT_JSON_FILE $2" &
else
cat <<End-of-message
*******************************************************************************
*******************************************************************************
** Please now run:
-** subscribe_notify_test_slave_starter.sh $1 $CLIENT_JSON_FILE $3
+** subscribe_notify_test_slave_starter.sh $CLIENT_JSON_FILE $2
** from an external host to successfully complete this test.
**
** You probably will need to adapt the 'unicast' settings in
@@ -97,11 +74,6 @@ do
wait $job || ((FAIL+=1))
done
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop sntms
- docker rm sntms
-fi
-
# Check if both exited successfully
if [ $FAIL -eq 0 ]
then
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp
index 8d9f856..1971c1e 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_client.cpp
@@ -14,7 +14,7 @@
#include <utility>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include <gtest/gtest.h>
@@ -65,17 +65,20 @@ public:
// the service offers three events in two eventgroups
// one of the events is in both eventgroups (info_.event_id + 2)
its_groups.insert(info_.eventgroup_id);
- app_->request_event(info_.service_id, info_.instance_id, info_.event_id, its_groups, true);
app_->request_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ info_.event_id, its_groups,
+ vsomeip::event_type_e::ET_FIELD);
+ app_->request_event(info_.service_id, info_.instance_id,
+ static_cast<vsomeip::event_t>(info_.event_id + 2),
+ its_groups, vsomeip::event_type_e::ET_FIELD);
its_groups.erase(info_.eventgroup_id);
its_groups.insert(static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id +1));
app_->request_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id+1), its_groups, true);
+ static_cast<vsomeip::event_t>(info_.event_id+1),
+ its_groups, vsomeip::event_type_e::ET_FIELD);
app_->request_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id+2), its_groups, true);
-
-
+ static_cast<vsomeip::event_t>(info_.event_id+2),
+ its_groups, vsomeip::event_type_e::ET_FIELD);
return true;
}
@@ -154,7 +157,9 @@ public:
std::lock_guard<std::mutex> its_lock(events_mutex_);
received_events_.push_back(_response->get_payload());
if (received_events_.size() > 4) {
- ADD_FAILURE() << "Received too much events";
+ ADD_FAILURE() << "Received too many events ["
+ << std::hex << _response->get_method()
+ << " (" << std::dec << received_events_.size() << ")";
}
number_received_events_[_response->get_method()]++;
events_condition_.notify_one();
@@ -268,7 +273,6 @@ public:
check_received_events_number(its_expected);
its_expected.clear();
-
// set value again
set_field_at_service(0x2);
{
@@ -285,7 +289,6 @@ public:
check_received_events_number(its_expected);
its_expected.clear();
-
// set value again
set_field_at_service(0x3);
{
@@ -366,8 +369,8 @@ int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
if(argc < 2) {
- std::cerr << "Please specify a subscription type, like: " << argv[0] << " UDP" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
+ std::cerr << "Please specify a offer type of the service, like: " << argv[0] << " UDP" << std::endl;
+ std::cerr << "Valid offer types include:" << std::endl;
std::cerr << "[UDP, TCP]" << std::endl;
return 1;
}
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
index c983369..943ef10 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_master_starter.sh
@@ -31,7 +31,7 @@ FAIL=0
export VSOMEIP_CONFIGURATION=$2
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the client
@@ -41,10 +41,10 @@ sleep 1
if [ ! -z "$USE_LXC_TEST" ]; then
echo "starting subscribe_notify_test_slave_starter.sh on slave LXC with parameters $SLAVE_JSON_FILE"
- ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip/test; ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE\"" &
+ ssh -tt -i $SANDBOX_ROOT_DIR/commonapi_main/lxc-config/.ssh/mgc_lxc/rsa_key_file.pub -o StrictHostKeyChecking=no root@$LXC_TEST_SLAVE_IP "bash -ci \"set -m; cd \\\$SANDBOX_TARGET_DIR/vsomeip_lib/test; ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE\"" &
echo "remote ssh job id: $!"
elif [ ! -z "$USE_DOCKER" ]; then
- docker run --name sntms --cap-add NET_ADMIN $DOCKER_IMAGE sh -c "route add -net 224.0.0.0/4 dev eth0 && cd $DOCKER_TESTS && ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE" &
+ docker exec $DOCKER_IMAGE sh -c "cd $DOCKER_TESTS && ./subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh $SLAVE_JSON_FILE" &
else
cat <<End-of-message
*******************************************************************************
@@ -73,11 +73,6 @@ wait $PID_CLIENT || FAIL=$(($FAIL+1))
kill $PID_VSOMEIPD
wait $PID_VSOMEIPD || FAIL=$(($FAIL+1))
-if [ ! -z "$USE_DOCKER" ]; then
- docker stop sntms
- docker rm sntms
-fi
-
echo ""
# Check if both exited successfully
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp
index 1d7b0c3..6710892 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_service.cpp
@@ -14,7 +14,7 @@
#include <atomic>
#include <gtest/gtest.h>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include <vsomeip/vsomeip.hpp>
@@ -68,15 +68,26 @@ public:
// one of the events is in both eventgroups
its_groups.insert(info_.eventgroup_id);
app_->offer_event(info_.service_id, info_.instance_id,
- info_.event_id, its_groups, true);
+ info_.event_id, its_groups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
app_->offer_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ static_cast<vsomeip::event_t>(info_.event_id + 2),
+ its_groups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
its_groups.erase(info_.eventgroup_id);
its_groups.insert(static_cast<vsomeip::eventgroup_t>(info_.eventgroup_id + 1));
app_->offer_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id + 1), its_groups, true);
+ static_cast<vsomeip::event_t>(info_.event_id + 1),
+ its_groups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
app_->offer_event(info_.service_id, info_.instance_id,
- static_cast<vsomeip::event_t>(info_.event_id + 2), its_groups, true);
+ static_cast<vsomeip::event_t>(info_.event_id + 2),
+ its_groups, vsomeip::event_type_e::ET_FIELD,
+ std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
payload_ = vsomeip::runtime::get()->create_payload();
return true;
@@ -125,7 +136,7 @@ public:
std::shared_ptr<vsomeip::message> its_response
= vsomeip::runtime::get()->create_response(_message);
its_response->set_payload(payload_);
- app_->send(its_response, true);
+ app_->send(its_response);
{
std::lock_guard<std::mutex> its_lock(shutdown_mutex_);
wait_for_shutdown_ = false;
@@ -138,14 +149,14 @@ public:
= vsomeip::runtime::get()->create_response(_message);
payload_ = _message->get_payload();
its_response->set_payload(payload_);
- app_->send(its_response, true);
+ app_->send(its_response);
app_->notify(info_.service_id, info_.instance_id, info_.event_id, payload_);
app_->notify(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id + 1), payload_);
app_->notify(info_.service_id, info_.instance_id, static_cast<vsomeip::event_t>(info_.event_id + 2), payload_);
}
void on_message(const std::shared_ptr<vsomeip::message> &_message) {
- app_->send(vsomeip::runtime::get()->create_response(_message),true);
+ app_->send(vsomeip::runtime::get()->create_response(_message));
}
void wait_for_shutdown() {
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
index 8138612..aa2784b 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_one_event_two_eventgroups_slave_starter.sh
@@ -20,7 +20,7 @@ FAIL=0
export VSOMEIP_CONFIGURATION=$1
# start daemon
-../daemon/./vsomeipd &
+../examples/routingmanagerd/./routingmanagerd &
PID_VSOMEIPD=$!
# Start the services
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
index 968d9ed..6f13d39 100644
--- a/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
+++ b/test/subscribe_notify_tests/subscribe_notify_test_service.cpp
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <vsomeip/vsomeip.hpp>
-#include "../../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
#include "subscribe_notify_test_globals.hpp"
@@ -24,11 +24,9 @@
class subscribe_notify_test_service {
public:
subscribe_notify_test_service(struct subscribe_notify_test::service_info _service_info,
- vsomeip::subscription_type_e _subscription_type,
std::array<subscribe_notify_test::service_info, 7> _service_infos) :
service_info_(_service_info),
service_infos_(_service_infos),
- subscription_type_(_subscription_type),
app_(vsomeip::runtime::get()->create_application()),
wait_until_registered_(true),
wait_until_other_services_available_(true),
@@ -44,6 +42,7 @@ public:
ADD_FAILURE() << "Couldn't initialize application";
return;
}
+
app_->register_state_handler(
std::bind(&subscribe_notify_test_service::on_state, this,
std::placeholders::_1));
@@ -60,7 +59,9 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(service_info_.eventgroup_id);
app_->offer_event(service_info_.service_id, service_info_.instance_id,
- service_info_.event_id, its_eventgroups, true);
+ service_info_.event_id, its_eventgroups,
+ vsomeip::event_type_e::ET_FIELD, std::chrono::milliseconds::zero(),
+ false, true, nullptr, vsomeip::reliability_type_e::RT_UNKNOWN);
// register availability for all other services and request their event.
@@ -84,7 +85,7 @@ public:
std::set<vsomeip::eventgroup_t> its_eventgroups;
its_eventgroups.insert(i.eventgroup_id);
- app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, true);
+ app_->request_event(i.service_id, i.instance_id, i.event_id, its_eventgroups, vsomeip::event_type_e::ET_FIELD);
other_services_available_[std::make_pair(i.service_id, i.instance_id)] = false;
other_services_received_notification_[std::make_pair(i.service_id, i.method_id)] = 0;
@@ -95,7 +96,8 @@ public:
app_->register_subscription_handler(service_info_.service_id,
service_info_.instance_id, service_info_.eventgroup_id,
std::bind(&subscribe_notify_test_service::on_subscription, this,
- std::placeholders::_1, std::placeholders::_2));
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
app_->start();
}
@@ -110,6 +112,7 @@ public:
}
void stop_offer() {
+ app_->stop_offer_event(service_info_.service_id, service_info_.instance_id, service_info_.event_id);
app_->stop_offer_service(service_info_.service_id, service_info_.instance_id);
}
@@ -167,9 +170,12 @@ public:
<< " : on_subscription_state_change: for service " << std::hex
<< _service << " received a subscription error!";
}
- }
+ }
- bool on_subscription(vsomeip::client_t _client, bool _subscribed) {
+ bool on_subscription(vsomeip::client_t _client, std::uint32_t _uid, std::uint32_t _gid,
+ bool _subscribed) {
+ (void)_uid;
+ (void)_gid;
std::lock_guard<std::mutex> its_lock(subscribers_mutex_);
static bool notified(false);
if (_subscribed) {
@@ -188,7 +194,7 @@ public:
// -1 for placeholder in array
// divide by two because we only receive once subscription per remote node
// no matter how many clients subscribed to this eventgroup on the remote node
- if(!notified && subscribers_.size() == (service_infos_.size() - 1) / 2 )
+ if (!notified && subscribers_.size() == (service_infos_.size() - 1) / 2 )
{
// notify the notify thread to start sending out notifications
std::lock_guard<std::mutex> its_lock(notify_mutex_);
@@ -225,24 +231,11 @@ public:
<< _message->get_session() << "] from Service/Method ["
<< std::setw(4) << std::setfill('0') << std::hex
<< _message->get_service() << "/" << std::setw(4) << std::setfill('0')
- << std::hex << _message->get_method() <<"] (now have: "
+ << std::hex << _message->get_method() << "/" << std::dec << _message->get_length() << "] (now have: "
<< std::dec << other_services_received_notification_[std::make_pair(_message->get_service(),
_message->get_method())] << ")";
- bool notify(false);
- switch(subscription_type_) {
- case vsomeip::subscription_type_e::SU_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE:
- case vsomeip::subscription_type_e::SU_PREFER_RELIABLE:
- case vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE:
- if (all_notifications_received()) {
- notify = true;
- }
- break;
- }
-
- if(notify) {
+ if(all_notifications_received()) {
std::lock_guard<std::mutex> its_lock(stop_mutex_);
wait_for_stop_ = false;
stop_condition_.notify_one();
@@ -317,7 +310,7 @@ public:
}
++subscribe_count;
app_->subscribe(i.service_id, i.instance_id, i.eventgroup_id,
- vsomeip::DEFAULT_MAJOR, subscription_type_);
+ vsomeip::DEFAULT_MAJOR);
VSOMEIP_DEBUG << "[" << std::hex << service_info_.service_id
<< "] subscribing to Service/Instance/Eventgroup ["
<< std::setw(4) << std::setfill('0') << std::hex << i.service_id << "/"
@@ -344,7 +337,7 @@ public:
void notify() {
std::unique_lock<std::mutex> its_lock(notify_mutex_);
- while(wait_for_notify_) {
+ while (wait_for_notify_) {
notify_condition_.wait(its_lock);
}
@@ -419,8 +412,8 @@ public:
|| (i.service_id == 0xFFFF && i.instance_id == 0xFFFF)) {
continue;
}
- app_->register_subscription_status_handler(i.service_id, i.instance_id,
- i.eventgroup_id, vsomeip::ANY_EVENT, nullptr);
+ app_->unregister_subscription_status_handler(i.service_id, i.instance_id,
+ i.eventgroup_id, vsomeip::ANY_EVENT);
app_->unsubscribe(i.service_id, i.instance_id, i.eventgroup_id);
app_->release_event(i.service_id, i.instance_id, i.event_id);
app_->release_service(i.service_id, i.instance_id);
@@ -432,7 +425,6 @@ public:
private:
subscribe_notify_test::service_info service_info_;
std::array<subscribe_notify_test::service_info, 7> service_infos_;
- vsomeip::subscription_type_e subscription_type_;
std::shared_ptr<vsomeip::application> app_;
std::map<std::pair<vsomeip::service_t, vsomeip::instance_t>, bool> other_services_available_;
std::map<std::pair<vsomeip::service_t, vsomeip::method_t>, std::uint32_t> other_services_received_notification_;
@@ -460,8 +452,7 @@ private:
std::mutex subscribers_mutex_;
};
-static int service_number;
-static vsomeip::subscription_type_e subscription_type;
+static unsigned long service_number;
static bool use_same_service_id;
TEST(someip_subscribe_notify_test, send_ten_notifications_to_service)
@@ -469,11 +460,10 @@ TEST(someip_subscribe_notify_test, send_ten_notifications_to_service)
if(use_same_service_id) {
subscribe_notify_test_service its_sample(
subscribe_notify_test::service_infos_same_service_id[service_number],
- subscription_type,
subscribe_notify_test::service_infos_same_service_id);
} else {
subscribe_notify_test_service its_sample(
- subscribe_notify_test::service_infos[service_number], subscription_type,
+ subscribe_notify_test::service_infos[service_number],
subscribe_notify_test::service_infos);
}
}
@@ -482,35 +472,16 @@ TEST(someip_subscribe_notify_test, send_ten_notifications_to_service)
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
- if(argc < 3) {
- std::cerr << "Please specify a service number and subscription type, like: " << argv[0] << " 2 UDP SAME_SERVICE_ID" << std::endl;
+ if(argc < 2) {
+ std::cerr << "Please specify a service number, like: " << argv[0] << " 2 SAME_SERVICE_ID" << std::endl;
std::cerr << "Valid service numbers are in the range of [1,6]" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
std::cerr << "If SAME_SERVICE_ID is specified as third parameter the test is run w/ multiple instances of the same service" << std::endl;
return 1;
}
- service_number = std::stoi(std::string(argv[1]), nullptr);
-
- if(std::string("TCP_AND_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE_AND_UNRELIABLE;
- } else if(std::string("PREFER_UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_UNRELIABLE;
- } else if(std::string("PREFER_TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_PREFER_RELIABLE;
- } else if(std::string("UDP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_UNRELIABLE;
- } else if(std::string("TCP") == std::string(argv[2])) {
- subscription_type = vsomeip::subscription_type_e::SU_RELIABLE;
- } else {
- std::cerr << "Wrong subscription type passed, exiting" << std::endl;
- std::cerr << "Valid subscription types include:" << std::endl;
- std::cerr << "[TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]" << std::endl;
- return 1;
- }
+ service_number = std::stoul(std::string(argv[1]), nullptr);
- if (argc >= 4 && std::string("SAME_SERVICE_ID") == std::string(argv[3])) {
+ if (argc >= 3 && std::string("SAME_SERVICE_ID") == std::string(argv[2])) {
use_same_service_id = true;
} else {
use_same_service_id = false;
diff --git a/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh b/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
index 9865536..20362c7 100755
--- a/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
+++ b/test/subscribe_notify_tests/subscribe_notify_test_slave_starter.sh
@@ -10,51 +10,28 @@
# the testcase simply executes this script. This script then runs the services
# and checks that all exit successfully.
-if [ $# -lt 2 ]
+if [ $# -lt 1 ]
then
- echo "Please pass a subscription method to this script."
- echo "For example: $0 UDP subscribe_notify_test_diff_client_ids_diff_ports_slave.json"
- echo "Valid subscription types include:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
echo "Please pass a json file to this script."
echo "For example: $0 UDP subscribe_notify_test_diff_client_ids_diff_ports_slave.json"
echo "To use the same service id but different instances on the node pass SAME_SERVICE_ID as third parameter"
exit 1
fi
-# Make sure only valid subscription types are passed to the script
-SUBSCRIPTION_TYPES="TCP_AND_UDP PREFER_UDP PREFER_TCP UDP TCP"
-VALID=0
-for valid_subscription_type in $SUBSCRIPTION_TYPES
-do
- if [ $valid_subscription_type == $1 ]
- then
- VALID=1
- fi
-done
-
-if [ $VALID -eq 0 ]
-then
- echo "Invalid subscription type passed, valid types are:"
- echo " [TCP_AND_UDP, PREFER_UDP, PREFER_TCP, UDP, TCP]"
- echo "Exiting"
- exit 1
-fi
-
FAIL=0
# Start the services
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_four
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 4 $1 $3 &
+export VSOMEIP_CONFIGURATION=$1
+./subscribe_notify_test_service 4 $2 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_five
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 5 $1 $3 &
+export VSOMEIP_CONFIGURATION=$1
+./subscribe_notify_test_service 5 $2 &
export VSOMEIP_APPLICATION_NAME=subscribe_notify_test_service_six
-export VSOMEIP_CONFIGURATION=$2
-./subscribe_notify_test_service 6 $1 $3 &
+export VSOMEIP_CONFIGURATION=$1
+./subscribe_notify_test_service 6 $2 &
# Wait until all applications are finished
for job in $(jobs -p)
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 60ee7ea..cb35623 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -8,7 +8,7 @@ cmake_minimum_required (VERSION 2.8)
# vsomeip_ctrl
add_executable(vsomeip_ctrl EXCLUDE_FROM_ALL vsomeip_ctrl.cpp)
target_link_libraries(vsomeip_ctrl
- vsomeip
+ vsomeip3
${Boost_LIBRARIES}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
diff --git a/tools/vsomeip_ctrl.cpp b/tools/vsomeip_ctrl.cpp
index 1f64c2f..4b24deb 100644
--- a/tools/vsomeip_ctrl.cpp
+++ b/tools/vsomeip_ctrl.cpp
@@ -4,8 +4,8 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <vsomeip/vsomeip.hpp>
-#include "../implementation/configuration/include/internal.hpp"
-#include "../implementation/logging/include/logger.hpp"
+#include <vsomeip/internal/logger.hpp>
+
#include "../implementation/service_discovery/include/constants.hpp"
#include "../implementation/utility/include/byteorder.hpp"
@@ -22,7 +22,7 @@ namespace vsomeip_ctrl {
class vsomeip_sender {
public:
vsomeip_sender(bool _use_tcp,
- std::vector<vsomeip::byte_t> _user_message,
+ const std::vector<vsomeip::byte_t>& _user_message,
vsomeip::instance_t _instance) :
use_tcp_(_use_tcp),
user_message_(_user_message),
@@ -350,7 +350,7 @@ static void print_help(char* binary_name) {
"Please note: the fields client id and session id in the provided message\n"
"will be overwritten by the stack with the required values\n"
"Please further make sure to use the same configuration file\n"
- "as the target service, if the system is not using vsomeipd" << std::endl;
+ "as the target service, if the system is not using routingmanagerd" << std::endl;
}
int main(int argc, char** argv) {
@@ -397,7 +397,7 @@ int main(int argc, char** argv) {
}
if(instance_str.length() < 4) {
while(instance_str.size() != 4) {
- instance_str = "0" + instance_str;
+ instance_str = std::string("0") += instance_str;
}
}
vsomeip::byte_t high(0x0);
diff --git a/vsomeip.pc.in b/vsomeip.pc.in
index dc450b7..9049c80 100644
--- a/vsomeip.pc.in
+++ b/vsomeip.pc.in
@@ -1,11 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_PREFIX@/@INSTALL_LIB_DIR@
-includedir=@CMAKE_INSTALL_PREFIX@/include
+includedir=@CMAKE_INSTALL_PREFIX@/include/compat
Name: @PROJECT@
Description: New SOME/IP stack, feature complete
Version: @VSOMEIP_VERSION@
-Libs: -L${libdir} -lvsomeip -lvsomeip-sd -lboost_system -lboost_log -lboost_filesystem
+Libs: -L${libdir} -lvsomeip
Cflags: -I${includedir}
diff --git a/vsomeip3.pc.in b/vsomeip3.pc.in
new file mode 100644
index 0000000..27888e7
--- /dev/null
+++ b/vsomeip3.pc.in
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_PREFIX@/@INSTALL_LIB_DIR@
+includedir=@CMAKE_INSTALL_PREFIX@/include
+
+Name: @PROJECT@
+Description: New SOME/IP stack, feature complete
+Version: @VSOMEIP_VERSION@
+Libs: -L${libdir} -lvsomeip3
+Cflags: -I${includedir}
+
diff --git a/vsomeip3Config.cmake.in b/vsomeip3Config.cmake.in
new file mode 100644
index 0000000..d689970
--- /dev/null
+++ b/vsomeip3Config.cmake.in
@@ -0,0 +1,19 @@
+# Config file for the vSomeIP package, defines the following variables:
+# Exports the following targets:
+# vsomeip3 - CMake target for vSomeIP
+# Additionally, the following variables are defined:
+# VSOMEIP_LIBRARIES - list of libraries to link against, contains only
+# "vsomeip3"
+
+# Compute paths
+get_filename_component (VSOMEIP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+# Legacy variable, no longer used but kept for compatibility
+get_filename_component(VSOMEIP_INCLUDE_DIRS "" PATH)
+
+# Our library dependencies (contains definitions for IMPORTED targets)
+if (NOT TARGET vsomeip AND NOT vsomeip_BINARY_DIR)
+ include ("${VSOMEIP_CMAKE_DIR}/vsomeip3Targets.cmake")
+endif ()
+
+# These are IMPORTED targets created by vsomeipTargets.cmake
+set (VSOMEIP_LIBRARIES vsomeip3)
diff --git a/vsomeip3ConfigVersion.cmake.in b/vsomeip3ConfigVersion.cmake.in
new file mode 100644
index 0000000..1c39479
--- /dev/null
+++ b/vsomeip3ConfigVersion.cmake.in
@@ -0,0 +1,11 @@
+set (PACKAGE_VERSION "@VSOMEIP_VERSION@")
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_COMPATIBLE FALSE)
+else ()
+ set (PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_EXACT TRUE)
+ endif ()
+endif ()
diff --git a/vsomeipConfig.cmake.in b/vsomeipConfig.cmake.in
index 71e3ebb..38ea7ae 100644
--- a/vsomeipConfig.cmake.in
+++ b/vsomeipConfig.cmake.in
@@ -1,15 +1,19 @@
-# Config file for the vSomeIP package, defines the following variables:
-# VSOMEIP_INCLUDE_DIRS - include directories for vSomeIP
-# VSOMEIP_LIBRARIES - libraries to link against
-
-# Compute paths
-get_filename_component (VSOMEIP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-get_filename_component(VSOMEIP_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@" REALPATH)
-
-# Our library dependencies (contains definitions for IMPORTED targets)
-if (NOT TARGET vsomeip AND NOT vsomeip_BINARY_DIR)
- include ("${VSOMEIP_CMAKE_DIR}/vsomeipTargets.cmake")
-endif ()
-
-# These are IMPORTED targets created by vsomeipTargets.cmake
-set (VSOMEIP_LIBRARIES vsomeip)
+# Config file for the vSomeIP package, defines the following variables:
+# Exports the following targets:
+# vsomeip - CMake target for vSomeIP
+# Additionally, the following variables are defined:
+# VSOMEIP_LIBRARIES - list of libraries to link against, contains only
+# "vsomeip"
+
+# Compute paths
+get_filename_component (VSOMEIP_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+# Legacy variable, no longer used but kept for compatibility
+get_filename_component(VSOMEIP_INCLUDE_DIRS "" PATH)
+
+# Our library dependencies (contains definitions for IMPORTED targets)
+if (NOT TARGET vsomeip AND NOT vsomeip_BINARY_DIR)
+ include ("${VSOMEIP_CMAKE_DIR}/vsomeipTargets.cmake")
+endif ()
+
+# These are IMPORTED targets created by vsomeipTargets.cmake
+set (VSOMEIP_LIBRARIES vsomeip)
diff --git a/vsomeipConfigVersion.cmake.in b/vsomeipConfigVersion.cmake.in
index 69988bd..19eb60f 100644
--- a/vsomeipConfigVersion.cmake.in
+++ b/vsomeipConfigVersion.cmake.in
@@ -1,11 +1,11 @@
-set (PACKAGE_VERSION "@VSOMEIP_VERSION@")
-
-# Check whether the requested PACKAGE_FIND_VERSION is compatible
-if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
- set (PACKAGE_VERSION_COMPATIBLE FALSE)
-else ()
- set (PACKAGE_VERSION_COMPATIBLE TRUE)
- if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
- set (PACKAGE_VERSION_EXACT TRUE)
- endif ()
-endif ()
+set (PACKAGE_VERSION "@VSOMEIP_COMPAT_VERSION@")
+
+# Check whether the requested PACKAGE_FIND_VERSION is compatible
+if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_COMPATIBLE FALSE)
+else ()
+ set (PACKAGE_VERSION_COMPATIBLE TRUE)
+ if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
+ set (PACKAGE_VERSION_EXACT TRUE)
+ endif ()
+endif ()