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