From 84f91c2e21c58e966bae67183df33f682d35d430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Wed, 7 Aug 2019 21:54:25 +0200 Subject: [PATCH] Parse Discovery Response Headers --- gui/src/discoverycmd.cpp | 1 + lib/include/chiaki/discovery.h | 18 ++++++++++++ lib/src/discovery.c | 52 +++++++++++++++++++++++++++++++++- lib/src/discoveryservice.c | 2 +- lib/src/http.c | 16 +++++++---- test/http.c | 27 +++++++++++++++--- 6 files changed, 104 insertions(+), 12 deletions(-) diff --git a/gui/src/discoverycmd.cpp b/gui/src/discoverycmd.cpp index 05516f6..2b2b6b2 100644 --- a/gui/src/discoverycmd.cpp +++ b/gui/src/discoverycmd.cpp @@ -30,6 +30,7 @@ int RunDiscoveryCmd(const QString &host) { ChiakiLog log; + chiaki_log_init(&log, CHIAKI_LOG_ALL, chiaki_log_cb_print, NULL); ChiakiDiscovery discovery; ChiakiErrorCode err = chiaki_discovery_init(&discovery, &log, AF_INET); // TODO: IPv6 diff --git a/lib/include/chiaki/discovery.h b/lib/include/chiaki/discovery.h index ef6862a..203a6fa 100644 --- a/lib/include/chiaki/discovery.h +++ b/lib/include/chiaki/discovery.h @@ -44,6 +44,24 @@ typedef struct chiaki_discovery_packet_t char *protocol_version; } ChiakiDiscoveryPacket; +typedef enum chiaki_discovery_host_state_t +{ + CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN, + CHIAKI_DISCOVERY_HOST_STATE_READY, + CHIAKI_DISCOVERY_HOST_STATE_STANDBY +} ChiakiDiscoveryHostState; + +typedef struct chiaki_discovery_srch_response_t +{ + ChiakiDiscoveryHostState state; + const char *system_version; + const char *device_discovery_protocol_version; + uint16_t host_request_port; + const char *host_name; + const char *host_type; + const char *host_id; +} ChiakiDiscoverySrchResponse; + CHIAKI_EXPORT int chiaki_discovery_packet_fmt(char *buf, size_t buf_size, ChiakiDiscoveryPacket *packet); typedef struct chiaki_discovery_t diff --git a/lib/src/discovery.c b/lib/src/discovery.c index b6246d0..9b64487 100644 --- a/lib/src/discovery.c +++ b/lib/src/discovery.c @@ -16,6 +16,7 @@ */ #include +#include #include #include @@ -38,6 +39,49 @@ CHIAKI_EXPORT int chiaki_discovery_packet_fmt(char *buf, size_t buf_size, Chiaki } } +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_srch_response_parse(ChiakiDiscoverySrchResponse *response, char *buf, size_t buf_size) +{ + ChiakiHttpResponse http_response; + ChiakiErrorCode err = chiaki_http_response_parse(&http_response, buf, buf_size); + if(err != CHIAKI_ERR_SUCCESS) + return err; + + memset(response, 0, sizeof(*response)); + + switch(http_response.code) + { + case 200: + response->state = CHIAKI_DISCOVERY_HOST_STATE_READY; + break; + case 620: + response->state = CHIAKI_DISCOVERY_HOST_STATE_STANDBY; + break; + default: + response->state = CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN; + break; + } + + for(ChiakiHttpHeader *header = http_response.headers; header; header=header->next) + { + printf("%s: %s\n", header->key, header->value); + if(strcmp(header->key, "system-version") == 0) + response->system_version = header->value; + else if(strcmp(header->key, "device-discovery-protocol-version") == 0) + response->device_discovery_protocol_version = header->value; + else if(strcmp(header->key, "host-request-port") == 0) + response->host_request_port = (uint16_t)strtoul(header->value, NULL, 0); + else if(strcmp(header->key, "host-name") == 0) + response->host_name = header->value; + else if(strcmp(header->key, "host-type") == 0) + response->host_type = header->value; + else if(strcmp(header->key, "host-id") == 0) + response->host_id = header->value; + } + + chiaki_http_response_fini(&http_response); + return CHIAKI_ERR_SUCCESS; +} + CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, ChiakiLog *log, sa_family_t family) { if(family != AF_INET && family != AF_INET6) @@ -177,7 +221,13 @@ static void *discovery_thread_func(void *user) buf[n] = '\00'; - CHIAKI_LOGD(discovery->log, "Discovery received:\n%s", buf); + CHIAKI_LOGV(discovery->log, "Discovery received:\n%s", buf); + chiaki_log_hexdump_raw(discovery->log, CHIAKI_LOG_VERBOSE, (const uint8_t *)buf, n); + + ChiakiDiscoverySrchResponse response; + err = chiaki_discovery_srch_response_parse(&response, buf, n); + if(err != CHIAKI_ERR_SUCCESS) + CHIAKI_LOGI(discovery->log, "Discovery Response invalid"); } return NULL; diff --git a/lib/src/discoveryservice.c b/lib/src/discoveryservice.c index 7ef467e..cefe347 100644 --- a/lib/src/discoveryservice.c +++ b/lib/src/discoveryservice.c @@ -35,7 +35,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_service_init(ChiakiDiscoveryServi ChiakiErrorCode err = chiaki_discovery_init(&service->discovery, log, service->options.send_addr->sa_family); if(err != CHIAKI_ERR_SUCCESS) - goto error_servers; + goto error_send_addr; err = chiaki_bool_pred_cond_init(&service->stop_cond); if(err != CHIAKI_ERR_SUCCESS) diff --git a/lib/src/http.c b/lib/src/http.c index 80516b8..94e9d9b 100644 --- a/lib/src/http.c +++ b/lib/src/http.c @@ -53,9 +53,10 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_http_header_parse(ChiakiHttpHeader **header FAIL(CHIAKI_ERR_INVALID_DATA); *buf = '\0'; buf++; - if(buf == end || *buf != ' ') + if(buf == end) FAIL(CHIAKI_ERR_INVALID_DATA); - buf++; + if(*buf == ' ') + buf++; if(buf == end) FAIL(CHIAKI_ERR_INVALID_DATA); value_ptr = buf; @@ -113,13 +114,16 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_http_response_parse(ChiakiHttpResponse *res buf += http_version_size; buf_size -= http_version_size; - char *line_end = memchr(buf, '\r', buf_size); + char *line_end = memchr(buf, '\n', buf_size); if(!line_end) return CHIAKI_ERR_INVALID_DATA; - size_t line_length = (line_end - buf) + 2; - if(buf_size <= line_length || line_end[1] != '\n') + size_t line_length = (line_end - buf) + 1; + if(buf_size <= line_length) return CHIAKI_ERR_INVALID_DATA; - *line_end = '\0'; + if(line_length > 1 && *(line_end - 1) == '\r') + *(line_end - 1) = '\0'; + else + *line_end = '\0'; char *endptr; response->code = (int)strtol(buf, &endptr, 10); diff --git a/test/http.c b/test/http.c index ee0eaf4..bb1cf9b 100644 --- a/test/http.c +++ b/test/http.c @@ -20,15 +20,25 @@ #include #include -static const char *response = +static char * const response_crlf = "HTTP/1.1 200 OK\r\n" "Content-type: text/html, text, plain\r\n" - "Ultimate Ability: Gamer\r\n" + "Ultimate Ability: Gamer\r\n" "\r\n"; +static char * const response_lf = + "HTTP/1.1 200 Ok\n" + "Content-type: text/html, text, plain\n" + "Ultimate Ability:Gamer\n"; + static void *test_http_response_parse_setup(const MunitParameter params[], void *user) { - return strdup(response); + const char *response = NULL; + if(strcmp(params[0].value, "crlf") == 0) + response = response_crlf; + else if(strcmp(params[0].value, "lf") == 0) + response = response_lf; + return response ? strdup(response) : NULL; } static void test_http_response_parse_teardown(void *fixture) @@ -61,6 +71,15 @@ static MunitResult test_http_response_parse(const MunitParameter params[], void return MUNIT_OK; } +static char *response_params[] = { + "crlf", "lf", NULL +}; + +static MunitParameterEnum params[] = { + { "line ending", response_params }, + { NULL, NULL } +}; + MunitTest tests_http[] = { { "/response_parse", @@ -68,7 +87,7 @@ MunitTest tests_http[] = { test_http_response_parse_setup, test_http_response_parse_teardown, MUNIT_TEST_OPTION_NONE, - NULL + params }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } }; \ No newline at end of file