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