in bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c [194:316]
celix_status_t remoteServiceAdmin_create(celix_bundle_context_t *context, remote_service_admin_t **admin) {
celix_status_t status = CELIX_SUCCESS;
*admin = calloc(1, sizeof(**admin));
if (!*admin) {
status = CELIX_ENOMEM;
} else {
(*admin)->context = context;
(*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
(*admin)->importedServices = celix_arrayList_create();
celixThreadRwlock_create(&(*admin)->exportedServicesLock, NULL);
celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
(*admin)->importedEndpointUrls = celix_stringHashMap_create();//Ignore ENOMEM for now and deal with it on other PRs in the future
(*admin)->loghelper = celix_logHelper_create(context, "celix_rsa_admin");
long port = celix_bundleContext_getPropertyAsLong(context, RSA_PORT_KEY, RSA_PORT_DEFAULT);
const char *ip = celix_bundleContext_getProperty(context, RSA_IP_KEY, RSA_IP_DEFAULT);
const char *interface = celix_bundleContext_getProperty(context, RSA_INTERFACE_KEY, NULL);
(*admin)->curlShareEnabled = celix_bundleContext_getPropertyAsBool(context, RSA_DFI_USE_CURL_SHARE_HANDLE, RSA_DFI_USE_CURL_SHARE_HANDLE_DEFAULT);
(*admin)->dynamicIpSupport = celix_bundleContext_getPropertyAsBool(context, CELIX_RSA_DFI_DYNAMIC_IP_SUPPORT, CELIX_RSA_DFI_DYNAMIC_IP_SUPPORT_DEFAULT);
char *detectedIp = NULL;
if ((interface != NULL) && (remoteServiceAdmin_getIpAddress((char*)interface, &detectedIp) != CELIX_SUCCESS)) {
celix_logHelper_log((*admin)->loghelper, CELIX_LOG_LEVEL_WARNING, "RSA: Could not retrieve IP address for interface %s", interface);
}
if (detectedIp != NULL) {
ip = detectedIp;
(*admin)->discoveryInterface = celix_utils_strdup(interface);
} else {
(*admin)->discoveryInterface = remoteServiceAdmin_getIFNameForIP(ip);
}
if (ip != NULL) {
celix_logHelper_log((*admin)->loghelper, CELIX_LOG_LEVEL_DEBUG, "RSA: Using %s for service annunciation", ip);
(*admin)->ip = strdup(ip);
}
if (detectedIp != NULL) {
free(detectedIp);
}
(*admin)->curlShare = curl_share_init();
curl_share_setopt((*admin)->curlShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
curl_share_setopt((*admin)->curlShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
curl_share_setopt((*admin)->curlShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt((*admin)->curlShare, CURLSHOPT_USERDATA, *admin);
curl_share_setopt((*admin)->curlShare, CURLSHOPT_LOCKFUNC, remoteServiceAdmin_curlshare_lock);
curl_share_setopt((*admin)->curlShare, CURLSHOPT_UNLOCKFUNC, remoteServiceAdmin_curlshare_unlock);
if(status == CELIX_SUCCESS && pthread_mutex_init(&(*admin)->curlMutexConnect, NULL) != 0) {
fprintf(stderr, "Could not initialize mutex connect\n");
status = EPERM;
}
if(status == CELIX_SUCCESS && pthread_mutex_init(&(*admin)->curlMutexCookie, NULL) != 0) {
fprintf(stderr, "Could not initialize mutex cookie\n");
status = EPERM;
}
if(status == CELIX_SUCCESS && pthread_mutex_init(&(*admin)->curlMutexDns, NULL) != 0) {
fprintf(stderr, "Could not initialize mutex dns\n");
status = EPERM;
}
remoteServiceAdmin_setupStopExportsThread(*admin);
// Prepare callbacks structure. We have only one callback, the rest are NULL.
struct mg_callbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.begin_request = remoteServiceAdmin_callback;
char newPort[10];
snprintf(newPort, 10, "%li", port);
unsigned int port_counter = 0;
bool bindToAllInterfaces = celix_bundleContext_getPropertyAsBool(context, CELIX_RSA_BIND_ON_ALL_INTERFACES, CELIX_RSA_BIND_ON_ALL_INTERFACES_DEFAULT);
do {
char *listeningPorts = NULL;
if (bindToAllInterfaces || (*admin)->dynamicIpSupport) {
asprintf(&listeningPorts,"0.0.0.0:%s", newPort);
} else {
asprintf(&listeningPorts,"%s:%s", (*admin)->ip, newPort);
}
const char *options[] = { "listening_ports", listeningPorts, "num_threads", "5", NULL};
(*admin)->ctx = mg_start(&callbacks, (*admin), options);
if ((*admin)->ctx != NULL) {
celix_logHelper_log((*admin)->loghelper, CELIX_LOG_LEVEL_INFO, "RSA: Start webserver: %s", listeningPorts);
(*admin)->port = strdup(newPort);
} else {
celix_logHelper_log((*admin)->loghelper, CELIX_LOG_LEVEL_ERROR, "Error while starting rsa server on port %s - retrying on port %li...", newPort, port + port_counter);
snprintf(newPort, 10, "%li", port + port_counter++);
}
free(listeningPorts);
} while (((*admin)->ctx == NULL) && (port_counter < MAX_NUMBER_OF_RESTARTS));
}
bool logCalls = celix_bundleContext_getPropertyAsBool(context, RSA_LOG_CALLS_KEY, RSA_LOG_CALLS_DEFAULT);
if (logCalls) {
const char *f = celix_bundleContext_getProperty(context, RSA_LOG_CALLS_FILE_KEY, RSA_LOG_CALLS_FILE_DEFAULT);
if (strncmp(f, "stdout", strlen("stdout")) == 0) {
(*admin)->logFile = stdout;
} else {
(*admin)->logFile = fopen(f, "w");
if ( (*admin)->logFile == NULL) {
celix_logHelper_log((*admin)->loghelper, CELIX_LOG_LEVEL_WARNING, "Error opening file '%s' for logging calls. %s", f, strerror(errno));
}
}
}
return status;
}