static int remoteServiceAdmin_callback()

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;
}