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