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 BLUEKITCHEN
24 * GMBH 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 int socket_fd; // ds only stores event handle in win32
131 SOCKET_STATE state;
132 uint16_t bytes_read;
133 uint16_t bytes_to_read;
134 uint8_t buffer[6+HCI_ACL_BUFFER_SIZE]; // packet_header(6) + max packet: 3-DH5 = header(6) + payload (1021)
135 };
136
137 /** list of socket connections */
138 static btstack_linked_list_t connections = NULL;
139 static btstack_linked_list_t parked = NULL;
140
141 #ifdef _WIN32
142 // workaround as btstack_data_source_t only stores windows event (instead of fd)
143 static int tcp_socket_fd;
144 #endif
145
146 /** client packet handler */
147
148 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;
149
socket_connection_dummy_handler(connection_t * connection,uint16_t packet_type,uint16_t channel,uint8_t * data,uint16_t length)150 static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){
151 UNUSED(connection);
152 UNUSED(packet_type);
153 UNUSED(channel);
154 UNUSED(data);
155 UNUSED(length);
156 return 0;
157 }
158
socket_connection_free_connection(connection_t * conn)159 static void socket_connection_free_connection(connection_t *conn){
160 // remove from run_loop
161 btstack_run_loop_remove_data_source(&conn->ds);
162
163 // and from connection list
164 btstack_linked_list_remove(&connections, &conn->linked_connection.item);
165
166 #ifdef _WIN32
167 if (conn->ds.source.handle){
168 WSACloseEvent(conn->ds.source.handle);
169 }
170 #endif
171
172 // destroy
173 free(conn);
174 }
175
socket_connection_init_statemachine(connection_t * connection)176 static void socket_connection_init_statemachine(connection_t *connection){
177 // wait for next packet
178 connection->state = SOCKET_W4_HEADER;
179 connection->bytes_read = 0;
180 connection->bytes_to_read = sizeof(packet_header_t);
181 }
182
socket_connection_register_new_connection(int fd)183 static connection_t * socket_connection_register_new_connection(int fd){
184 // create connection objec
185 connection_t * conn = malloc( sizeof(connection_t));
186 if (conn == NULL) return NULL;
187 memset(conn, 0, sizeof(connection_t));
188 // store reference from linked item to base object
189 conn->linked_connection.connection = conn;
190
191 // keep fd around
192 conn->socket_fd = fd;
193
194 #ifdef _WIN32
195 // wrap fd in windows event and configure for accept and close
196 WSAEVENT event = WSACreateEvent();
197 if (!event){
198 log_error("Error creating WSAEvent for socket");
199 return NULL;
200 }
201 int res = WSAEventSelect(fd, event, FD_READ | FD_WRITE | FD_CLOSE);
202 if (res == SOCKET_ERROR){
203 log_error("WSAEventSelect() error: %d\n" , WSAGetLastError());
204 free(conn);
205 return NULL;
206 }
207 #endif
208
209 btstack_run_loop_set_data_source_handler(&conn->ds, &socket_connection_hci_process);
210 #ifdef _WIN32
211 conn->ds.source.handle = event;
212 #else
213 btstack_run_loop_set_data_source_fd(&conn->ds, fd);
214 #endif
215 btstack_run_loop_enable_data_source_callbacks(&conn->ds, DATA_SOURCE_CALLBACK_READ);
216
217 // prepare state machine and
218 socket_connection_init_statemachine(conn);
219
220 // add this socket to the run_loop
221 btstack_run_loop_add_data_source( &conn->ds );
222
223 // and the connection list
224 btstack_linked_list_add( &connections, &conn->linked_connection.item);
225
226 return conn;
227 }
228
socket_connection_emit_connection_opened(connection_t * connection)229 void static socket_connection_emit_connection_opened(connection_t *connection){
230 uint8_t event[1];
231 event[0] = DAEMON_EVENT_CONNECTION_OPENED;
232 (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
233 }
234
socket_connection_emit_connection_closed(connection_t * connection)235 void static socket_connection_emit_connection_closed(connection_t *connection){
236 uint8_t event[1];
237 event[0] = DAEMON_EVENT_CONNECTION_CLOSED;
238 (*socket_connection_packet_callback)(connection, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
239 }
240
socket_connection_hci_process(btstack_data_source_t * socket_ds,btstack_data_source_callback_type_t callback_type)241 void socket_connection_hci_process(btstack_data_source_t *socket_ds, btstack_data_source_callback_type_t callback_type) {
242 UNUSED(callback_type);
243 connection_t *conn = (connection_t *) socket_ds;
244
245 log_debug("socket_connection_hci_process, callback %x", callback_type);
246
247 // get socket_fd
248 int socket_fd = conn->socket_fd;
249
250 #ifdef _WIN32
251 // sync state
252 WSANETWORKEVENTS network_events;
253 if (WSAEnumNetworkEvents(socket_fd, socket_ds->source.handle, &network_events) == SOCKET_ERROR){
254 log_error("WSAEnumNetworkEvents() failed with error %d\n", WSAGetLastError());
255 return;
256 }
257 // check if read possible
258 if ((network_events.lNetworkEvents & FD_READ) == 0) return;
259 #endif
260
261 // read from socket
262 #ifdef _WIN32
263 int flags = 0;
264 int bytes_read = recv(socket_fd, (char*) &conn->buffer[conn->bytes_read], conn->bytes_to_read, flags);
265 #else
266 int bytes_read = read(socket_fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
267 #endif
268
269 log_debug("socket_connection_hci_process fd %x, bytes read %d", socket_fd, bytes_read);
270 if (bytes_read <= 0){
271 // connection broken (no particular channel, no date yet)
272 socket_connection_emit_connection_closed(conn);
273
274 // free connection
275 socket_connection_free_connection(conn);
276
277 return;
278 }
279 conn->bytes_read += bytes_read;
280 conn->bytes_to_read -= bytes_read;
281 if (conn->bytes_to_read > 0) return;
282
283 int dispatch = 0;
284 switch (conn->state){
285 case SOCKET_W4_HEADER:
286 conn->state = SOCKET_W4_DATA;
287 conn->bytes_to_read = little_endian_read_16( conn->buffer, 4);
288 if (conn->bytes_to_read == 0){
289 dispatch = 1;
290 }
291 break;
292 case SOCKET_W4_DATA:
293 dispatch = 1;
294 break;
295 default:
296 break;
297 }
298
299 if (dispatch){
300 // dispatch packet !!! connection, type, channel, data, size
301 int dispatch_err = (*socket_connection_packet_callback)(conn, little_endian_read_16( conn->buffer, 0), little_endian_read_16( conn->buffer, 2),
302 &conn->buffer[sizeof(packet_header_t)], little_endian_read_16( conn->buffer, 4));
303
304 // reset state machine
305 socket_connection_init_statemachine(conn);
306
307 // "park" if dispatch failed
308 if (dispatch_err) {
309 log_info("socket_connection_hci_process dispatch failed -> park connection");
310 btstack_run_loop_remove_data_source(socket_ds);
311 btstack_linked_list_add_tail(&parked, (btstack_linked_item_t *) socket_ds);
312 }
313 }
314 }
315
316 /**
317 * try to dispatch packet for all "parked" connections.
318 * if dispatch is successful, a connection is added again to run loop
319 * pre: connections get parked iff packet was dispatched but could not be sent
320 */
socket_connection_retry_parked(void)321 void socket_connection_retry_parked(void){
322 // log_info("socket_connection_hci_process retry parked");
323 btstack_linked_item_t *it = (btstack_linked_item_t *) &parked;
324 while (it->next) {
325 connection_t * conn = (connection_t *) it->next;
326
327 // dispatch packet !!! connection, type, channel, data, size
328 uint16_t packet_type = little_endian_read_16( conn->buffer, 0);
329 uint16_t channel = little_endian_read_16( conn->buffer, 2);
330 uint16_t length = little_endian_read_16( conn->buffer, 4);
331 log_info("socket_connection_hci_process retry parked %p (type %u, channel %04x, length %u", conn, packet_type, channel, length);
332 int dispatch_err = (*socket_connection_packet_callback)(conn, packet_type, channel, &conn->buffer[sizeof(packet_header_t)], length);
333 // "un-park" if successful
334 if (!dispatch_err) {
335 log_info("socket_connection_hci_process dispatch succeeded -> un-park connection %p", conn);
336 it->next = it->next->next;
337 btstack_run_loop_add_data_source( (btstack_data_source_t *) conn);
338 } else {
339 it = it->next;
340 }
341 }
342 }
343
socket_connection_has_parked_connections(void)344 int socket_connection_has_parked_connections(void){
345 return parked != NULL;
346 }
347
socket_connection_accept(btstack_data_source_t * socket_ds,btstack_data_source_callback_type_t callback_type)348 static void socket_connection_accept(btstack_data_source_t *socket_ds, btstack_data_source_callback_type_t callback_type) {
349 UNUSED(callback_type);
350 struct sockaddr_storage ss;
351 socklen_t slen = sizeof(ss);
352
353 // get socket_fd
354 #ifdef _WIN32
355 int socket_fd = tcp_socket_fd;
356 #else
357 int socket_fd = btstack_run_loop_get_data_source_fd(socket_ds);
358 #endif
359
360 #ifdef _WIN32
361 // sync state
362 WSANETWORKEVENTS network_events;
363 if (WSAEnumNetworkEvents(socket_fd, socket_ds->source.handle, &network_events) == SOCKET_ERROR){
364 log_error("WSAEnumNetworkEvents() failed with error %d\n", WSAGetLastError());
365 return;
366 }
367 #endif
368
369 /* New connection coming in! */
370 int fd = accept(socket_fd, (struct sockaddr *)&ss, &slen);
371 if (fd < 0) {
372 perror("accept");
373 return;
374 }
375
376 log_info("socket_connection_accept new connection %u", fd);
377
378 connection_t * connection = socket_connection_register_new_connection(fd);
379 socket_connection_emit_connection_opened(connection);
380 }
381
382 /**
383 * create socket data_source for tcp socket
384 *
385 * @return data_source object. If null, check errno
386 */
socket_connection_create_tcp(int port)387 int socket_connection_create_tcp(int port){
388
389 // create btstack_data_source_t
390 btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
391 if (ds == NULL) return -1;
392
393 // create tcp socket
394 int fd = socket (PF_INET, SOCK_STREAM, 0);
395 if (fd < 0) {
396 log_error("Error creating socket ...(%s)", strerror(errno));
397 free(ds);
398 return -1;
399 }
400
401 log_info ("Socket created for port %u", port);
402
403 #ifdef _WIN32
404 // wrap fd in windows event and configure for accept and close
405 WSAEVENT event = WSACreateEvent();
406 if (!event){
407 log_error("Error creating WSAEvent for socket");
408 free(ds);
409 return -1;
410 }
411 int res = WSAEventSelect(fd, event, FD_ACCEPT | FD_CLOSE);
412 if (res == SOCKET_ERROR){
413 log_error("WSAEventSelect() error: %d\n" , WSAGetLastError());
414 free(ds);
415 return -1;
416 }
417 // keep fd around
418 tcp_socket_fd = fd;
419 #endif
420
421 struct sockaddr_in addr;
422 addr.sin_family = AF_INET;
423 addr.sin_port = htons (port);
424 memset (&addr.sin_addr, 0, sizeof (addr.sin_addr));
425
426 const int y = 1;
427 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
428
429 if (bind ( fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
430 log_error("Error on bind() ...(%s)", strerror(errno));
431 free(ds);
432 return -1;
433 }
434
435 if (listen (fd, MAX_PENDING_CONNECTIONS)) {
436 log_error("Error on listen() ...(%s)", strerror(errno));
437 free(ds);
438 return -1;
439 }
440
441 #ifdef _WIN32
442 ds->source.handle = event;
443 #else
444 btstack_run_loop_set_data_source_fd(ds, fd);
445 #endif
446 btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
447 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
448 btstack_run_loop_add_data_source(ds);
449
450 log_info ("Server up and running ...");
451 return 0;
452 }
453
454 #ifdef USE_LAUNCHD
455
456 /*
457 * Register listening sockets with our run loop
458 */
socket_connection_launchd_register_fd_array(launch_data_t listening_fd_array)459 void socket_connection_launchd_register_fd_array(launch_data_t listening_fd_array){
460 int i;
461 for (i = 0; i < launch_data_array_get_count(listening_fd_array); i++) {
462 // get fd
463 launch_data_t tempi = launch_data_array_get_index (listening_fd_array, i);
464 int listening_fd = launch_data_get_fd(tempi);
465 launch_data_free (tempi);
466 log_info("file descriptor = %u", listening_fd);
467
468 // create btstack_data_source_t for fd
469 btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
470 if (ds == NULL) return;
471 btstack_run_loop_set_data_source_fd(ds, listening_fd);
472 btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
473 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
474 btstack_run_loop_add_data_source(ds);
475 }
476 }
477
478 /**
479 * create socket data_source for socket specified by launchd configuration
480 */
socket_connection_create_launchd(void)481 int socket_connection_create_launchd(void){
482
483 launch_data_t sockets_dict, checkin_response;
484 launch_data_t checkin_request;
485 launch_data_t listening_fd_array;
486
487 /*
488 * Register ourselves with launchd.
489 *
490 */
491 if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
492 log_error( "launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.");
493 return -1;
494 }
495
496 if ((checkin_response = launch_msg(checkin_request)) == NULL) {
497 log_error( "launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %u", errno);
498 return -1;
499 }
500
501 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
502 errno = launch_data_get_errno(checkin_response);
503 log_error( "Check-in failed: %u", errno);
504 return -1;
505 }
506
507 launch_data_t the_label = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_LABEL);
508 if (NULL == the_label) {
509 log_error( "No label found");
510 return -1;
511 }
512
513 /*
514 * Retrieve the dictionary of Socket entries in the config file
515 */
516 sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
517 if (NULL == sockets_dict) {
518 log_error("No sockets found to answer requests on!");
519 return -1;
520 }
521
522 // if (launch_data_dict_get_count(sockets_dict) > 1) {
523 // log_error("Some sockets will be ignored!");
524 // }
525
526 /*
527 * Get the dictionary value from the key "Listeners"
528 */
529 listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners");
530 if (listening_fd_array) {
531 // log_error("Listeners...");
532 socket_connection_launchd_register_fd_array( listening_fd_array );
533 }
534
535 /*
536 * Get the dictionary value from the key "Listeners"
537 */
538 listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners2");
539 if (listening_fd_array) {
540 // log_error("Listeners2...");
541 socket_connection_launchd_register_fd_array( listening_fd_array );
542 }
543
544 // although used in Apple examples, it creates a malloc warning
545 // launch_data_free(checkin_response);
546 return 0;
547 }
548 #endif
549
550
551 /**
552 * set packet handler for all auto-accepted connections
553 */
socket_connection_register_packet_callback(int (* packet_callback)(connection_t * connection,uint16_t packet_type,uint16_t channel,uint8_t * data,uint16_t length))554 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) ){
555 socket_connection_packet_callback = packet_callback;
556 }
557
558 /**
559 * send HCI packet to single connection
560 */
socket_connection_send_packet(connection_t * conn,uint16_t type,uint16_t channel,uint8_t * packet,uint16_t size)561 void socket_connection_send_packet(connection_t *conn, uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
562 uint8_t header[sizeof(packet_header_t)];
563 little_endian_store_16(header, 0, type);
564 little_endian_store_16(header, 2, channel);
565 little_endian_store_16(header, 4, size);
566 // avoid -Wunused-result
567 int res;
568 #ifdef _WIN32
569 int flags = 0;
570 res = send(conn->socket_fd, (const char *) header, 6, flags);
571 res = send(conn->socket_fd, (const char *) packet, size, flags);
572 #else
573 res = write(conn->socket_fd, header, 6);
574 res = write(conn->socket_fd, packet, size);
575 #endif
576 UNUSED(res);
577 }
578
579 /**
580 * send HCI packet to all connections
581 */
socket_connection_send_packet_all(uint16_t type,uint16_t channel,uint8_t * packet,uint16_t size)582 void socket_connection_send_packet_all(uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
583 btstack_linked_item_t *next;
584 btstack_linked_item_t *it;
585 for (it = (btstack_linked_item_t *) connections; it ; it = next){
586 next = it->next; // cache pointer to next connection_t to allow for removal
587 linked_connection_t * linked_connection = (linked_connection_t *) it;
588 socket_connection_send_packet( linked_connection->connection, type, channel, packet, size);
589 }
590 }
591
592 /**
593 * create socket connection to BTdaemon
594 */
socket_connection_open_tcp(const char * address,uint16_t port)595 connection_t * socket_connection_open_tcp(const char *address, uint16_t port){
596 // TCP
597 struct protoent* tcp = getprotobyname("tcp");
598
599 int btsocket = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
600 if(btsocket == -1){
601 return NULL;
602 }
603 // localhost
604 struct sockaddr_in btdaemon_address;
605 btdaemon_address.sin_family = AF_INET;
606 btdaemon_address.sin_port = htons(port);
607 struct hostent* localhost = gethostbyname(address);
608 if(!localhost){
609 return NULL;
610 }
611 // connect
612 char* addr = localhost->h_addr_list[0];
613 memcpy(&btdaemon_address.sin_addr.s_addr, addr, sizeof (struct in_addr));
614 if(connect(btsocket, (struct sockaddr*)&btdaemon_address, sizeof (btdaemon_address)) == -1){
615 return NULL;
616 }
617
618 return socket_connection_register_new_connection(btsocket);
619 }
620
621
622 /**
623 * close socket connection to BTdaemon
624 */
socket_connection_close_tcp(connection_t * connection)625 int socket_connection_close_tcp(connection_t * connection){
626 if (!connection) return -1;
627 #ifdef _WIN32
628 shutdown(connection->ds.source.fd, SD_BOTH);
629 #else
630 shutdown(connection->ds.source.fd, SHUT_RDWR);
631 #endif
632 socket_connection_free_connection(connection);
633 return 0;
634 }
635
636 #ifdef HAVE_UNIX_SOCKETS
637
638 /**
639 * create socket data_source for unix domain socket
640 */
socket_connection_create_unix(char * path)641 int socket_connection_create_unix(char *path){
642
643 // create btstack_data_source_t
644 btstack_data_source_t *ds = calloc(sizeof(btstack_data_source_t), 1);
645 if (ds == NULL) return -1;
646
647 // create unix socket
648 int fd = socket (AF_UNIX, SOCK_STREAM, 0);
649 if (fd < 0) {
650 log_error( "Error creating socket ...(%s)", strerror(errno));
651 free(ds);
652 return -1;
653 }
654 log_info ("Socket created at %s", path);
655
656 struct sockaddr_un addr;
657 memset(&addr, 0, sizeof(addr));
658 addr.sun_family = AF_UNIX;
659 strcpy(addr.sun_path, path);
660 unlink(path);
661
662 const int y = 1;
663 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &y, sizeof(int));
664
665 if (bind (fd, (struct sockaddr *) &addr, sizeof (addr) ) ) {
666 log_error( "Error on bind() ...(%s)", strerror(errno));
667 free(ds);
668 return -1;
669 }
670
671 // http://blog.henning.makholm.net/2008/06/unix-domain-socket-woes.html
672 // make socket accept from all clients
673 chmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
674 //
675
676 if (listen(fd, MAX_PENDING_CONNECTIONS)) {
677 log_error( "Error on listen() ...(%s)", strerror(errno));
678 free(ds);
679 return -1;
680 }
681
682 btstack_run_loop_set_data_source_fd(ds, fd);
683 btstack_run_loop_set_data_source_handler(ds, &socket_connection_accept);
684 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
685 btstack_run_loop_add_data_source(ds);
686
687 log_info ("Server up and running ...");
688 return 0;
689 }
690
691 /**
692 * create socket connection to BTdaemon
693 */
socket_connection_open_unix(void)694 connection_t * socket_connection_open_unix(void){
695
696 int btsocket = socket(AF_UNIX, SOCK_STREAM, 0);
697 if(btsocket == -1){
698 return NULL;
699 }
700
701 struct sockaddr_un server;
702 memset(&server, 0, sizeof(server));
703 server.sun_family = AF_UNIX;
704 strcpy(server.sun_path, BTSTACK_UNIX);
705 if (connect(btsocket, (struct sockaddr *)&server, sizeof (server)) == -1){
706 return NULL;
707 };
708
709 return socket_connection_register_new_connection(btsocket);
710 }
711
712
713 /**
714 * close socket connection to BTdaemon
715 */
socket_connection_close_unix(connection_t * connection)716 int socket_connection_close_unix(connection_t * connection){
717 if (!connection) return -1;
718 #ifdef _WIN32
719 shutdown(connection->ds.source.fd, SD_BOTH);
720 #else
721 shutdown(connection->ds.source.fd, SHUT_RDWR);
722 #endif
723 socket_connection_free_connection(connection);
724 return 0;
725 }
726
727 #endif /* HAVE_UNIX_SOCKETS */
728
729 /**
730 * Init socket connection module
731 */
socket_connection_init(void)732 void socket_connection_init(void){
733
734 // just ignore broken sockets - NO_SO_SIGPIPE
735 #ifndef _WIN32
736 sig_t result = signal(SIGPIPE, SIG_IGN);
737 if (result){
738 log_error("socket_connection_init: failed to ignore SIGPIPE, error: %s", strerror(errno));
739 }
740 #endif
741
742 #ifdef _WIN32
743 // TODO: call WSACleanup with wsa data on shutdown
744 WSADATA wsa;
745 int res = WSAStartup(MAKEWORD(2, 2), &wsa);
746 log_info("WSAStartup(v2.2) = %x", res);
747 if (res){
748 log_error("WSAStartup error: %d", WSAGetLastError());
749 return;
750 }
751 #endif
752 }
753
754
755