xref: /btstack/platform/daemon/src/socket_connection.c (revision 09cf8159072d80e092b9c303cea9b43a81b36aee)
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 #endif
88 
89 // has been missing on mingw32 in the past
90 #ifndef S_IRWXG
91 #define S_IRWXG 0
92 #endif
93 #ifndef S_IRWXO
94 #define S_IRWXO 0
95 #endif
96 
97 #ifdef USE_LAUNCHD
98 #include "../port/ios/3rdparty/launch.h"
99 #endif
100 
101 #define MAX_PENDING_CONNECTIONS 10
102 
103 /** prototypes */
104 static void socket_connection_hci_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
105 static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length);
106 
107 /** globals */
108 
109 /** packet header used over socket connections, in front of the HCI packet */
110 typedef struct packet_header {
111     uint16_t type;
112     uint16_t channel;
113     uint16_t length;
114     uint8_t  data[0];
115 } packet_header_t;  // 6
116 
117 typedef enum {
118     SOCKET_W4_HEADER,
119     SOCKET_W4_DATA
120 } SOCKET_STATE;
121 
122 typedef struct linked_connection {
123     btstack_linked_item_t item;
124     connection_t * connection;
125 } linked_connection_t;
126 
127 struct connection {
128     btstack_data_source_t ds;                // used for run loop
129     linked_connection_t linked_connection;   // used for connection list
130     SOCKET_STATE state;
131     uint16_t bytes_read;
132     uint16_t bytes_to_read;
133     uint8_t  buffer[6+HCI_ACL_BUFFER_SIZE]; // packet_header(6) + max packet: 3-DH5 = header(6) + payload (1021)
134 };
135 
136 /** list of socket connections */
137 static btstack_linked_list_t connections = NULL;
138 static btstack_linked_list_t parked = NULL;
139 
140 
141 /** client packet handler */
142 
143 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;
144 
145 static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){
146     UNUSED(connection);
147     UNUSED(packet_type);
148     UNUSED(channel);
149     UNUSED(data);
150     UNUSED(length);
151     return 0;
152 }
153 
154 static void socket_connection_free_connection(connection_t *conn){
155     // remove from run_loop
156     btstack_run_loop_remove_data_source(&conn->ds);
157 
158     // and from connection list
159     btstack_linked_list_remove(&connections, &conn->linked_connection.item);
160 
161     // destroy
162     free(conn);
163 }
164 
165 static void socket_connection_init_statemachine(connection_t *connection){
166     // wait for next packet
167     connection->state = SOCKET_W4_HEADER;
168     connection->bytes_read = 0;
169     connection->bytes_to_read = sizeof(packet_header_t);
170 }
171 
172 static connection_t * socket_connection_register_new_connection(int fd){
173     // create connection objec
174     connection_t * conn = malloc( sizeof(connection_t));
175     if (conn == NULL) return 0;
176 
177     // store reference from linked item to base object
178     conn->linked_connection.connection = conn;
179 
180     btstack_run_loop_set_data_source_handler(&conn->ds, &socket_connection_hci_process);
181     btstack_run_loop_set_data_source_fd(&conn->ds, fd);
182     btstack_run_loop_enable_data_source_callbacks(&conn->ds, DATA_SOURCE_CALLBACK_READ);
183 
184     // prepare state machine and
185     socket_connection_init_statemachine(conn);
186 
187     // add this socket to the run_loop
188     btstack_run_loop_add_data_source( &conn->ds );
189 
190     // and the connection list
191     btstack_linked_list_add( &connections, &conn->linked_connection.item);
192 
193     return conn;
194 }
195 
196 void static socket_connection_emit_connection_opened(connection_t *connection){
197     uint8_t event[1];
198     event[0] = DAEMON_EVENT_CONNECTION_OPENED;
199     (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
200 }
201 
202 void static socket_connection_emit_connection_closed(connection_t *connection){
203     uint8_t event[1];
204     event[0] = DAEMON_EVENT_CONNECTION_CLOSED;
205     (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
206 }
207 
208 void socket_connection_hci_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
209     UNUSED(callback_type);
210     connection_t *conn = (connection_t *) ds;
211     int fd = btstack_run_loop_get_data_source_fd(ds);
212     int bytes_read = read(fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
213     if (bytes_read <= 0){
214         // connection broken (no particular channel, no date yet)
215         socket_connection_emit_connection_closed(conn);
216 
217         // free connection
218         socket_connection_free_connection(conn);
219 
220         return;
221     }
222     conn->bytes_read += bytes_read;
223     conn->bytes_to_read -= bytes_read;
224     if (conn->bytes_to_read > 0) return;
225 
226     int dispatch = 0;
227     switch (conn->state){
228         case SOCKET_W4_HEADER:
229             conn->state = SOCKET_W4_DATA;
230             conn->bytes_to_read = little_endian_read_16( conn->buffer, 4);
231             if (conn->bytes_to_read == 0){
232                 dispatch = 1;
233             }
234             break;
235         case SOCKET_W4_DATA:
236             dispatch = 1;
237             break;
238         default:
239             break;
240     }
241 
242     if (dispatch){
243         // dispatch packet !!! connection, type, channel, data, size
244         int dispatch_err = (*socket_connection_packet_callback)(conn, little_endian_read_16( conn->buffer, 0), little_endian_read_16( conn->buffer, 2),
245                                                             &conn->buffer[sizeof(packet_header_t)], little_endian_read_16( conn->buffer, 4));
246 
247         // reset state machine
248         socket_connection_init_statemachine(conn);
249 
250         // "park" if dispatch failed
251         if (dispatch_err) {
252             log_info("socket_connection_hci_process dispatch failed -> park connection");
253             btstack_run_loop_remove_data_source(ds);
254             btstack_linked_list_add_tail(&parked, (btstack_linked_item_t *) ds);
255         }
256     }
257 }
258 
259 /**
260  * try to dispatch packet for all "parked" connections.
261  * if dispatch is successful, a connection is added again to run loop
262  * pre: connections get parked iff packet was dispatched but could not be sent
263  */
264 void socket_connection_retry_parked(void){
265     // log_info("socket_connection_hci_process retry parked");
266     btstack_linked_item_t *it = (btstack_linked_item_t *) &parked;
267     while (it->next) {
268         connection_t * conn = (connection_t *) it->next;
269 
270         // dispatch packet !!! connection, type, channel, data, size
271         uint16_t packet_type = little_endian_read_16( conn->buffer, 0);
272         uint16_t channel     = little_endian_read_16( conn->buffer, 2);
273         uint16_t length      = little_endian_read_16( conn->buffer, 4);
274         log_info("socket_connection_hci_process retry parked %p (type %u, channel %04x, length %u", conn, packet_type, channel, length);
275         int dispatch_err = (*socket_connection_packet_callback)(conn, packet_type, channel, &conn->buffer[sizeof(packet_header_t)], length);
276         // "un-park" if successful
277         if (!dispatch_err) {
278             log_info("socket_connection_hci_process dispatch succeeded -> un-park connection %p", conn);
279             it->next = it->next->next;
280             btstack_run_loop_add_data_source( (btstack_data_source_t *) conn);
281         } else {
282             it = it->next;
283         }
284     }
285 }
286 
287 int  socket_connection_has_parked_connections(void){
288     return parked != NULL;
289 }
290 
291 static void socket_connection_accept(btstack_data_source_t *socket_ds, btstack_data_source_callback_type_t callback_type) {
292     UNUSED(callback_type);
293     struct sockaddr_storage ss;
294     socklen_t slen = sizeof(ss);
295     int socket_fd = btstack_run_loop_get_data_source_fd(socket_ds);
296 
297 	/* New connection coming in! */
298 	int fd = accept(socket_fd, (struct sockaddr *)&ss, &slen);
299 	if (fd < 0) {
300 		perror("accept");
301         return;
302 	}
303 
304     log_info("socket_connection_accept new connection %u", fd);
305 
306     connection_t * connection = socket_connection_register_new_connection(fd);
307     socket_connection_emit_connection_opened(connection);
308 }
309 
310 /**
311  * create socket data_source for tcp socket
312  *
313  * @return data_source object. If null, check errno
314  */
315 int socket_connection_create_tcp(int port){
316 
317     // create btstack_data_source_t
318     btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
319     if (ds == NULL) return -1;
320 
321 	// create tcp socket
322     int fd = socket (PF_INET, SOCK_STREAM, 0);
323 	if (fd < 0) {
324 		log_error("Error creating socket ...(%s)", strerror(errno));
325 		free(ds);
326         return -1;
327 	}
328 
329 	log_info ("Socket created for port %u", port);
330 
331     struct sockaddr_in addr;
332 	addr.sin_family = AF_INET;
333 	addr.sin_port = htons (port);
334 	memset (&addr.sin_addr, 0, sizeof (addr.sin_addr));
335 
336 	const int y = 1;
337 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
338 
339 	if (bind ( fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
340 		log_error("Error on bind() ...(%s)", strerror(errno));
341 		free(ds);
342         return -1;
343 	}
344 
345 	if (listen (fd, MAX_PENDING_CONNECTIONS)) {
346 		log_error("Error on listen() ...(%s)", strerror(errno));
347 		free(ds);
348         return -1;
349 	}
350 
351     btstack_run_loop_set_data_source_fd(ds, fd);
352     btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
353     btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
354     btstack_run_loop_add_data_source(ds);
355 
356 	log_info ("Server up and running ...");
357     return 0;
358 }
359 
360 #ifdef USE_LAUNCHD
361 
362 /*
363  * Register listening sockets with our run loop
364  */
365 void socket_connection_launchd_register_fd_array(launch_data_t listening_fd_array){
366 	int i;
367     for (i = 0; i < launch_data_array_get_count(listening_fd_array); i++) {
368         // get fd
369         launch_data_t tempi = launch_data_array_get_index (listening_fd_array, i);
370         int listening_fd = launch_data_get_fd(tempi);
371         launch_data_free (tempi);
372 		log_info("file descriptor = %u", listening_fd);
373 
374         // create btstack_data_source_t for fd
375         btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
376         if (ds == NULL) return;
377         btstack_run_loop_set_data_source_fd(ds, listening_fd);
378         btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
379         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
380         btstack_run_loop_add_data_source(ds);
381 	}
382 }
383 
384 /**
385  * create socket data_source for socket specified by launchd configuration
386  */
387 int socket_connection_create_launchd(void){
388 
389     launch_data_t sockets_dict, checkin_response;
390 	launch_data_t checkin_request;
391     launch_data_t listening_fd_array;
392 
393 	/*
394 	 * Register ourselves with launchd.
395 	 *
396 	 */
397 	if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
398 		log_error( "launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.");
399 		return -1;
400 	}
401 
402 	if ((checkin_response = launch_msg(checkin_request)) == NULL) {
403 		log_error( "launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %u", errno);
404 		return -1;
405 	}
406 
407 	if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
408 		errno = launch_data_get_errno(checkin_response);
409 		log_error( "Check-in failed: %u", errno);
410 		return -1;
411 	}
412 
413     launch_data_t the_label = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_LABEL);
414 	if (NULL == the_label) {
415 		log_error( "No label found");
416 		return -1;
417 	}
418 
419 	/*
420 	 * Retrieve the dictionary of Socket entries in the config file
421 	 */
422 	sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
423 	if (NULL == sockets_dict) {
424 		log_error("No sockets found to answer requests on!");
425 		return -1;
426 	}
427 
428 	// if (launch_data_dict_get_count(sockets_dict) > 1) {
429 	// 	log_error("Some sockets will be ignored!");
430 	// }
431 
432 	/*
433 	 * Get the dictionary value from the key "Listeners"
434 	 */
435 	listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners");
436 	if (listening_fd_array) {
437         // log_error("Listeners...");
438         socket_connection_launchd_register_fd_array( listening_fd_array );
439     }
440 
441 	/*
442 	 * Get the dictionary value from the key "Listeners"
443 	 */
444 	listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners2");
445 	if (listening_fd_array) {
446         // log_error("Listeners2...");
447         socket_connection_launchd_register_fd_array( listening_fd_array );
448     }
449 
450     // although used in Apple examples, it creates a malloc warning
451 	// launch_data_free(checkin_response);
452     return 0;
453 }
454 #endif
455 
456 
457 /**
458  * set packet handler for all auto-accepted connections
459  */
460 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) ){
461     socket_connection_packet_callback = packet_callback;
462 }
463 
464 /**
465  * send HCI packet to single connection
466  */
467 void socket_connection_send_packet(connection_t *conn, uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
468     uint8_t header[sizeof(packet_header_t)];
469     little_endian_store_16(header, 0, type);
470     little_endian_store_16(header, 2, channel);
471     little_endian_store_16(header, 4, size);
472     write(conn->ds.source.fd, header, 6);
473     write(conn->ds.source.fd, packet, size);
474 }
475 
476 /**
477  * send HCI packet to all connections
478  */
479 void socket_connection_send_packet_all(uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
480     btstack_linked_item_t *next;
481     btstack_linked_item_t *it;
482     for (it = (btstack_linked_item_t *) connections; it ; it = next){
483         next = it->next; // cache pointer to next connection_t to allow for removal
484         linked_connection_t * linked_connection = (linked_connection_t *) it;
485         socket_connection_send_packet( linked_connection->connection, type, channel, packet, size);
486     }
487 }
488 
489 /**
490  * create socket connection to BTdaemon
491  */
492 connection_t * socket_connection_open_tcp(const char *address, uint16_t port){
493     // TCP
494     struct protoent* tcp = getprotobyname("tcp");
495 
496     int btsocket = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
497 	if(btsocket == -1){
498 		return NULL;
499 	}
500     // localhost
501 	struct sockaddr_in btdaemon_address;
502 	btdaemon_address.sin_family = AF_INET;
503 	btdaemon_address.sin_port = htons(port);
504 	struct hostent* localhost = gethostbyname(address);
505 	if(!localhost){
506 		return NULL;
507 	}
508     // connect
509 	char* addr = localhost->h_addr_list[0];
510 	memcpy(&btdaemon_address.sin_addr.s_addr, addr, sizeof (struct in_addr));
511 	if(connect(btsocket, (struct sockaddr*)&btdaemon_address, sizeof (btdaemon_address)) == -1){
512 		return NULL;
513 	}
514 
515     return socket_connection_register_new_connection(btsocket);
516 }
517 
518 
519 /**
520  * close socket connection to BTdaemon
521  */
522 int socket_connection_close_tcp(connection_t * connection){
523     if (!connection) return -1;
524 #ifdef _WIN32
525     shutdown(connection->ds.source.fd, SD_BOTH);
526 #else
527     shutdown(connection->ds.source.fd, SHUT_RDWR);
528 #endif
529     socket_connection_free_connection(connection);
530     return 0;
531 }
532 
533 #ifdef HAVE_UNIX_SOCKETS
534 
535 /**
536  * create socket data_source for unix domain socket
537  */
538 int socket_connection_create_unix(char *path){
539 
540     // create btstack_data_source_t
541     btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
542     if (ds == NULL) return -1;
543 
544     // create unix socket
545     int fd = socket (AF_UNIX, SOCK_STREAM, 0);
546     if (fd < 0) {
547         log_error( "Error creating socket ...(%s)", strerror(errno));
548         free(ds);
549         return -1;
550     }
551     log_info ("Socket created at %s", path);
552 
553     struct sockaddr_un addr;
554     memset(&addr, 0, sizeof(addr));
555     addr.sun_family = AF_UNIX;
556     strcpy(addr.sun_path, path);
557     unlink(path);
558 
559     const int y = 1;
560     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
561 
562     if (bind (fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
563         log_error( "Error on bind() ...(%s)", strerror(errno));
564         free(ds);
565         return -1;
566     }
567 
568     // http://blog.henning.makholm.net/2008/06/unix-domain-socket-woes.html
569     // make socket accept from all clients
570     chmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
571     //
572 
573     if (listen(fd, MAX_PENDING_CONNECTIONS)) {
574         log_error( "Error on listen() ...(%s)", strerror(errno));
575         free(ds);
576         return -1;
577     }
578 
579     btstack_run_loop_set_data_source_fd(ds, fd);
580     btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
581     btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
582     btstack_run_loop_add_data_source(ds);
583 
584     log_info ("Server up and running ...");
585     return 0;
586 }
587 
588 /**
589  * create socket connection to BTdaemon
590  */
591 connection_t * socket_connection_open_unix(void){
592 
593     int btsocket = socket(AF_UNIX, SOCK_STREAM, 0);
594 	if(btsocket == -1){
595 		return NULL;
596 	}
597 
598     struct sockaddr_un server;
599     memset(&server, 0, sizeof(server));
600     server.sun_family = AF_UNIX;
601     strcpy(server.sun_path, BTSTACK_UNIX);
602     if (connect(btsocket, (struct sockaddr *)&server, sizeof (server)) == -1){
603         return NULL;
604     };
605 
606     return socket_connection_register_new_connection(btsocket);
607 }
608 
609 
610 /**
611  * close socket connection to BTdaemon
612  */
613 int socket_connection_close_unix(connection_t * connection){
614     if (!connection) return -1;
615 #ifdef _WIN32
616     shutdown(connection->ds.source.fd, SD_BOTH);
617 #else
618     shutdown(connection->ds.source.fd, SHUT_RDWR);
619 #endif
620     socket_connection_free_connection(connection);
621     return 0;
622 }
623 
624 #endif /* HAVE_UNIX_SOCKETS */
625 
626 /**
627  * Init socket connection module
628  */
629 void socket_connection_init(void){
630     // just ignore broken sockets - NO_SO_SIGPIPE
631 #ifndef _WIN32
632     sig_t result = signal(SIGPIPE, SIG_IGN);
633     if (result){
634         log_error("socket_connection_init: failed to ignore SIGPIPE, error: %s", strerror(errno));
635     }
636 #endif
637 }
638 
639 
640