From 7120e736f630b8697b0359fc1834bd9728f24590 Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Mon, 21 Sep 2020 15:14:50 -0500 Subject: [PATCH] more refactoring --- examples/read.c | 14 ++-- examples/test.c | 59 ++++++++++----- include/skipstone/link.h | 16 +++-- include/skipstone/message.h | 12 ++-- src/link.c | 140 +++++++++++------------------------- src/message.c | 94 ++++++++++++------------ src/system.c | 14 ++-- 7 files changed, 165 insertions(+), 184 deletions(-) diff --git a/examples/read.c b/examples/read.c index f7bd75d..8e92910 100644 --- a/examples/read.c +++ b/examples/read.c @@ -12,8 +12,11 @@ static void usage(int argc, char **argv) { int main(int argc, char **argv) { skipstone_link *link; + void *buf; - uint16_t len, endpoint; + ssize_t len; + + uint16_t endpoint; if (argc != 2) { usage(argc, argv); @@ -23,12 +26,15 @@ int main(int argc, char **argv) { goto error_malloc_buf; } - if ((link = skipstone_link_open_serial(argv[1])) == NULL) { + if ((link = skipstone_link_open(argv[1])) == NULL) { goto error_link_open; } - while (skipstone_link_recv(link, buf, &len, &endpoint, NULL) >= 0) { - printf("Received message %hu bytes for endpoint %hu\n", + while ((len = skipstone_link_recv(link, + buf, + &endpoint, + SKIPSTONE_MESSAGE_MAX_PAYLOAD)) >= 0) { + printf("Received message %zd bytes for endpoint %hu\n", len, endpoint); } diff --git a/examples/test.c b/examples/test.c index 1b87c9e..2477073 100644 --- a/examples/test.c +++ b/examples/test.c @@ -9,13 +9,20 @@ #include "../src/util.h" +struct context { + skipstone_link *link; +}; + static void usage(int argc, char **argv) { fprintf(stderr, "usage: %s /dev/rfcommX\n", argv[0]); exit(1); } static int answer_phone_version_message(skipstone_message_service *service, - void *buf, uint16_t size, uint16_t id, void *context) { + void *buf, + uint16_t size, + uint16_t id, + void *context) { const uint32_t flags = SKIPSTONE_SYSTEM_CLIENT_TELEPHONY | SKIPSTONE_SYSTEM_CLIENT_SMS | SKIPSTONE_SYSTEM_CLIENT_ANDROID; @@ -24,7 +31,12 @@ static int answer_phone_version_message(skipstone_message_service *service, } static int answer_music_message(skipstone_message_service *service, - void *buf, uint16_t size, uint16_t id, void *context) { + void *buf, + uint16_t size, + uint16_t id, + void *ctx) { + struct context *context = ctx; + uint8_t message[256]; ssize_t len; @@ -39,7 +51,9 @@ static int answer_music_message(skipstone_message_service *service, goto error_message_pack; } - skipstone_message_service_queue(service, message, len, 32); + if (skipstone_link_send(context->link, message, 32, len) < 0) { + goto error_link_send; + } if ((len = skipstone_message_pack(message, sizeof(message), @@ -54,7 +68,9 @@ static int answer_music_message(skipstone_message_service *service, goto error_message_pack; } - skipstone_message_service_queue(service, message, len, 32); + if (skipstone_link_send(context->link, message, 32, len) < 0) { + goto error_link_send; + } if ((len = skipstone_message_pack(message, sizeof(message), @@ -65,19 +81,25 @@ static int answer_music_message(skipstone_message_service *service, goto error_message_pack; } - skipstone_message_service_queue(service, message, len, 32); + if (skipstone_link_send(context->link, message, 32, len) < 0) { + goto error_link_send; + } } else { printf("Got playback command %02x\n", ((uint8_t *)buf)[0]); } return 0; +error_link_send: error_message_pack: return -1; } static int answer_phone_message(skipstone_message_service *service, - void *buf, uint16_t size, uint16_t id, void *context) { + void *buf, + uint16_t size, + uint16_t id, + void *context) { printf("Got phone command %02x\n", ((uint8_t *)buf)[0]); return 0; @@ -87,32 +109,31 @@ int main(int argc, char **argv) { skipstone_link *link; skipstone_message_service *service; + struct context context; + if (argc != 2) { usage(argc, argv); } - if ((link = skipstone_link_open_serial(argv[1])) == NULL) { - perror("skipstone_link_open_serial()"); + if ((link = skipstone_link_open(argv[1])) == NULL) { + perror("skipstone_link_open()"); goto error_link_open; } - if ((service = skipstone_message_service_new()) == NULL) { + if ((service = skipstone_message_service_new(link)) == NULL) { perror("skipstone_message_service_new()"); goto error_message_service_new; } - skipstone_message_service_register(service, 17, answer_phone_version_message, NULL); - skipstone_message_service_register(service, 32, answer_music_message, NULL); - skipstone_message_service_register(service, 33, answer_phone_message, NULL); + context.link = link; + + skipstone_message_service_register(service, 17, answer_phone_version_message, &context); + skipstone_message_service_register(service, 32, answer_music_message, &context); + skipstone_message_service_register(service, 33, answer_phone_message, &context); while (1) { - struct timeval timeout = { - .tv_sec = 0, - .tv_usec = 50000 - }; - - if (skipstone_message_service_next_event(service, link, &timeout) < 0) { - perror("skipstone_message_service_next_event()"); + if (skipstone_message_service_event_handle(service) < 0) { + perror("skipstone_message_service_event_handle()"); goto error_io; } diff --git a/include/skipstone/link.h b/include/skipstone/link.h index 8e05edd..a0fc539 100644 --- a/include/skipstone/link.h +++ b/include/skipstone/link.h @@ -6,14 +6,20 @@ typedef struct _skipstone_link skipstone_link; -skipstone_link *skipstone_link_open_serial(const char *device); +skipstone_link *skipstone_link_open(const char *device); int skipstone_link_close(skipstone_link *link); -int skipstone_link_send(skipstone_link *link, - void *buf, uint16_t size, uint16_t id); +int skipstone_link_fd(skipstone_link *link); -int skipstone_link_recv(skipstone_link *link, - void *buf, uint16_t *size, uint16_t *id, struct timeval *timeout); +ssize_t skipstone_link_send(skipstone_link *link, + void *buf, + uint16_t id, + size_t size); + +ssize_t skipstone_link_recv(skipstone_link *link, + void *buf, + uint16_t *id, + size_t size); #endif /* _SKIPSTONE_LINK_H */ diff --git a/include/skipstone/message.h b/include/skipstone/message.h index bb28bc2..6665df8 100644 --- a/include/skipstone/message.h +++ b/include/skipstone/message.h @@ -37,10 +37,12 @@ ssize_t skipstone_message_pack(void *message, size_t len, const char *template, ...); -skipstone_message_service *skipstone_message_service_new(); +skipstone_message_service *skipstone_message_service_new(skipstone_link *link); void skipstone_message_service_destroy(skipstone_message_service *service); +skipstone_link *skipstone_message_service_link(skipstone_message_service *service); + int skipstone_message_service_register(skipstone_message_service *service, uint16_t id, skipstone_message_handler *handler, @@ -49,12 +51,6 @@ int skipstone_message_service_register(skipstone_message_service *service, int skipstone_message_service_deregister(skipstone_message_service *service, uint16_t id); -int skipstone_message_service_queue(skipstone_message_service *service, - void *buf, - uint16_t size, - uint16_t id); - -int skipstone_message_service_next_event(skipstone_message_service *service, - skipstone_link *link, struct timeval *timeout); +int skipstone_message_service_event_handle(skipstone_message_service *service); #endif /* _SKIPSTONE_MESSAGE_H */ diff --git a/src/link.c b/src/link.c index 294992d..7baf366 100644 --- a/src/link.c +++ b/src/link.c @@ -7,68 +7,50 @@ #include #include #include +#include #include "util.h" #include #include -enum skipstone_link_type { - SKIPSTONE_WATCH_LINK_SERIAL = 1 -}; - struct _skipstone_link { - enum skipstone_link_type type; - - union { - struct { - int fd; - - struct termios attr_old, - attr_new; - } serial; - }; + int fd; + struct termios attrs; }; -skipstone_link *skipstone_link_open_serial(const char *device) { +skipstone_link *skipstone_link_open(const char *device) { skipstone_link *link; + struct termios t; if ((link = malloc(sizeof(*link))) == NULL) { goto error_malloc_link; } - link->type = SKIPSTONE_WATCH_LINK_SERIAL; - - if ((link->serial.fd = open(device, O_RDWR | O_NOCTTY)) < 0) { + if ((link->fd = open(device, O_RDWR | O_NOCTTY)) < 0) { goto error_open; } - if (tcgetattr(link->serial.fd, &link->serial.attr_old) < 0) { + if (tcgetattr(link->fd, &link->attrs) < 0) { goto error_io; } - memset(&link->serial.attr_new, 0, sizeof(struct termios)); + memcpy(&t, &link->attrs, sizeof(t)); - link->serial.attr_new.c_cflag = CS8 | HUPCL; - link->serial.attr_new.c_ispeed = B115200; - link->serial.attr_new.c_ospeed = B115200; - link->serial.attr_new.c_iflag = IGNPAR; - link->serial.attr_new.c_oflag = 0; - link->serial.attr_new.c_lflag = 0; - link->serial.attr_new.c_cc[VTIME] = 0; - link->serial.attr_new.c_cc[VMIN] = 1; + cfmakeraw(&t); + cfsetspeed(&t, B115200); - if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_new) < 0) { + if (tcsetattr(link->fd, TCSANOW, &t) < 0) { goto error_io; } - if (fcntl(link->serial.fd, F_SETFL, 0) < 0) { + if (fcntl(link->fd, F_SETFL, 0) < 0) { goto error_io; } return link; error_io: - close(link->serial.fd); + close(link->fd); error_open: free(link); @@ -77,108 +59,70 @@ error_malloc_link: return NULL; } -static int _watch_link_close_serial(skipstone_link *link) { - if (tcsetattr(link->serial.fd, TCSANOW, &link->serial.attr_old) < 0) { - goto error_io; - } - - return close(link->serial.fd); - -error_io: - return -1; -} - int skipstone_link_close(skipstone_link *link) { - switch (link->type) { - case SKIPSTONE_WATCH_LINK_SERIAL: { - return _watch_link_close_serial(link); - } - - default: break; + if (tcsetattr(link->fd, TCSANOW, &link->attrs) < 0) { + goto error_tcsetattr; } + return close(link->fd); + +error_tcsetattr: return -1; } -int skipstone_link_send(skipstone_link *link, void *buf, uint16_t size, uint16_t id) { +int skipstone_link_fd(skipstone_link *link) { + return link->fd; +} + +ssize_t skipstone_link_send(skipstone_link *link, + void *buf, + uint16_t id, + size_t size) { skipstone_message_header header; - ssize_t wrlen; - - size_t remaining = (size_t)size, - offset = 0; + ssize_t len; if (size > SKIPSTONE_MESSAGE_MAX_PAYLOAD) { + errno = EOVERFLOW; + goto error_toobig; } header.size = htobe16(size); header.id = htobe16(id); - if ((wrlen = write(link->serial.fd, &header, sizeof(header))) < 0) { + if ((len = write(link->fd, &header, sizeof(header))) < 0) { goto error_io; } - while (remaining) { - if ((wrlen = write(link->serial.fd, (uint8_t *)buf + offset, remaining)) < 0) { - goto error_io; - } - - remaining -= (size_t)wrlen; - offset += (size_t)wrlen; - } - - return 0; + return write(link->fd, buf, size); error_io: error_toobig: return -1; } -int skipstone_link_recv(skipstone_link *link, - void *buf, uint16_t *size, uint16_t *id, struct timeval *timeout) { +ssize_t skipstone_link_recv(skipstone_link *link, + void *buf, + uint16_t *id, + size_t size) { skipstone_message_header header; - ssize_t len_read; - size_t len_wanted, offset = 0; + size_t len; - fd_set fds; - int ready; - - FD_ZERO(&fds); - FD_SET(link->serial.fd, &fds); - - if ((ready = select(1 + link->serial.fd, &fds, NULL, NULL, timeout)) < 0) { + if (read(link->fd, &header, sizeof(header)) < 0) { goto error_io; } - if (ready == 0) { - return 0; - } + len = be16toh(header.size); + + if (len > size) { + errno = EOVERFLOW; - if (read(link->serial.fd, &header, sizeof(header)) < 0) { goto error_io; } - len_wanted = (size_t)be16toh(header.size); - - if (len_wanted > SKIPSTONE_MESSAGE_MAX_PAYLOAD) { - goto error_io; - } - - while (len_wanted) { - if ((len_read = read(link->serial.fd, (uint8_t *)buf + offset, len_wanted)) < 0) { - goto error_io; - } - - len_wanted -= len_read; - offset += len_read; - } - - *size = be16toh(header.size); - *id = be16toh(header.id); - - return 1; + return read(link->fd, buf, len); error_io: return -1; diff --git a/src/message.c b/src/message.c index f803f93..b39b3c6 100644 --- a/src/message.c +++ b/src/message.c @@ -16,8 +16,11 @@ struct endpoint { }; struct _skipstone_message_service { + skipstone_link *link; skipstone_map *endpoints; skipstone_queue *pending; + + size_t bufsz; void *buf; }; @@ -97,7 +100,7 @@ error_invalid_template: return -1; } -skipstone_message_service *skipstone_message_service_new() { +skipstone_message_service *skipstone_message_service_new(skipstone_link *link) { skipstone_message_service *service; if ((service = malloc(sizeof(*service))) == NULL) { @@ -116,6 +119,9 @@ skipstone_message_service *skipstone_message_service_new() { goto error_queue_new_pending; } + service->link = link; + service->bufsz = SKIPSTONE_MESSAGE_MAX_PAYLOAD; + return service; error_queue_new_pending: @@ -143,6 +149,10 @@ void skipstone_message_service_destroy(skipstone_message_service *service) { return; } +skipstone_link *skipstone_message_service_link(skipstone_message_service *service) { + return service->link; +} + int skipstone_message_service_register(skipstone_message_service *service, uint16_t id, skipstone_message_handler *handler, void *context) { struct endpoint *endpoint; @@ -166,58 +176,54 @@ int skipstone_message_service_deregister(skipstone_message_service *service, return skipstone_map_set((skipstone_map *)service, id, NULL); } -int skipstone_message_service_queue(skipstone_message_service *service, - void *buf, - uint16_t size, - uint16_t id) { - skipstone_message_header *message; - - if ((message = malloc(sizeof(*message) + size)) == NULL) { - goto error_malloc_message; - } - - message->size = size; - message->id = id; - - memcpy(message + 1, buf, size); - - if (skipstone_queue_add(service->pending, message) < 0) { - goto error_queue_add_pending; - } - - return 0; - -error_queue_add_pending: - free(message); - -error_malloc_message: - return -1; -} - -int skipstone_message_service_next_event(skipstone_message_service *service, - skipstone_link *link, - struct timeval *timeout) { - skipstone_message_header *message; +int skipstone_message_service_event_handle(skipstone_message_service *service) { struct endpoint *endpoint; - uint16_t size, id; - int ready; - if ((ready = skipstone_link_recv(link, service->buf, &size, &id, timeout)) < 0) { + fd_set fds; + + struct timeval timeout = { + .tv_sec = 0, + .tv_usec = 50000 + }; + + int fd = skipstone_link_fd(service->link), + ready; + + ssize_t len; + uint16_t id; + + memset(&fds, '\0', sizeof(fds)); + + FD_SET(fd, &fds); + + if ((ready = select(fd + 1, + &fds, + NULL, + NULL, + &timeout)) < 0) { + goto error_io; + } else if (ready == 0 || !FD_ISSET(fd, &fds)) { + goto done; + } + + if ((len = skipstone_link_recv(service->link, + service->buf, + &id, + service->bufsz)) < 0) { goto error_io; } - if (ready && (endpoint = skipstone_map_get(service->endpoints, id)) != NULL) { - if (endpoint->handler(service, service->buf, size, id, endpoint->context) < 0) { - goto error_io; - } - } - - while (skipstone_queue_remove(service->pending, (void **)&message)) { - if (skipstone_link_send(link, message + 1, message->size, message->id) < 0) { + if ((endpoint = skipstone_map_get(service->endpoints, id)) != NULL) { + if (endpoint->handler(service, + service->buf, + len, + id, + endpoint->context) < 0) { goto error_io; } } +done: return 0; error_io: diff --git a/src/system.c b/src/system.c index 02d7b29..2925e57 100644 --- a/src/system.c +++ b/src/system.c @@ -7,6 +7,8 @@ int skipstone_system_send_client_version(skipstone_message_service *service, uint32_t flags) { + skipstone_link *link = skipstone_message_service_link(service); + uint8_t message[25]; ssize_t len; @@ -25,16 +27,16 @@ int skipstone_system_send_client_version(skipstone_message_service *service, goto error_message_pack; } - if (skipstone_message_service_queue(service, - message, - (uint16_t)len, - SKIPSTONE_SYSTEM_ENDPOINT_PHONE_VERSION) < 0) { - goto error_message_service_queue; + if (skipstone_link_send(link, + message, + SKIPSTONE_SYSTEM_ENDPOINT_PHONE_VERSION, + len) < 0) { + goto error_link_send; } return 0; -error_message_service_queue: +error_link_send: error_message_pack: return -1; }