diff --git a/lib/include/chiaki/discovery.h b/lib/include/chiaki/discovery.h index 51835d7..745c5df 100644 --- a/lib/include/chiaki/discovery.h +++ b/lib/include/chiaki/discovery.h @@ -19,6 +19,10 @@ #define CHIAKI_DISCOVERY_H #include "common.h" +#include "thread.h" + +#include +#include #ifdef __cplusplus extern "C" { @@ -38,13 +42,26 @@ typedef struct chiaki_discovery_packet_t char *protocol_version; } ChiakiDiscoveryPacket; +CHIAKI_EXPORT int chiaki_discovery_packet_fmt(char *buf, size_t buf_size, ChiakiDiscoveryPacket *packet); + typedef struct chiaki_discovery_t { int socket; + struct sockaddr local_addr; } ChiakiDiscovery; -CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery); +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, sa_family_t family); CHIAKI_EXPORT void chiaki_discovery_fini(ChiakiDiscovery *discovery); +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_send(ChiakiDiscovery *discovery, ChiakiDiscoveryPacket *packet, struct sockaddr *addr, size_t addr_size); + +typedef struct chiaki_discovery_thread_t +{ + ChiakiDiscovery *discovery; + ChiakiThread thread; +} ChiakiDiscoveryThread; + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_thread_start(ChiakiDiscoveryThread *thread); +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_thread_stop(ChiakiDiscoveryThread *thread); #ifdef __cplusplus } diff --git a/lib/src/discovery.c b/lib/src/discovery.c index 09d7479..f08250a 100644 --- a/lib/src/discovery.c +++ b/lib/src/discovery.c @@ -17,26 +17,96 @@ #include +#include #include - -#include -#include +#include +#include -static const char *packet_srch_template = - "SRCH * HTTP/1.1\n" - "device-discovery-protocol-version:%s\n"; - - -CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery) +CHIAKI_EXPORT int chiaki_discovery_packet_fmt(char *buf, size_t buf_size, ChiakiDiscoveryPacket *packet) { + const char *version_str = packet->protocol_version ? packet->protocol_version : CHIAKI_DISCOVERY_PROTOCOL_VERSION; + switch(packet->cmd) + { + case CHIAKI_DISCOVERY_CMD_SRCH: + return snprintf(buf, buf_size, "SRCH * HTTP/1.1\ndevice-discovery-protocol-version:%s\n", + version_str); + default: + return -1; + } +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery, sa_family_t family) +{ + if(family != AF_INET && family != AF_INET6) + return CHIAKI_ERR_INVALID_DATA; + discovery->socket = socket(AF_INET, SOCK_DGRAM, 0); if(discovery->socket < 0) - return CHIAKI_ERR_UNKNOWN; + return CHIAKI_ERR_NETWORK; + + memset(&discovery->local_addr, 0, sizeof(discovery->local_addr)); + discovery->local_addr.sa_family = family; + if(family == AF_INET6) + { + struct in6_addr anyaddr = IN6ADDR_ANY_INIT; + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&discovery->local_addr; + addr->sin6_addr = anyaddr; + addr->sin6_port = htons(0); + } + else // AF_INET + { + struct sockaddr_in *addr = (struct sockaddr_in *)&discovery->local_addr; + addr->sin_addr.s_addr = htonl(INADDR_ANY); + addr->sin_port = htons(0); + } + + int r = bind(discovery->socket, &discovery->local_addr, sizeof(discovery->local_addr)); + if(r < 0) + { + close(discovery->socket); + return CHIAKI_ERR_NETWORK; + } + + const int broadcast = 1; + setsockopt(discovery->socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); + return CHIAKI_ERR_SUCCESS; } CHIAKI_EXPORT void chiaki_discovery_fini(ChiakiDiscovery *discovery) { close(discovery->socket); +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_send(ChiakiDiscovery *discovery, ChiakiDiscoveryPacket *packet, struct sockaddr *addr, size_t addr_size) +{ + if(addr->sa_family != discovery->local_addr.sa_family) + return CHIAKI_ERR_INVALID_DATA; + + char buf[512]; + int len = chiaki_discovery_packet_fmt(buf, sizeof(buf), packet); + if(len < 0) + return CHIAKI_ERR_UNKNOWN; + if((size_t)len >= sizeof(buf)) + return CHIAKI_ERR_BUF_TOO_SMALL; + + ssize_t rc = sendto(discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size); + if(rc < 0) + return CHIAKI_ERR_NETWORK; + + return CHIAKI_ERR_SUCCESS; +} + + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_thread_start(ChiakiDiscoveryThread *thread) +{ + // TODO + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_thread_stop(ChiakiDiscoveryThread *thread) +{ + // TODO + return CHIAKI_ERR_SUCCESS; } \ No newline at end of file