diff --git a/lib/include/chiaki/discoveryservice.h b/lib/include/chiaki/discoveryservice.h index 6510c29..8a67c9b 100644 --- a/lib/include/chiaki/discoveryservice.h +++ b/lib/include/chiaki/discoveryservice.h @@ -25,12 +25,32 @@ extern "C" { #endif +typedef struct chiaki_discovery_service_options_t +{ + size_t servers_max; + uint64_t ping_ms; + struct sockaddr *send_addr; + size_t send_addr_size; +} ChiakiDiscoveryServiceOptions; + +typedef struct chiaki_discovery_service_server_t +{ + uint64_t last_ping_index; +} ChiakiDiscoveryServiceServer; + typedef struct chiaki_discovery_service_t { + ChiakiLog *log; + ChiakiDiscoveryServiceOptions options; ChiakiDiscovery discovery; + uint64_t ping_index; + ChiakiDiscoveryServiceServer *servers; + size_t servers_count; + ChiakiThread thread; + ChiakiBoolPredCond stop_cond; } ChiakiDiscoveryService; -CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_service_init(ChiakiDiscoveryService *service, ChiakiLog *log, sa_family_t family); +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_service_init(ChiakiDiscoveryService *service, ChiakiDiscoveryServiceOptions *options, ChiakiLog *log); CHIAKI_EXPORT void chiaki_discovery_service_fini(ChiakiDiscoveryService *service); #ifdef __cplusplus diff --git a/lib/src/discoveryservice.c b/lib/src/discoveryservice.c index 1105580..21733cd 100644 --- a/lib/src/discoveryservice.c +++ b/lib/src/discoveryservice.c @@ -17,12 +17,81 @@ #include -CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_service_init(ChiakiDiscoveryService *service, ChiakiLog *log, sa_family_t family) +#include + +static void *discovery_service_thread_func(void *user); + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_service_init(ChiakiDiscoveryService *service, ChiakiDiscoveryServiceOptions *options, ChiakiLog *log) { - return chiaki_discovery_init(&service->discovery, log, family); + service->options = *options; + service->servers = calloc(service->options.servers_max, sizeof(ChiakiDiscoveryServiceServer)); + if(!service->servers) + return CHIAKI_ERR_MEMORY; + service->options.send_addr = malloc(service->options.send_addr_size); + if(!service->options.send_addr) + goto error_servers; + memcpy(service->options.send_addr, options->send_addr, service->options.send_addr_size); + service->servers_count = 0; + + ChiakiErrorCode err = chiaki_discovery_init(&service->discovery, log, service->options.send_addr->sa_family); + if(err != CHIAKI_ERR_SUCCESS) + goto error_servers; + + err = chiaki_bool_pred_cond_init(&service->stop_cond); + if(err != CHIAKI_ERR_SUCCESS) + goto error_discovery; + + err = chiaki_thread_create(&service->thread, discovery_service_thread_func, service); + if(err != CHIAKI_ERR_SUCCESS) + goto error_stop_cond; + + return CHIAKI_ERR_SUCCESS; +error_stop_cond: + chiaki_bool_pred_cond_fini(&service->stop_cond); +error_discovery: + chiaki_discovery_fini(&service->discovery); +error_send_addr: + free(service->options.send_addr); +error_servers: + free(service->servers); + return err; } CHIAKI_EXPORT void chiaki_discovery_service_fini(ChiakiDiscoveryService *service) { + chiaki_bool_pred_cond_signal(&service->stop_cond); + chiaki_thread_join(&service->thread, NULL); + chiaki_bool_pred_cond_fini(&service->stop_cond); chiaki_discovery_fini(&service->discovery); + free(service->servers); + free(service->options.send_addr); +} + +static void discovery_service_ping(ChiakiDiscoveryService *service); + +static void *discovery_service_thread_func(void *user) +{ + ChiakiDiscoveryService *service = user; + + ChiakiErrorCode err = chiaki_bool_pred_cond_lock(&service->stop_cond); + if(err != CHIAKI_ERR_SUCCESS) + return NULL; + + while(service->stop_cond.pred) + { + err = chiaki_bool_pred_cond_timedwait(&service->stop_cond, service->options.ping_ms); + if(err != CHIAKI_ERR_TIMEOUT) + break; + discovery_service_ping(service); + } + + chiaki_bool_pred_cond_unlock(&service->stop_cond); + return NULL; +} + +static void discovery_service_ping(ChiakiDiscoveryService *service) +{ + ChiakiDiscoveryPacket packet = { 0 }; + packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH; + chiaki_discovery_send(&service->discovery, &packet, service->options.send_addr, service->options.send_addr_size); }