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