#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum DISCOVERY_MAPPING { DISCOVERY_MAPPING_ID = 0, DISCOVERY_MAPPING_NAME = 1, DISCOVERY_MAPPING_COMMAND_PORT = 2, DISCOVERY_MAPPING_RELAY_COUNT = 3, }; int discovery_socket_open(uint16_t discovery_port) { struct addrinfo hints, *res; int fd, status; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; // use ipv4 hints.ai_socktype = SOCK_DGRAM; //set socket flag hints.ai_flags = AI_PASSIVE; // get my IP char* discovery_port_str = malloc(6 * sizeof(char)); sprintf(discovery_port_str, "%u", discovery_port); //get connection info for our computer if ((status = getaddrinfo(NULL, discovery_port_str, &hints, &res)) != 0) { LOG_FATAL("getaddrinfo: %s", gai_strerror(status)); freeaddrinfo(res); exit(EXIT_FAILURE); } //creating socket fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); int yes = 1; // lose the pesky "Address already in use" error message if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { LOG_FATAL("setsockopt: %s", strerror(errno)); freeaddrinfo(res); exit(EXIT_FAILURE); } if (bind(fd, res->ai_addr, res->ai_addrlen) == -1) { LOG_FATAL("bind: %s", strerror(errno)); freeaddrinfo(res); exit(EXIT_FAILURE); } freeaddrinfo(res); LOG_DEBUG("opened discovery socket on port %u", discovery_port); return fd; } void discovery_handle_discover(int fd, controller *cntrlr) { ssize_t bytes_transferred; uint16_t discovery_answer_port; struct sockaddr_in si_other; socklen_t slen = sizeof(si_other); if((bytes_transferred = recvfrom(fd, &discovery_answer_port, sizeof(discovery_answer_port), 0, (struct sockaddr *) &si_other, &slen)) <= 0) { LOG_ERROR("received invalid discovery from %s", inet_ntoa(si_other.sin_addr)); return; } LOG_DEBUG("received discovery from %s for port %d", inet_ntoa(si_other.sin_addr), discovery_answer_port); if(discovery_answer_port == 0) { LOG_ERROR("invalid port received"); return; } binn *map = binn_map(); binn_map_set_blob(map, DISCOVERY_MAPPING_ID, &cntrlr->id, sizeof(uuid_t)); binn_map_set_str(map, DISCOVERY_MAPPING_NAME, cntrlr->name); binn_map_set_uint32(map, DISCOVERY_MAPPING_COMMAND_PORT, cntrlr->command_port); binn_map_set_uint8(map, DISCOVERY_MAPPING_RELAY_COUNT, cntrlr->relay_count); void *payload = binn_ptr(map); size_t payload_size = binn_size(map); char discover_answer_port_str[6]; sprintf(discover_answer_port_str, "%d", discovery_answer_port); int fd_answer = helper_connect_server(inet_ntoa(si_other.sin_addr), discover_answer_port_str); LOG_DEBUG("size: %ld (%ld)", payload_size, sizeof(payload_size)); if((bytes_transferred = send(fd_answer, &payload_size, sizeof(payload_size), 0)) <= 0) { LOG_ERROR("error during sending"); binn_free(map); return; } if((bytes_transferred = send(fd_answer, payload, payload_size, 0)) <= 0) { LOG_ERROR("error during sending"); binn_free(map); return; } close(fd_answer); }