1 // Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
2 // This Source Code Form is subject to the terms of the Mozilla Public
3 // License, v. 2.0. If a copy of the MPL was not distributed with this
4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
6 #include <csignal>
7 #endif
8 #include <chrono>
9 #include <condition_variable>
10 #include <iomanip>
11 #include <iostream>
12 #include <sstream>
13 #include <thread>
14 
15 #include <vsomeip/vsomeip.hpp>
16 
17 #include "sample-ids.hpp"
18 
19 class client_sample {
20 public:
client_sample(bool _use_tcp,bool _be_quiet,uint32_t _cycle)21     client_sample(bool _use_tcp, bool _be_quiet, uint32_t _cycle)
22         : app_(vsomeip::runtime::get()->create_application()),
23           request_(vsomeip::runtime::get()->create_request(_use_tcp)),
24           use_tcp_(_use_tcp),
25           be_quiet_(_be_quiet),
26           cycle_(_cycle),
27           running_(true),
28           blocked_(false),
29           is_available_(false),
30           sender_(std::bind(&client_sample::run, this)) {
31     }
32 
init()33     bool init() {
34         if (!app_->init()) {
35             std::cerr << "Couldn't initialize application" << std::endl;
36             return false;
37         }
38 
39         std::cout << "Client settings [protocol="
40                   << (use_tcp_ ? "TCP" : "UDP")
41                   << ":quiet="
42                   << (be_quiet_ ? "true" : "false")
43                   << ":cycle="
44                   << cycle_
45                   << "]"
46                   << std::endl;
47 
48         app_->register_state_handler(
49                 std::bind(
50                     &client_sample::on_state,
51                     this,
52                     std::placeholders::_1));
53 
54         app_->register_message_handler(
55                 vsomeip::ANY_SERVICE, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD,
56                 std::bind(&client_sample::on_message,
57                           this,
58                           std::placeholders::_1));
59 
60         request_->set_service(SAMPLE_SERVICE_ID);
61         request_->set_instance(SAMPLE_INSTANCE_ID);
62         request_->set_method(SAMPLE_METHOD_ID);
63 
64         std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
65         std::vector< vsomeip::byte_t > its_payload_data;
66         for (std::size_t i = 0; i < 10; ++i)
67             its_payload_data.push_back(static_cast<vsomeip::byte_t>(i % 256));
68         its_payload->set_data(its_payload_data);
69         request_->set_payload(its_payload);
70 
71         app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID,
72                 std::bind(&client_sample::on_availability,
73                           this,
74                           std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
75 
76         app_->register_availability_handler(SAMPLE_SERVICE_ID + 1, SAMPLE_INSTANCE_ID,
77                 std::bind(&client_sample::on_availability,
78                           this,
79                           std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
80         return true;
81     }
82 
start()83     void start() {
84         app_->start();
85     }
86 
87 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
88     /*
89      * Handle signal to shutdown
90      */
stop()91     void stop() {
92         running_ = false;
93         blocked_ = true;
94         app_->clear_all_handler();
95         app_->release_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
96         condition_.notify_one();
97         sender_.join();
98         app_->stop();
99     }
100 #endif
101 
on_state(vsomeip::state_type_e _state)102     void on_state(vsomeip::state_type_e _state) {
103         if (_state == vsomeip::state_type_e::ST_REGISTERED) {
104             app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
105         }
106     }
107 
on_availability(vsomeip::service_t _service,vsomeip::instance_t _instance,bool _is_available)108     void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
109         std::cout << "Service ["
110                 << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
111                 << "] is "
112                 << (_is_available ? "available." : "NOT available.")
113                 << std::endl;
114 
115         if (SAMPLE_SERVICE_ID == _service && SAMPLE_INSTANCE_ID == _instance) {
116             if (is_available_  && !_is_available) {
117                 is_available_ = false;
118             } else if (_is_available && !is_available_) {
119                 is_available_ = true;
120                 send();
121             }
122         }
123     }
124 
on_message(const std::shared_ptr<vsomeip::message> & _response)125     void on_message(const std::shared_ptr< vsomeip::message > &_response) {
126         std::cout << "Received a response from Service ["
127                 << std::setw(4) << std::setfill('0') << std::hex << _response->get_service()
128                 << "."
129                 << std::setw(4) << std::setfill('0') << std::hex << _response->get_instance()
130                 << "] to Client/Session ["
131                 << std::setw(4) << std::setfill('0') << std::hex << _response->get_client()
132                 << "/"
133                 << std::setw(4) << std::setfill('0') << std::hex << _response->get_session()
134                 << "]"
135                 << std::endl;
136         if (is_available_)
137             send();
138     }
139 
send()140     void send() {
141         if (!be_quiet_)
142         {
143             std::lock_guard< std::mutex > its_lock(mutex_);
144             blocked_ = true;
145             condition_.notify_one();
146         }
147     }
148 
run()149     void run() {
150         while (running_) {
151             {
152                 std::unique_lock<std::mutex> its_lock(mutex_);
153                 while (!blocked_) condition_.wait(its_lock);
154                 if (is_available_) {
155                     app_->send(request_);
156                     std::cout << "Client/Session ["
157                             << std::setw(4) << std::setfill('0') << std::hex << request_->get_client()
158                             << "/"
159                             << std::setw(4) << std::setfill('0') << std::hex << request_->get_session()
160                             << "] sent a request to Service ["
161                             << std::setw(4) << std::setfill('0') << std::hex << request_->get_service()
162                             << "."
163                             << std::setw(4) << std::setfill('0') << std::hex << request_->get_instance()
164                             << "]"
165                             << std::endl;
166                     blocked_ = false;
167                 }
168             }
169             std::this_thread::sleep_for(std::chrono::milliseconds(cycle_));
170         }
171     }
172 
173 private:
174     std::shared_ptr< vsomeip::application > app_;
175     std::shared_ptr< vsomeip::message > request_;
176     bool use_tcp_;
177     bool be_quiet_;
178     uint32_t cycle_;
179     std::mutex mutex_;
180     std::condition_variable condition_;
181     bool running_;
182     bool blocked_;
183     bool is_available_;
184 
185     std::thread sender_;
186 };
187 
188 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
189     client_sample *its_sample_ptr(nullptr);
handle_signal(int _signal)190     void handle_signal(int _signal) {
191         if (its_sample_ptr != nullptr &&
192                 (_signal == SIGINT || _signal == SIGTERM))
193             its_sample_ptr->stop();
194     }
195 #endif
196 
main(int argc,char ** argv)197 int main(int argc, char **argv) {
198     bool use_tcp = false;
199     bool be_quiet = false;
200     uint32_t cycle = 1000; // Default: 1s
201 
202     std::string tcp_enable("--tcp");
203     std::string udp_enable("--udp");
204     std::string quiet_enable("--quiet");
205     std::string cycle_arg("--cycle");
206 
207     int i = 1;
208     while (i < argc) {
209         if (tcp_enable == argv[i]) {
210             use_tcp = true;
211         } else if (udp_enable == argv[i]) {
212             use_tcp = false;
213         } else if (quiet_enable == argv[i]) {
214             be_quiet = true;
215         } else if (cycle_arg == argv[i] && i+1 < argc) {
216             i++;
217             std::stringstream converter;
218             converter << argv[i];
219             converter >> cycle;
220         }
221         i++;
222     }
223 
224     client_sample its_sample(use_tcp, be_quiet, cycle);
225 #ifndef VSOMEIP_ENABLE_SIGNAL_HANDLING
226     its_sample_ptr = &its_sample;
227     signal(SIGINT, handle_signal);
228     signal(SIGTERM, handle_signal);
229 #endif
230     if (its_sample.init()) {
231         its_sample.start();
232         return 0;
233     } else {
234         return 1;
235     }
236 }
237