2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.1 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "controller_connection_manager.h"
18 #include "messages/message_manager.h"
19 #include "messages/message_command.h"
20 #include "messages/message_ack.h"
21 #include "messages/message_factory.h"
22 #include "messages/message_config_user_name.h"
28 #define KEEP_ALIVE_CHECK_ATTEMPTS 5
29 #define HELLO_ACCEPT_ATTEMPTS 5
30 #define HELLO_ACCEPT_INTERVAL 1000 //In ms
31 #define KEEP_ALIVE_CHECK_INTERVAL 1000 //In ms
33 #define SAFE_SOURCE_REMOVE(source)\
36 g_source_remove(source); \
41 typedef struct _controller_connection_manager_info {
42 controller_connection_state_e state;
43 char *controller_address;
45 connection_state_cb state_cb;
46 command_received_cb command_cb;
47 user_name_received_cb user_name_cb;
48 int keep_alive_check_attempts_left;
49 int connect_accept_attempts_left;
50 guint connect_accept_timer;
51 guint keep_alive_check_timer;
52 unsigned long long int last_serial;
53 message_factory_t *message_factory;
54 } _controller_connection_manager_s;
56 static _controller_connection_manager_s s_info = {
57 .state = CONTROLLER_CONNECTION_STATE_READY,
58 .controller_address = NULL,
60 .keep_alive_check_attempts_left = KEEP_ALIVE_CHECK_ATTEMPTS,
61 .connect_accept_attempts_left = HELLO_ACCEPT_ATTEMPTS,
62 .connect_accept_timer = 0,
63 .keep_alive_check_timer = 0
66 static int _try_connect(const char *ip, int port);
67 static void _disconnect();
68 static void _set_state(controller_connection_state_e state);
69 static void _receive_cb(message_t *message, void *data);
70 static void _reset_counters();
71 static gboolean _send_connect_accept();
72 static gboolean _connect_accept_timer_cb(gpointer data);
73 static gboolean _keep_alive_check_timer_cb(gpointer data);
74 static int _addr_cmp(const char *addr1, int port1, const char *addr2, int port2);
76 int controller_connection_manager_listen()
78 s_info.message_factory = message_factory_create();
79 if(!s_info.message_factory) {
82 message_manager_set_receive_message_cb(_receive_cb, NULL);
86 controller_connection_state_e controller_connection_manager_get_state()
91 void controller_connection_manager_set_state_change_cb(connection_state_cb callback)
93 s_info.state_cb = callback;
96 void controller_connection_manager_set_command_received_cb(command_received_cb callback)
98 s_info.command_cb = callback;
101 void controller_connection_manager_set_user_name_received_cb(user_name_received_cb callback)
103 s_info.user_name_cb = callback;
106 void controller_connection_manager_handle_message(message_t *message)
108 if(!s_info.message_factory) {
109 _E("Message factory not initialized");
112 const char *msg_address;
114 message_get_sender(message, &msg_address, &msg_port);
115 int address_match = !_addr_cmp(s_info.controller_address, s_info.controller_port, msg_address, msg_port);
117 switch(message_get_type(message)) {
118 case MESSAGE_CONNECT:
119 if(s_info.state == CONTROLLER_CONNECTION_STATE_READY) {
120 if(_try_connect(msg_address, msg_port)) {
121 _E("Received CONNECT, but cannot establish connection");
123 s_info.last_serial = message_get_serial(message);
124 _I("Established connection with %s:%d", s_info.controller_address, s_info.controller_port);
127 message_t *response = message_factory_create_message(s_info.message_factory, MESSAGE_CONNECT_REFUSED);
129 _W("Failed to create CONNECT_REFUSED message");
132 message_set_receiver(response, msg_address, msg_port);
133 message_manager_send_message(response);
134 message_destroy(response);
137 case MESSAGE_KEEP_ALIVE:
138 if(s_info.state == CONTROLLER_CONNECTION_STATE_RESERVED && address_match) {
139 unsigned long long int serial = message_get_serial(message);
140 if(serial > s_info.last_serial) {
141 SAFE_SOURCE_REMOVE(s_info.connect_accept_timer);
142 s_info.keep_alive_check_attempts_left = KEEP_ALIVE_CHECK_ATTEMPTS;
143 message_ack_t response;
144 message_ack_init_from_request(&response, message);
145 message_set_receiver((message_t*)&response, s_info.controller_address, s_info.controller_port);
146 message_manager_send_message((message_t*)&response);
147 message_destroy((message_t*)&response);
148 s_info.last_serial = serial;
150 _W("Received late KEEP_ALIVE (%d, when last is %d)", serial, s_info.last_serial);
153 _W("Unexpectedly received KEEP_ALIVE from %s:%d (address_match == %d)", msg_address, msg_port, address_match);
156 case MESSAGE_COMMAND:
157 if(s_info.state == CONTROLLER_CONNECTION_STATE_RESERVED && address_match) {
158 const command_s *command = message_command_get_command((message_command_t *) message);
160 _E("Failed to obtain command");
163 if(s_info.command_cb) {
164 s_info.command_cb(*command);
167 _W("Unexpectedly received COMMAND from %s:%d (address_match == %d)", msg_address, msg_port, address_match);
171 if(s_info.state == CONTROLLER_CONNECTION_STATE_RESERVED && address_match) {
174 _W("Unexpectedly received BYE from %s:%d (address_match == %d)", msg_address, msg_port, address_match);
177 case MESSAGE_CONFIG_USER_NAME:
178 if(s_info.state == CONTROLLER_CONNECTION_STATE_RESERVED && address_match) {
179 if(s_info.user_name_cb) {
180 s_info.user_name_cb(message_config_user_name_get_name((message_config_user_name_t*)message));
182 message_ack_t response;
183 message_ack_init_from_request(&response, message);
184 message_set_receiver((message_t*)&response, s_info.controller_address, s_info.controller_port);
185 message_manager_send_message((message_t*)&response);
186 message_destroy((message_t*)&response);
188 _W("Unexpectedly received BYE from %s:%d (address_match == %d)", msg_address, msg_port, address_match);
192 _W("Received incorrect message");
196 void controller_connection_manager_release()
198 if(s_info.state == CONTROLLER_CONNECTION_STATE_RESERVED) {
201 message_factory_destroy(s_info.message_factory);
202 message_manager_shutdown();
203 s_info.message_factory = NULL;
206 static void _set_state(controller_connection_state_e state)
208 if(state == s_info.state) {
212 controller_connection_state_e previous = s_info.state;
213 s_info.state = state;
214 _I("Connection state changed from %d to %d", previous, state);
215 if(s_info.state_cb) {
216 s_info.state_cb(previous, state);
220 static void _receive_cb(message_t *message, void *data)
222 controller_connection_manager_handle_message(message);
225 static int _try_connect(const char *ip, int port)
227 if(s_info.state != CONTROLLER_CONNECTION_STATE_READY) {
228 _E("Attempt to connect failed - already reserved by %s:%d", s_info.controller_address, s_info.controller_port);
232 s_info.controller_address = strdup(ip);
233 if(!s_info.controller_address) {
234 _E("Failed to save controller address");
238 s_info.controller_port = port;
239 _set_state(CONTROLLER_CONNECTION_STATE_RESERVED);
240 if(!_send_connect_accept()) {
241 _E("Failed to send CONNECT_ACCEPT");
244 s_info.connect_accept_timer = g_timeout_add(HELLO_ACCEPT_INTERVAL, _connect_accept_timer_cb, NULL);
245 s_info.keep_alive_check_timer = g_timeout_add(KEEP_ALIVE_CHECK_INTERVAL, _keep_alive_check_timer_cb, NULL);
249 static void _disconnect()
251 if(s_info.state == CONTROLLER_CONNECTION_STATE_READY) {
252 _W("No connection already initiated");
256 SAFE_SOURCE_REMOVE(s_info.connect_accept_timer);
258 SAFE_SOURCE_REMOVE(s_info.keep_alive_check_timer);
260 free(s_info.controller_address);
261 s_info.controller_port = 0;
262 _set_state(CONTROLLER_CONNECTION_STATE_READY);
265 static gboolean _send_connect_accept()
267 if(s_info.state != CONTROLLER_CONNECTION_STATE_RESERVED) {
268 _E("Car is not reserved");
271 if(!--s_info.connect_accept_attempts_left) {
272 _W("Connect accepted, but no KEEP ALIVE received - disconnecting started");
276 message_t *message = message_factory_create_message(s_info.message_factory, MESSAGE_CONNECT_ACCEPTED);
277 message_set_receiver(message, s_info.controller_address, s_info. controller_port);
278 message_manager_send_message(message);
279 message_destroy(message);
283 static gboolean _connect_accept_timer_cb(gpointer data)
285 return _send_connect_accept();
288 static gboolean _keep_alive_check_timer_cb(gpointer data)
290 if(s_info.state != CONTROLLER_CONNECTION_STATE_RESERVED) {
291 _E("Incorrect state of connection");
294 if(!s_info.keep_alive_check_attempts_left--) {
295 _W("KEEP ALIVE timeout reached - disconnecting started");
302 static void _reset_counters()
304 s_info.keep_alive_check_attempts_left = KEEP_ALIVE_CHECK_ATTEMPTS;
305 s_info.connect_accept_attempts_left = HELLO_ACCEPT_ATTEMPTS;
308 static int _addr_cmp(const char *addr1, int port1, const char *addr2, int port2)
310 if(addr1 == NULL || addr2 == NULL) {
314 unsigned int address_length = strlen(addr2);
315 return port1 != port2 || strlen(addr1) != address_length || strncmp(addr1, addr2, address_length);