celix_status_t endpointDiscoveryServer_create()

in bundles/remote_services/discovery_common/src/endpoint_discovery_server.c [68:204]


celix_status_t endpointDiscoveryServer_create(discovery_t *discovery,
                                              celix_bundle_context_t *context,
                                              const char* defaultServerPath,
                                              const char* defaultServerPort,
                                              const char* defaultServerIp,
                                              endpoint_discovery_server_t **server) {
    celix_status_t status;

    const char *port = NULL;
    const char *ip = NULL;
    char *detectedIp = NULL;
    const char *path = NULL;
    const char *retries = NULL;

    int max_ep_num = MAX_NUMBER_OF_RESTARTS;

    *server = malloc(sizeof(struct endpoint_discovery_server));
    if (!*server) {
        return CELIX_ENOMEM;
    }

    (*server)->loghelper = &discovery->loghelper;
    (*server)->entries = hashMap_create(&utils_stringHash, NULL, &utils_stringEquals, NULL);
    if (!(*server)->entries) {
        return CELIX_ENOMEM;
    }

    status = celixThreadMutex_create(&(*server)->serverLock, NULL);
    if (status != CELIX_SUCCESS) {
        return CELIX_BUNDLE_EXCEPTION;
    }

    bundleContext_getProperty(context, DISCOVERY_SERVER_IP, &ip);
#ifndef ANDROID
    if (ip == NULL) {
        const char *interface = NULL;

        bundleContext_getProperty(context, DISCOVERY_SERVER_INTERFACE, &interface);
        if ((interface != NULL) && (endpointDiscoveryServer_getIpAddress((char*)interface, &detectedIp) != CELIX_SUCCESS)) {
            celix_logHelper_warning(*(*server)->loghelper, "Could not retrieve IP address for interface %s", interface);
        }

        if (detectedIp == NULL) {
            endpointDiscoveryServer_getIpAddress(NULL, &detectedIp);
        }

        ip = detectedIp;
    }
#endif

    if (ip != NULL) {
        celix_logHelper_info(*(*server)->loghelper, "Using %s for service annunciation", ip);
        (*server)->ip = strdup(ip);
    }
    else {
        celix_logHelper_warning(*(*server)->loghelper, "No IP address for service annunciation set. Using %s", defaultServerIp);
        (*server)->ip = strdup((char*) defaultServerIp);
    }

    if (detectedIp != NULL) {
        free(detectedIp);
    }

    bundleContext_getProperty(context, DISCOVERY_SERVER_PORT, &port);
    if (port == NULL) {
        port = defaultServerPort;
    }

    bundleContext_getProperty(context, DISCOVERY_SERVER_PATH, &path);
    if (path == NULL) {
        path = defaultServerPath;
    }

    bundleContext_getProperty(context, DISCOVERY_SERVER_MAX_EP, &retries);
    if (retries != NULL) {
        errno=0;
        max_ep_num = strtol(retries,NULL,10);
        if(errno!=0 || max_ep_num<=0){
            max_ep_num=MAX_NUMBER_OF_RESTARTS;
        }
    }

    (*server)->path = format_path(path);

    const struct mg_callbacks callbacks = {
            .begin_request = endpointDiscoveryServer_callback,
    };

    unsigned int port_counter = 0;
    char newPort[10];
    bool bindToAllInterfaces = celix_bundleContext_getPropertyAsBool(context, CELIX_DISCOVERY_BIND_ON_ALL_INTERFACES, CELIX_DISCOVERY_BIND_ON_ALL_INTERFACES_DEFAULT);

    do {
        char *listeningPorts = NULL;
        if (bindToAllInterfaces) {
            asprintf(&listeningPorts,"0.0.0.0:%s", port);
        } else {
            asprintf(&listeningPorts,"%s:%s", (*server)->ip, port);
        }

        const char *options[] = {
                "listening_ports", listeningPorts,
                "num_threads", DEFAULT_SERVER_THREADS,
                NULL
        };

        (*server)->ctx = mg_start(&callbacks, (*server), options);

        if ((*server)->ctx != NULL)
        {
            celix_logHelper_info(discovery->loghelper, "Starting discovery server on port %s...", listeningPorts);
        }
        else {
            errno = 0;
            char* endptr = (char*)port;
            long currentPort = strtol(port, &endptr, 10);

            if (*endptr || errno != 0) {
                currentPort = strtol(defaultServerPort, NULL, 10);
            }

            port_counter++;
            snprintf(&newPort[0], 10,  "%ld", (currentPort+1));

            celix_logHelper_warning(discovery->loghelper, "Error while starting discovery server on port %s - retrying on port %s...", port, newPort);
            port = newPort;

        }

        free(listeningPorts);

    } while(((*server)->ctx == NULL) && (port_counter < max_ep_num));

    (*server)->port = strdup(port);

    return status;
}