in bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c [460:578]
static int remoteServiceAdmin_callback(struct mg_connection *conn) {
int result = 1; // zero means: let civetweb handle it further, any non-zero value means it is handled by us...
export_registration_t *export = NULL;
celix_properties_t *metadata = NULL;
const struct mg_request_info *request_info = mg_get_request_info(conn);
if (request_info->request_uri != NULL) {
remote_service_admin_t *rsa = request_info->user_data;
if (strncmp(request_info->request_uri, "/service/", 9) == 0 && strcmp("POST", request_info->request_method) == 0) {
// uri = /services/myservice/call
const char *uri = request_info->request_uri;
// rest = myservice/call
const char *rest = uri+9;
char *interfaceStart = strchr(rest, '/');
int pos = interfaceStart - rest;
char service[pos+1];
strncpy(service, rest, pos);
service[pos] = '\0';
unsigned long serviceId = strtoul(service,NULL,10);
for (int i = 0; i < request_info->num_headers; i++) {
struct mg_header header = request_info->http_headers[i];
if (strncmp(header.name, "X-RSA-Metadata-", 15) == 0) {
if (metadata == NULL) {
metadata = celix_properties_create();
}
celix_properties_set(metadata, header.name + 15, header.value);
}
}
celixThreadRwlock_readLock(&rsa->exportedServicesLock);
//find endpoint
hash_map_iterator_pt iter = hashMapIterator_create(rsa->exportedServices);
while (hashMapIterator_hasNext(iter)) {
hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
celix_array_list_t *exports = hashMapEntry_getValue(entry);
int expIt = 0;
for (expIt = 0; expIt < celix_arrayList_size(exports); expIt++) {
export_registration_t *check = celix_arrayList_get(exports, expIt);
export_reference_t * ref = NULL;
exportRegistration_getExportReference(check, &ref);
endpoint_description_t * checkEndpoint = NULL;
exportReference_getExportedEndpoint(ref, &checkEndpoint);
if (serviceId == checkEndpoint->serviceId) {
export = check;
free(ref);
break;
}
free(ref);
}
}
hashMapIterator_destroy(iter);
if (export != NULL) {
exportRegistration_increaseUsage(export);
} else {
result = 0;
RSA_LOG_WARNING(rsa, "No export registration found for service id %lu", serviceId);
}
celixThreadRwlock_unlock(&rsa->exportedServicesLock);
}
if (export != NULL) {
uint64_t datalength = request_info->content_length;
char* data = malloc(datalength + 1);
mg_read(conn, data, datalength);
data[datalength] = '\0';
char *response = NULL;
int responceLength = 0;
int rc = exportRegistration_call(export, data, -1, &metadata, &response, &responceLength);
if (rc != CELIX_SUCCESS) {
RSA_LOG_ERROR(rsa, "Error trying to invoke remove service, got error %i\n", rc);
}
if (rc == CELIX_SUCCESS && response != NULL) {
mg_write(conn, data_response_headers, strlen(data_response_headers));
char *bufLoc = response;
size_t bytesLeft = strlen(response);
if (bytesLeft > INT_MAX) {
//NOTE arcording to civetweb mg_write, there is a limit on mg_write for INT_MAX.
RSA_LOG_WARNING(rsa, "nr of bytes to send for a remote call is > INT_MAX, this can lead to issues\n");
}
while (bytesLeft > 0) {
int send = mg_write(conn, bufLoc, strlen(bufLoc));
if (send > 0) {
bytesLeft -= send;
bufLoc += send;
} else {
RSA_LOG_ERROR(rsa, "Error sending response: %s", strerror(errno));
break;
}
}
free(response);
} else {
mg_write(conn, no_content_response_headers, strlen(no_content_response_headers));
}
result = 1;
free(data);
exportRegistration_decreaseUsage(export);
}
}
//free metadata
if(metadata != NULL) {
celix_properties_destroy(metadata);
}
return result;
}