xref: /btstack/platform/daemon/src/socket_connection.c (revision ab2c6ae4b737d5e801d3defe4117331eb244ebb7)
1 /*
2  * Copyright (C) 2014 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "socket_connection.c"
39 
40 /*
41  *  SocketServer.c
42  *
43  *  Handles multiple connections to a single socket without blocking
44  *
45  *  Created by Matthias Ringwald on 6/6/09.
46  *
47  */
48 
49 #include "socket_connection.h"
50 
51 #include "hci.h"
52 #include "btstack_debug.h"
53 
54 #include "btstack_config.h"
55 
56 #include "btstack.h"
57 #include "btstack_client.h"
58 
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <signal.h>
62 #include <stdint.h>
63 #include <stdio.h>
64 #include <string.h>
65 #include <unistd.h>
66 
67 #include <sys/stat.h>
68 
69 #ifndef _WIN32
70 #include <arpa/inet.h>
71 #include <netdb.h>
72 #include <sys/socket.h>
73 #include <sys/un.h>
74 #endif
75 
76 #ifdef _WIN32
77 #include "Winsock2.h"
78 // define missing types
79 typedef int32_t socklen_t;
80 //
81 #define UNIX_PATH_MAX 108
82 struct sockaddr_un {
83     uint16_t sun_family;
84     char sun_path[UNIX_PATH_MAX];
85 };
86 //
87 #define S_IRWXG 0
88 #define S_IRWXO 0
89 #endif
90 
91 #ifdef USE_LAUNCHD
92 #include "../port/ios/3rdparty/launch.h"
93 #endif
94 
95 #define MAX_PENDING_CONNECTIONS 10
96 
97 /** prototypes */
98 static void socket_connection_hci_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
99 static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length);
100 
101 /** globals */
102 
103 /** packet header used over socket connections, in front of the HCI packet */
104 typedef struct packet_header {
105     uint16_t type;
106     uint16_t channel;
107     uint16_t length;
108     uint8_t  data[0];
109 } packet_header_t;  // 6
110 
111 typedef enum {
112     SOCKET_W4_HEADER,
113     SOCKET_W4_DATA
114 } SOCKET_STATE;
115 
116 typedef struct linked_connection {
117     btstack_linked_item_t item;
118     connection_t * connection;
119 } linked_connection_t;
120 
121 struct connection {
122     btstack_data_source_t ds;                // used for run loop
123     linked_connection_t linked_connection;   // used for connection list
124     SOCKET_STATE state;
125     uint16_t bytes_read;
126     uint16_t bytes_to_read;
127     uint8_t  buffer[6+HCI_ACL_BUFFER_SIZE]; // packet_header(6) + max packet: 3-DH5 = header(6) + payload (1021)
128 };
129 
130 /** list of socket connections */
131 static btstack_linked_list_t connections = NULL;
132 static btstack_linked_list_t parked = NULL;
133 
134 
135 /** client packet handler */
136 
137 static int (*socket_connection_packet_callback)(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length) = socket_connection_dummy_handler;
138 
139 static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){
140     return 0;
141 }
142 
143 void socket_connection_free_connection(connection_t *conn){
144     // remove from run_loop
145     btstack_run_loop_remove_data_source(&conn->ds);
146 
147     // and from connection list
148     btstack_linked_list_remove(&connections, &conn->linked_connection.item);
149 
150     // destroy
151     free(conn);
152 }
153 
154 void socket_connection_init_statemachine(connection_t *connection){
155     // wait for next packet
156     connection->state = SOCKET_W4_HEADER;
157     connection->bytes_read = 0;
158     connection->bytes_to_read = sizeof(packet_header_t);
159 }
160 
161 connection_t * socket_connection_register_new_connection(int fd){
162     // create connection objec
163     connection_t * conn = malloc( sizeof(connection_t));
164     if (conn == NULL) return 0;
165 
166     // store reference from linked item to base object
167     conn->linked_connection.connection = conn;
168 
169     btstack_run_loop_set_data_source_handler(&conn->ds, &socket_connection_hci_process);
170     btstack_run_loop_set_data_source_fd(&conn->ds, fd);
171     btstack_run_loop_enable_data_source_callbacks(&conn->ds, DATA_SOURCE_CALLBACK_READ);
172 
173     // prepare state machine and
174     socket_connection_init_statemachine(conn);
175 
176     // add this socket to the run_loop
177     btstack_run_loop_add_data_source( &conn->ds );
178 
179     // and the connection list
180     btstack_linked_list_add( &connections, &conn->linked_connection.item);
181 
182     return conn;
183 }
184 
185 void static socket_connection_emit_connection_opened(connection_t *connection){
186     uint8_t event[1];
187     event[0] = DAEMON_EVENT_CONNECTION_OPENED;
188     (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
189 }
190 
191 void static socket_connection_emit_connection_closed(connection_t *connection){
192     uint8_t event[1];
193     event[0] = DAEMON_EVENT_CONNECTION_CLOSED;
194     (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
195 }
196 
197 void socket_connection_hci_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
198     connection_t *conn = (connection_t *) ds;
199     int fd = btstack_run_loop_get_data_source_fd(ds);
200     int bytes_read = read(fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
201     if (bytes_read <= 0){
202         // connection broken (no particular channel, no date yet)
203         socket_connection_emit_connection_closed(conn);
204 
205         // free connection
206         socket_connection_free_connection(conn);
207 
208         return;
209     }
210     conn->bytes_read += bytes_read;
211     conn->bytes_to_read -= bytes_read;
212     if (conn->bytes_to_read > 0) return;
213 
214     int dispatch = 0;
215     switch (conn->state){
216         case SOCKET_W4_HEADER:
217             conn->state = SOCKET_W4_DATA;
218             conn->bytes_to_read = little_endian_read_16( conn->buffer, 4);
219             if (conn->bytes_to_read == 0){
220                 dispatch = 1;
221             }
222             break;
223         case SOCKET_W4_DATA:
224             dispatch = 1;
225             break;
226         default:
227             break;
228     }
229 
230     if (dispatch){
231         // dispatch packet !!! connection, type, channel, data, size
232         int dispatch_err = (*socket_connection_packet_callback)(conn, little_endian_read_16( conn->buffer, 0), little_endian_read_16( conn->buffer, 2),
233                                                             &conn->buffer[sizeof(packet_header_t)], little_endian_read_16( conn->buffer, 4));
234 
235         // reset state machine
236         socket_connection_init_statemachine(conn);
237 
238         // "park" if dispatch failed
239         if (dispatch_err) {
240             log_info("socket_connection_hci_process dispatch failed -> park connection");
241             btstack_run_loop_remove_data_source(ds);
242             btstack_linked_list_add_tail(&parked, (btstack_linked_item_t *) ds);
243         }
244     }
245 }
246 
247 /**
248  * try to dispatch packet for all "parked" connections.
249  * if dispatch is successful, a connection is added again to run loop
250  * pre: connections get parked iff packet was dispatched but could not be sent
251  */
252 void socket_connection_retry_parked(void){
253     // log_info("socket_connection_hci_process retry parked");
254     btstack_linked_item_t *it = (btstack_linked_item_t *) &parked;
255     while (it->next) {
256         connection_t * conn = (connection_t *) it->next;
257 
258         // dispatch packet !!! connection, type, channel, data, size
259         uint16_t packet_type = little_endian_read_16( conn->buffer, 0);
260         uint16_t channel     = little_endian_read_16( conn->buffer, 2);
261         uint16_t length      = little_endian_read_16( conn->buffer, 4);
262         log_info("socket_connection_hci_process retry parked %p (type %u, channel %04x, length %u", conn, packet_type, channel, length);
263         int dispatch_err = (*socket_connection_packet_callback)(conn, packet_type, channel, &conn->buffer[sizeof(packet_header_t)], length);
264         // "un-park" if successful
265         if (!dispatch_err) {
266             log_info("socket_connection_hci_process dispatch succeeded -> un-park connection %p", conn);
267             it->next = it->next->next;
268             btstack_run_loop_add_data_source( (btstack_data_source_t *) conn);
269         } else {
270             it = it->next;
271         }
272     }
273 }
274 
275 int  socket_connection_has_parked_connections(void){
276     return parked != NULL;
277 }
278 
279 static void socket_connection_accept(btstack_data_source_t *socket_ds, btstack_data_source_callback_type_t callback_type) {
280     struct sockaddr_storage ss;
281     socklen_t slen = sizeof(ss);
282     int socket_fd = btstack_run_loop_get_data_source_fd(socket_ds);
283 
284 	/* New connection coming in! */
285 	int fd = accept(socket_fd, (struct sockaddr *)&ss, &slen);
286 	if (fd < 0) {
287 		perror("accept");
288         return;
289 	}
290 
291     log_info("socket_connection_accept new connection %u", fd);
292 
293     connection_t * connection = socket_connection_register_new_connection(fd);
294     socket_connection_emit_connection_opened(connection);
295 }
296 
297 /**
298  * create socket data_source for tcp socket
299  *
300  * @return data_source object. If null, check errno
301  */
302 int socket_connection_create_tcp(int port){
303 
304     // create btstack_data_source_t
305     btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
306     if (ds == NULL) return -1;
307 
308 	// create tcp socket
309     int fd = socket (PF_INET, SOCK_STREAM, 0);
310 	if (fd < 0) {
311 		log_error("Error creating socket ...(%s)", strerror(errno));
312 		free(ds);
313         return -1;
314 	}
315 
316 	log_info ("Socket created for port %u", port);
317 
318     struct sockaddr_in addr;
319 	addr.sin_family = AF_INET;
320 	addr.sin_port = htons (port);
321 	memset (&addr.sin_addr, 0, sizeof (addr.sin_addr));
322 
323 	const int y = 1;
324 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
325 
326 	if (bind ( fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
327 		log_error("Error on bind() ...(%s)", strerror(errno));
328 		free(ds);
329         return -1;
330 	}
331 
332 	if (listen (fd, MAX_PENDING_CONNECTIONS)) {
333 		log_error("Error on listen() ...(%s)", strerror(errno));
334 		free(ds);
335         return -1;
336 	}
337 
338     btstack_run_loop_set_data_source_fd(ds, fd);
339     btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
340     btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
341     btstack_run_loop_add_data_source(ds);
342 
343 	log_info ("Server up and running ...");
344     return 0;
345 }
346 
347 #ifdef USE_LAUNCHD
348 
349 /*
350  * Register listening sockets with our run loop
351  */
352 void socket_connection_launchd_register_fd_array(launch_data_t listening_fd_array){
353 	int i;
354     for (i = 0; i < launch_data_array_get_count(listening_fd_array); i++) {
355         // get fd
356         launch_data_t tempi = launch_data_array_get_index (listening_fd_array, i);
357         int listening_fd = launch_data_get_fd(tempi);
358         launch_data_free (tempi);
359 		log_info("file descriptor = %u", listening_fd);
360 
361         // create btstack_data_source_t for fd
362         btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
363         if (ds == NULL) return;
364         btstack_run_loop_set_data_source_fd(ds, listening_fd);
365         btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
366         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
367         btstack_run_loop_add_data_source(ds);
368 	}
369 }
370 
371 /**
372  * create socket data_source for socket specified by launchd configuration
373  */
374 int socket_connection_create_launchd(void){
375 
376     launch_data_t sockets_dict, checkin_response;
377 	launch_data_t checkin_request;
378     launch_data_t listening_fd_array;
379 
380 	/*
381 	 * Register ourselves with launchd.
382 	 *
383 	 */
384 	if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
385 		log_error( "launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.");
386 		return -1;
387 	}
388 
389 	if ((checkin_response = launch_msg(checkin_request)) == NULL) {
390 		log_error( "launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %u", errno);
391 		return -1;
392 	}
393 
394 	if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
395 		errno = launch_data_get_errno(checkin_response);
396 		log_error( "Check-in failed: %u", errno);
397 		return -1;
398 	}
399 
400     launch_data_t the_label = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_LABEL);
401 	if (NULL == the_label) {
402 		log_error( "No label found");
403 		return -1;
404 	}
405 
406 	/*
407 	 * Retrieve the dictionary of Socket entries in the config file
408 	 */
409 	sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
410 	if (NULL == sockets_dict) {
411 		log_error("No sockets found to answer requests on!");
412 		return -1;
413 	}
414 
415 	// if (launch_data_dict_get_count(sockets_dict) > 1) {
416 	// 	log_error("Some sockets will be ignored!");
417 	// }
418 
419 	/*
420 	 * Get the dictionary value from the key "Listeners"
421 	 */
422 	listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners");
423 	if (listening_fd_array) {
424         // log_error("Listeners...");
425         socket_connection_launchd_register_fd_array( listening_fd_array );
426     }
427 
428 	/*
429 	 * Get the dictionary value from the key "Listeners"
430 	 */
431 	listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners2");
432 	if (listening_fd_array) {
433         // log_error("Listeners2...");
434         socket_connection_launchd_register_fd_array( listening_fd_array );
435     }
436 
437     // although used in Apple examples, it creates a malloc warning
438 	// launch_data_free(checkin_response);
439     return 0;
440 }
441 #endif
442 
443 /**
444  * create socket data_source for unix domain socket
445  */
446 int socket_connection_create_unix(char *path){
447 
448     // create btstack_data_source_t
449     btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
450     if (ds == NULL) return -1;
451 
452 	// create unix socket
453     int fd = socket (AF_UNIX, SOCK_STREAM, 0);
454 	if (fd < 0) {
455 		log_error( "Error creating socket ...(%s)", strerror(errno));
456 		free(ds);
457         return -1;
458 	}
459 	log_info ("Socket created at %s", path);
460 
461     struct sockaddr_un addr;
462     memset(&addr, 0, sizeof(addr));
463 	addr.sun_family = AF_UNIX;
464     strcpy(addr.sun_path, path);
465     unlink(path);
466 
467 	const int y = 1;
468 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
469 
470 	if (bind (fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
471 		log_error( "Error on bind() ...(%s)", strerror(errno));
472 		free(ds);
473         return -1;
474 	}
475 
476     // http://blog.henning.makholm.net/2008/06/unix-domain-socket-woes.html
477     // make socket accept from all clients
478     chmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
479     //
480 
481 	if (listen(fd, MAX_PENDING_CONNECTIONS)) {
482 		log_error( "Error on listen() ...(%s)", strerror(errno));
483 		free(ds);
484         return -1;
485 	}
486 
487     btstack_run_loop_set_data_source_fd(ds, fd);
488     btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
489     btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
490     btstack_run_loop_add_data_source(ds);
491 
492 	log_info ("Server up and running ...");
493     return 0;
494 }
495 
496 /**
497  * set packet handler for all auto-accepted connections
498  */
499 void socket_connection_register_packet_callback( int (*packet_callback)(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length) ){
500     socket_connection_packet_callback = packet_callback;
501 }
502 
503 /**
504  * send HCI packet to single connection
505  */
506 void socket_connection_send_packet(connection_t *conn, uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
507     uint8_t header[sizeof(packet_header_t)];
508     little_endian_store_16(header, 0, type);
509     little_endian_store_16(header, 2, channel);
510     little_endian_store_16(header, 4, size);
511     write(conn->ds.fd, header, 6);
512     write(conn->ds.fd, packet, size);
513 }
514 
515 /**
516  * send HCI packet to all connections
517  */
518 void socket_connection_send_packet_all(uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
519     btstack_linked_item_t *next;
520     btstack_linked_item_t *it;
521     for (it = (btstack_linked_item_t *) connections; it ; it = next){
522         next = it->next; // cache pointer to next connection_t to allow for removal
523         linked_connection_t * linked_connection = (linked_connection_t *) it;
524         socket_connection_send_packet( linked_connection->connection, type, channel, packet, size);
525     }
526 }
527 
528 /**
529  * create socket connection to BTdaemon
530  */
531 connection_t * socket_connection_open_tcp(const char *address, uint16_t port){
532     // TCP
533     struct protoent* tcp = getprotobyname("tcp");
534 
535     int btsocket = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
536 	if(btsocket == -1){
537 		return NULL;
538 	}
539     // localhost
540 	struct sockaddr_in btdaemon_address;
541 	btdaemon_address.sin_family = AF_INET;
542 	btdaemon_address.sin_port = htons(port);
543 	struct hostent* localhost = gethostbyname(address);
544 	if(!localhost){
545 		return NULL;
546 	}
547     // connect
548 	char* addr = localhost->h_addr_list[0];
549 	memcpy(&btdaemon_address.sin_addr.s_addr, addr, sizeof (struct in_addr));
550 	if(connect(btsocket, (struct sockaddr*)&btdaemon_address, sizeof (btdaemon_address)) == -1){
551 		return NULL;
552 	}
553 
554     return socket_connection_register_new_connection(btsocket);
555 }
556 
557 
558 /**
559  * close socket connection to BTdaemon
560  */
561 int socket_connection_close_tcp(connection_t * connection){
562     if (!connection) return -1;
563 #ifdef _WIN32
564     shutdown(connection->ds.fd, SD_BOTH);
565 #else
566     shutdown(connection->ds.fd, SHUT_RDWR);
567 #endif
568     socket_connection_free_connection(connection);
569     return 0;
570 }
571 
572 
573 /**
574  * create socket connection to BTdaemon
575  */
576 connection_t * socket_connection_open_unix(void){
577 
578     int btsocket = socket(AF_UNIX, SOCK_STREAM, 0);
579 	if(btsocket == -1){
580 		return NULL;
581 	}
582 
583     struct sockaddr_un server;
584     memset(&server, 0, sizeof(server));
585     server.sun_family = AF_UNIX;
586     strcpy(server.sun_path, BTSTACK_UNIX);
587     if (connect(btsocket, (struct sockaddr *)&server, sizeof (server)) == -1){
588         return NULL;
589     };
590 
591     return socket_connection_register_new_connection(btsocket);
592 }
593 
594 
595 /**
596  * close socket connection to BTdaemon
597  */
598 int socket_connection_close_unix(connection_t * connection){
599     if (!connection) return -1;
600 #ifdef _WIN32
601     shutdown(connection->ds.fd, SD_BOTH);
602 #else
603     shutdown(connection->ds.fd, SHUT_RDWR);
604 #endif
605     socket_connection_free_connection(connection);
606     return 0;
607 }
608 
609 /**
610  * Init socket connection module
611  */
612 void socket_connection_init(void){
613     // just ignore broken sockets - NO_SO_SIGPIPE
614 #ifndef _WIN32
615     sig_t result = signal(SIGPIPE, SIG_IGN);
616     if (result){
617         log_error("socket_connection_init: failed to ignore SIGPIPE, error: %s", strerror(errno));
618     }
619 #endif
620 }
621 
622 
623