END_TEST START_TEST(test_service_present) { qeo_mgmt_url_ctx_t ctx = NULL; char* message = NULL; const char *url = NULL; qeo_mgmt_client_ctx_t mg_ctx; fail_if(s_ctx == NULL); message = get_services_messages(0); qeo_log_i("Testing message <%s>", message); curl_easy_mock_return_data(message, false); ctx = qeo_mgmt_url_init(s_ctx); mg_ctx.url_ctx = ctx; mg_ctx.curl_ctx = s_ctx; fail_if(ctx == NULL ); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_ENROLL_DEVICE, &url) == QMGMTCLIENT_OK); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_CHECK_POLICY, &url) == QMGMTCLIENT_OK); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_GET_POLICY, &url) == QMGMTCLIENT_OK); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_REGISTER_FORWARDER, &url) == QMGMTCLIENT_OK); qeo_mgmt_url_cleanup(ctx); message = get_services_messages(1); qeo_log_i("Testing message <%s>", message); curl_easy_mock_return_data(message, false); ctx = qeo_mgmt_url_init(s_ctx); mg_ctx.url_ctx = ctx; fail_if(ctx == NULL ); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_ENROLL_DEVICE, &url) == QMGMTCLIENT_OK); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_CHECK_POLICY, &url) == QMGMTCLIENT_EBADSERVICE); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_GET_POLICY, &url) == QMGMTCLIENT_OK); fail_unless(qeo_mgmt_url_get(&mg_ctx, mock_qeo_mgmt_client_ssl_ctx_cb, NULL, "blabla", QMGMT_URL_REGISTER_FORWARDER, &url) == QMGMTCLIENT_OK); qeo_mgmt_url_cleanup(ctx); }
static void my_result_cb(qeo_mgmt_client_retcode_t result, void *cookie){ qeo_log_i("my_result_cb"); s_result = result; pthread_mutex_lock(&s_mutex); pthread_cond_broadcast(&s_cond); pthread_mutex_unlock(&s_mutex); }
void fwd_destroy(qeo_factory_t *factory) { lock(&factory->mutex); if (true == factory->fwd.rqst_pending) { /* Wait untill the fwd request is finished before continuing. */ qeo_log_i("waiting for the fwd request to finish."); pthread_cond_wait(&factory->fwd.wait_rqst_finished, &factory->mutex); } unlock(&factory->mutex); if (factory->flags.is_forwarder) { fwd_server_unregister(factory); if (FWD_STATE_ENABLED == factory->fwd.u.server.state) { if (QEO_OK != fwd_server_instance_remove(factory)) { qeo_log_e("failed to remove instance from forwarder topic"); } } if (NULL != factory->fwd.u.server.writer) { qeocore_writer_close(factory->fwd.u.server.writer); } } if (NULL != factory->fwd.reader) { qeocore_reader_close(factory->fwd.reader); } if (NULL != factory->fwd.timer) { DDS_Timer_delete(factory->fwd.timer); } pthread_cond_destroy(&factory->fwd.wait_rqst_finished); fwd_locator_destroy(factory); }
static qeo_retcode_t fwd_server_unregister(qeo_factory_t *factory) { qeo_retcode_t rc = QEO_OK; if (!qeocore_parameter_get_number("FWD_DISABLE_LOCATION_SERVICE")) { qeo_security_hndl qeo_sec = factory->qeo_sec; qeo_mgmt_client_retcode_t mgmt_rc = QMGMTCLIENT_EFAIL; qeo_mgmt_client_ctx_t *mgmt_client_ctx = NULL; int nrOfLocators = 0; do { if (QEO_OK != (rc = qeo_security_get_mgmt_client_ctx(qeo_sec, &mgmt_client_ctx))) { qeo_log_e("unregister_forwarder get security mgmt client failed (rc=%d)", rc); break; } /* Now register the forwarder. */ qeo_log_i("unregister the forwarder"); if ((mgmt_rc = qeo_mgmt_client_register_forwarder(mgmt_client_ctx, factory->qeo_id.url, NULL, nrOfLocators, ssl_ctx_cb, qeo_sec)) != QMGMTCLIENT_OK) { qeo_log_e("unregister forwarder failed (rc=%d)", mgmt_rc); rc = QEO_EFAIL; break; } } while (0); } return rc; }
/** * This function returns the platform specific storage location as a path. * If the path does not exist, it will create one with 0700 mode. * The caller is responsible for freeing the string returned in *path. * */ const char *get_default_device_storage_path(void) { if (NULL != _default_storage_path) { return _default_storage_path; } do { _default_storage_path = get_qeo_dir(); if (_default_storage_path == NULL){ qeo_log_e("Could not get qeo storage dir"); break; } if (access(_default_storage_path, R_OK | W_OK) != 0) { qeo_log_i("Creating storage directory (%s)", strerror(errno)); if (mkdir(_default_storage_path, 0700) != 0) { qeo_log_e("Failed to create storage directory %s", _default_storage_path); break; } } } while(0); return _default_storage_path; }
static qeo_retcode_t fwd_server_register(qeo_factory_t *factory) { qeo_retcode_t rc = QEO_OK; if (!qeocore_parameter_get_number("FWD_DISABLE_LOCATION_SERVICE")) { qeo_security_hndl qeo_sec = factory->qeo_sec; qeo_mgmt_client_retcode_t mgmt_rc = QMGMTCLIENT_EFAIL; qeo_mgmt_client_ctx_t *mgmt_client_ctx = NULL; qeo_mgmt_client_locator_t locator={QMGMT_LOCATORTYPE_TCPV4, factory->fwd.locator->address, factory->fwd.locator->port}; int nrOfLocators = 1; do { if ((rc = qeo_security_get_mgmt_client_ctx(qeo_sec, &mgmt_client_ctx)) != QEO_OK) { qeo_log_e("register_forwarder get security mgmt client failed (rc=%d)", rc); break; } /* Now register the forwarder. */ qeo_log_i("register the forwarder with locator address %s:port %d\n", locator.address, locator.port); if ((mgmt_rc = qeo_mgmt_client_register_forwarder(mgmt_client_ctx, factory->qeo_id.url, &locator, nrOfLocators, ssl_ctx_cb, qeo_sec)) != QMGMTCLIENT_OK) { qeo_log_e("register forwarder failed (rc=%d)", mgmt_rc); rc = QEO_EFAIL; break; } } while (0); } return rc; }
static char* get_qeo_dir(void) { char *qeo_dir = NULL; const struct passwd *pwd; do { qeo_dir = qeo_strdup_ret(getenv("QEO_STORAGE_DIR")); if (qeo_dir != NULL){ break; } pwd = getpwuid(getuid()); if (pwd == NULL || pwd->pw_dir == NULL) { qeo_log_e("Failed in getting the home directory"); break; } if (asprintf(&qeo_dir, "%s/%s", pwd->pw_dir, LINUX_STORAGE_DIR) == -1){ qeo_log_e("No mem"); break; } } while(0); qeo_log_i("Qeo directory is %s", qeo_dir); return (char*)qeo_dir; }
void qmc_clean_ongoing_thread(qeo_mgmt_client_ctx_t *ctx){ if (ctx->join_thread == true){ qeo_log_i("Waiting for worker thread to shut down"); if (pthread_join(ctx->worker_thread, NULL) != 0){ qeo_log_w("Failed to join worker thread"); } ctx->join_thread = false; } }
static qeo_retcode_t client_start_timer(qeo_factory_t *factory, bool reset) { qeo_retcode_t rc = QEO_OK; if (reset) { factory->fwd.timeout = qeocore_parameter_get_number("FWD_LOC_SRV_MIN_TIMEOUT"); } qeo_log_i("retry contacting location service after %ds", factory->fwd.timeout/1000); rc = ddsrc_to_qeorc(DDS_Timer_start(factory->fwd.timer, factory->fwd.timeout, (uintptr_t)factory, fwd_client_discovery_timeout)); return rc; }
static qeo_platform_device_id qeo_get_device_uuid(const char* platform_storage_filepath, const char* generator_path) { FILE* file = NULL; char* result_uuid = NULL; do { file = fopen(platform_storage_filepath, "r"); if (file != NULL ) { fclose(file); qeo_log_i("Fetching the existing UUID"); result_uuid = get_uuid(platform_storage_filepath); break; } qeo_log_i("Creating a new UUID, because %s not found", platform_storage_filepath); result_uuid = get_uuid(generator_path); if (NULL == result_uuid) { qeo_log_e("Failed to get UUID"); break; } FILE* fp = fopen(platform_storage_filepath, "w"); if (fp != NULL ) { qeo_log_i("Writing the new UUID"); fprintf(fp, "%s", result_uuid); fclose(fp); } else { qeo_log_e("Failed to open %s", platform_storage_filepath); } } while (0); qeo_platform_device_id res = char_to_struct(result_uuid); free(result_uuid); return res; }
/** This callback will be called for each forwarder in the list received from the management client. */ qeo_mgmt_client_retcode_t forwarder_cb(qeo_mgmt_client_forwarder_t* forwarder, void *cookie) { qeo_factory_t *factory = (qeo_factory_t *) cookie; qeo_mgmt_client_locator_t *locator = NULL; int i = 0; /* Get the IP address and port from the qeo_mgmt_client_forwarder_t info. */ if ((forwarder != NULL) && (forwarder->nrOfLocators > 0)) { qeo_log_d("received %d locators", forwarder->nrOfLocators); for (i = 0, locator = forwarder->locators; i < forwarder->nrOfLocators; i++, locator++) { qeo_log_d("locator %d", i); if (locator != NULL) { qeo_log_i("valid locator: %s:%d", locator->address, locator->port); if (factory->fwd.u.client.state == FWD_CLIENT_STATE_WAIT) { qeo_log_i("Going to use this forwarder"); flags_t flags = { .forwarding_enabled = true }; client_state_machine_eval(factory, CLIENT_EVENT_LOC_SRV_DATA_RECEIVED, locator, forwarder->deviceID, flags); } else { /* TODO: at the moment only one forwarder is taken into account. */ qeo_log_i("Going to ignore this forwarder as not the first in the list"); } break; }
/** This callback will be called for each forwarder in the list received from the management client. */ qeo_mgmt_client_retcode_t forwarder_cb(qeo_mgmt_client_forwarder_t* forwarder, void *cookie) { qeo_factory_t *factory = (qeo_factory_t *) cookie; qeo_mgmt_client_locator_t *locator = NULL; int i = 0; /* Get the IP address and port from the qeo_mgmt_client_forwarder_t info. */ if ((forwarder != NULL) && (forwarder->nrOfLocators > 0)) { qeo_log_i("received %d locators", forwarder->nrOfLocators); for (i = 0, locator = forwarder->locators; i < forwarder->nrOfLocators; i++, locator++) { qeo_log_i("locator %d", i); if (locator != NULL) { qeo_log_i("valid locator"); /* TODO: at the moment only one forwarder is taken into account. */ if (factory->fwd.locator == NULL) { client_state_machine_eval(factory, CLIENT_EVENT_LOC_SRV_DATA_RECEIVED, locator, forwarder->deviceID); } } } qeo_mgmt_client_free_forwarder(forwarder); } return QMGMTCLIENT_OK; }
static void list_forwarders_and_expect_error(qeo_mgmt_client_retcode_t expected, char* message, int line){ _forwarder_cb_helper helper = {0}; int i = 0; qeo_log_i("Testing message <%s> at line <%d>", message, line); curl_easy_mock_clean(); curl_easy_mock_return_data(message, true); curl_easy_mock_ignore_and_return(CURLE_OK, true, CURLE_OK, CURLE_OK, CURLE_OK); ck_assert_int_eq(qeo_mgmt_client_get_forwarders_sync(s_ctx, TEST_URL, my_fwd_cb, (void*)&helper, my_ssl_cb, (void*)COOKIE_MAGIC_NUMBER), expected); for (i = 0; i < helper.nrForwarders; ++i) { qeo_mgmt_client_free_forwarder(helper.forwarders[i]); } free(helper.forwarders); }
static void list_forwarders_and_expect_async(int nrForwarders, char* message, int line){ _forwarder_cb_helper helper = {0}; int i = 0; qeo_log_i("Testing message <%s> at line <%d> using async api", message, line); curl_easy_mock_clean(); curl_easy_mock_return_data(message, true); curl_easy_mock_ignore_and_return(CURLE_OK, true, CURLE_OK, CURLE_OK, CURLE_OK); ck_assert_int_eq(qeo_mgmt_client_get_forwarders(s_ctx, TEST_URL, my_fwd_cb, my_result_cb, (void*)&helper, my_ssl_cb, (void*)COOKIE_MAGIC_NUMBER), QMGMTCLIENT_OK); pthread_cond_wait(&s_cond, &s_mutex); ck_assert_int_eq(helper.nrForwarders, nrForwarders); for (i = 0; i < helper.nrForwarders; ++i) { qeo_mgmt_client_free_forwarder(helper.forwarders[i]); } free(helper.forwarders); }
qeo_retcode_t fwd_init_post_auth(qeo_factory_t *factory) { qeo_retcode_t rc = QEO_EFAIL; qeocore_type_t *type = NULL; /* this will eventually also take the factory lock, so postponing our lock */ type = qeocore_type_register_tsm(factory, org_qeo_system_Forwarder_type, org_qeo_system_Forwarder_type->name); if (NULL != type) { lock(&factory->mutex); if (factory->flags.is_forwarder) { factory->fwd.listener.on_data = fwd_server_on_data; factory->fwd.reader = qeocore_reader_open(factory, type, org_qeo_system_Forwarder_type->name, QEOCORE_EFLAG_STATE_UPDATE, &factory->fwd.listener, NULL); if (NULL != factory->fwd.reader) { factory->fwd.u.server.writer = qeocore_writer_open(factory, type, org_qeo_system_Forwarder_type->name, QEOCORE_EFLAG_STATE_DATA | QEOCORE_EFLAG_ENABLE, NULL, NULL); if (NULL != factory->fwd.u.server.writer) { factory->fwd.u.server.state = FWD_STATE_INIT; rc = fwd_server_state_machine_eval_ul(factory, -1, false, false); } } } else { factory->fwd.listener.on_data = fwd_client_on_data; factory->fwd.listener.userdata = (uintptr_t)factory; factory->fwd.reader = qeocore_reader_open(factory, type, org_qeo_system_Forwarder_type->name, QEOCORE_EFLAG_STATE_DATA, &factory->fwd.listener, NULL); /* note: reader construction failure is not fatal */ if (qeocore_parameter_get_number("FWD_DISABLE_FORWARDING")) { qeo_log_i("Disable forwarding"); factory->fwd.u.client.state = FWD_CLIENT_STATE_READY; } else { factory->fwd.u.client.state = FWD_CLIENT_STATE_INIT; client_state_machine_eval_ul(factory, CLIENT_EVENT_START, NULL, -1); } rc = QEO_OK; } unlock(&factory->mutex); qeocore_type_free(type); } return rc; }
static qeo_retcode_t fwd_get_list(qeo_factory_t *factory) { qeo_retcode_t rc = QEO_OK; if (!qeocore_parameter_get_number("FWD_DISABLE_LOCATION_SERVICE")) { qeo_security_hndl qeo_sec = factory->qeo_sec; qeo_mgmt_client_retcode_t mgmt_rc = QMGMTCLIENT_EFAIL; qeo_mgmt_client_ctx_t *mgmt_client_ctx = NULL; do { if ((rc = qeo_security_get_mgmt_client_ctx(qeo_sec, &mgmt_client_ctx)) != QEO_OK) { qeo_log_e("get_forwarders get security mgmt client failed (rc=%d)", rc); break; } /* Factory is already locked when calling this function. */ if (true == factory->fwd.rqst_pending) { /* Just break, we will retry later. */ qeo_log_i("no need to send request (previous fwd request still ongoing)"); break; } /* Now get the list of forwarders. */ factory->fwd.rqst_pending = true; mgmt_rc = qeo_mgmt_client_get_forwarders(mgmt_client_ctx, factory->qeo_id.url, forwarder_cb, result_cb, factory, ssl_ctx_cb, qeo_sec); if (mgmt_rc == QMGMTCLIENT_OK) { qeo_log_d("get_forwarders succeeded"); } else { factory->fwd.rqst_pending = false; /* result callback will not be called. */ if ((mgmt_rc == QMGMTCLIENT_ESSL) || (mgmt_rc == QMGMTCLIENT_ENOTALLOWED)) { qeo_log_e("get_forwarders failed (rc=%d), aborting", mgmt_rc); rc = QEO_EFAIL; break; } else { qeo_log_e("get_forwarders failed (rc=%d), ignoring", mgmt_rc); } } } while (0); } return rc; }
static int fwd_server_count_instances(const qeocore_reader_t *reader) { qeo_retcode_t rc = QEO_OK; qeocore_filter_t filter = { 0 }; qeocore_data_t *data; int cnt = 0; data = qeocore_reader_data_new(reader); if (NULL != data) { filter.instance_handle = DDS_HANDLE_NIL; while (1) { rc = qeocore_reader_read(reader, &filter, data); if (QEO_OK == rc) { filter.instance_handle = qeocore_data_get_instance_handle(data); cnt++; #ifdef DEBUG { const org_qeo_system_Forwarder_t *fwd = qeocore_data_get_data(data); qeo_log_d("forwarder %d : id=%" PRIx64 " -> %s", cnt, fwd->deviceId, (fwd->deviceId == reader->entity.factory->qeo_id.device_id ? "self" : "other")); } #endif qeocore_data_reset(data); continue; } else if (QEO_ENODATA == rc) { rc = QEO_OK; } /* QEO_ENODATA or error */ break; } qeocore_data_free(data); } if (QEO_OK == rc) { qeo_log_i("found %d local forwarders", cnt); } else { qeo_log_e("failed to read all local forwarders"); } return cnt; }
END_TEST START_TEST(test_error_json) { int id = 0; qeo_mgmt_url_ctx_t ctx = NULL; qeo_mgmt_client_ctx_t mg_ctx; char* message = NULL; const char *url = NULL; fail_if(s_ctx == NULL); while ((message = get_error_messages(id))){ id++; qeo_log_i("Testing message <%s>", message); curl_easy_mock_return_data(message, false); ctx = qeo_mgmt_url_init(s_ctx); mg_ctx.url_ctx = ctx; mg_ctx.curl_ctx = s_ctx; fail_if(ctx == NULL); fail_if(qeo_mgmt_url_get(&mg_ctx, NULL, NULL, "blabla", QMGMT_URL_ENROLL_DEVICE, &url) == QMGMTCLIENT_OK); qeo_mgmt_url_cleanup(ctx); } }
static void fwd_client_reconfig(qeo_factory_t *factory, qeo_mgmt_client_locator_t *locator, int64_t device_id) { qeo_retcode_t rc = QEO_OK; /* Configure the locator in the factory */ if (QEO_OK == fwd_locator_create(factory)) { if (QEO_OK == fwd_locator_update(factory, locator)) { char *tcp_server = calloc(1, strlen(locator->address) + 12); if (NULL != tcp_server) { snprintf(tcp_server, strlen(locator->address) + 12, "%s:%d", locator->address, locator->port); qeo_log_i("use forwarder %s", tcp_server); if ((rc = core_factory_set_tcp_server_no_lock(factory, tcp_server)) != QEO_OK) { qeo_log_e("set tcp server failed (rc=%d)", rc); } free(tcp_server); } } } /* Configure the device ID in the factory */ factory->fwd.device_id = device_id; }
END_TEST START_TEST(test_curl_upload_memory) { qmgmt_curl_data_helper helper={0}; size_t len = 0; helper.length = 0x8000; helper.data = calloc(helper.length, sizeof(char)); char *data = calloc(helper.length, sizeof(char)); memset(helper.data, 'a', helper.length-1); for (len = 0x1; len <= 0x4000; len*=2) { qeo_log_i("read buffer of size %d", len); ck_assert_int_eq(_read_from_memory_cb(data, sizeof(char), len, &helper), (sizeof(char) * len)); ck_assert_int_eq(strlen(data), len); } ck_assert_int_eq(helper.offset, 0x7FFF); ck_assert_int_eq(_read_from_memory_cb(data, sizeof(char), 1, &helper), (sizeof(char) * 1)); ck_assert_int_eq(helper.offset, 0x8000); ck_assert_int_eq(_read_from_memory_cb(data, sizeof(char), 1, &helper), 0); ck_assert_int_eq(helper.offset, 0x8000); }
qeo_mgmt_client_retcode_t ssl_ctx_cb(SSL_CTX *ctx, void *cookie) { qeo_mgmt_client_retcode_t client_ret = QMGMTCLIENT_EFAIL; qeo_retcode_t qeo_ret = QEO_OK; qeo_security_hndl qeo_sec = (qeo_security_hndl)cookie; EVP_PKEY *key = NULL; STACK_OF(X509) * certs = NULL; X509 *user_cert = NULL; X509 *cert = NULL; int i = 0; do { if (qeo_sec == NULL) { qeo_log_e("qeoSecPol == NULL"); break; } qeo_ret = qeo_security_get_credentials(qeo_sec, &key, &certs); if (qeo_ret != QEO_OK) { qeo_log_e("failed to get credentials"); break; } if (sk_X509_num(certs) <= 1) { qeo_log_e("not enough certificates in chain"); break; } user_cert = sk_X509_value(certs, 0); if (user_cert == NULL) { qeo_log_e("user_cert == NULL"); break; } if (!SSL_CTX_use_certificate(ctx, user_cert)) { qeo_log_e("SSL_CTX_use_certificate failed"); break; } if (!SSL_CTX_use_PrivateKey(ctx, key)) { qeo_log_e("SSL_CTX_use_PrivateKey failed"); break; } if (!SSL_CTX_check_private_key(ctx)) { qeo_log_e("SSL_CTX_check_private_key failed"); break; } security_util_configure_ssl_ctx(ctx); for (i = 1; i < sk_X509_num(certs); i++) { qeo_log_i("add cert: %d", i); cert = sk_X509_value(certs, i); if (cert == NULL) { qeo_log_e("cert == NULL"); break; } if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert)) { dump_openssl_error_stack("X509_STORE_add_cert failed"); break; } } client_ret = QMGMTCLIENT_OK; } while (0); return client_ret; }
/** * \pre This should be called with the factory lock taken. * * param[in] num_local Number of local forwarders discovered, -1 if not counted * param[in] timeout True if a timeout occurred */ static qeo_retcode_t fwd_server_state_machine_eval_ul(qeo_factory_t *factory, int num_local, bool timeout, bool public_ip_available) { qeo_retcode_t rc = QEO_OK; qeo_log_i("old state %s : local fwd count = %d, timeout = %s, public ip available = %s", server_state_to_str(factory->fwd.u.server.state), num_local, bool2str(timeout), bool2str(public_ip_available)); switch (factory->fwd.u.server.state) { case FWD_STATE_INIT: { /* done with initialization */ int timeout = qeocore_parameter_get_number("FWD_WAIT_LOCAL_FWD"); rc = ddsrc_to_qeorc(DDS_Timer_start(factory->fwd.timer, timeout, (uintptr_t)factory, fwd_server_timeout)); if (QEO_OK != rc) { qeo_log_e("failed to start forwarder timer"); break; } rc = qeocore_reader_enable(factory->fwd.reader); if (QEO_OK != rc) { qeo_log_e("failed to enable forwarder reader"); break; } factory->fwd.u.server.state = FWD_STATE_WAIT_LOCAL; break; } case FWD_STATE_WAIT_LOCAL: /* done waiting for local forwarder */ if (timeout) { /* no local forwarders found, try start forwarding ourselves */ factory->fwd.u.server.state = FWD_STATE_STARTING; unlock(&factory->mutex); factory->listener.on_fwdfactory_get_public_locator(factory); lock(&factory->mutex); } else if (num_local > 0) { /* local forwarder(s) available stop timer */ DDS_Timer_stop(factory->fwd.timer); factory->fwd.u.server.state = FWD_STATE_DISABLED; } break; case FWD_STATE_STARTING: /* done waiting for publicly available locator */ if (num_local > 0) { factory->fwd.u.server.state = FWD_STATE_DISABLED; } else if (public_ip_available) { if (QEO_OK == fwd_server_start_forwarding(factory)) { factory->fwd.u.server.state = FWD_STATE_ENABLED; } else { /* failed to start */ factory->fwd.u.server.state = FWD_STATE_DISABLED; } } break; case FWD_STATE_ENABLED: if (public_ip_available) { if (QEO_OK == fwd_server_start_forwarding(factory)) { factory->fwd.u.server.state = FWD_STATE_ENABLED; } else { /* failed to start */ factory->fwd.u.server.state = FWD_STATE_DISABLED; } } break; case FWD_STATE_DISABLED: if (0 == num_local) { /* no local forwarders anymore, try start forwarding ourselves */ factory->fwd.u.server.state = FWD_STATE_STARTING; unlock(&factory->mutex); factory->listener.on_fwdfactory_get_public_locator(factory); lock(&factory->mutex); } break; } qeo_log_i("new state %s", server_state_to_str(factory->fwd.u.server.state)); return rc; }
/* * Wrap data in PKCS#7 envelopes and base64-encode the result. * Data is PKCS#10 request in PKCSReq, or pkcs7_issuer_and_subject * structure in GetCertInitial and PKCS7_ISSUER_AND_SERIAL in * GetCert and GETCrl. */ int pkcs7_wrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info) { BIO *databio = NULL; BIO *encbio = NULL; BIO *pkcs7bio = NULL; BIO *memorybio = NULL; BIO *outbio = NULL; unsigned char *buffer = NULL; int len = 0; STACK_OF(X509) *recipients = NULL; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attributes; X509 *signercert = NULL; EVP_PKEY *signerkey = NULL; int ret = SCEP_PKISTATUS_P7; char *payload = NULL; int payload_len; /* Create a new sender nonce for all messages * XXXXXXXXXXXXXX should it be per transaction? */ s->sender_nonce_len = 16; free(s->sender_nonce);/* Clean up from previous runs */ s->sender_nonce = (char *)malloc(s->sender_nonce_len * sizeof(char)); RAND_bytes((unsigned char *) s->sender_nonce, s->sender_nonce_len); /* Prepare data payload */ switch (s->request_type) { case SCEP_REQUEST_PKCSREQ: /* * Set printable message type * We set this later as an autheticated attribute * "messageType". */ s->request_type_str = SCEP_REQUEST_PKCSREQ_STR; /* Signer cert */ signercert = s->signercert; signerkey = s->signerkey; /* Create inner PKCS#7 */ if (ctx->verbose){ qeo_log_i("creating inner PKCS#7"); } /* Read request in memory bio */ databio = BIO_new(BIO_s_mem()); if (i2d_X509_REQ_bio(databio, op_info->request) <= 0) { qeo_log_e("error writing certificate request in bio"); goto error; } (void)BIO_flush(databio); break; case SCEP_REQUEST_GETCERTINIT: /* Set printable message type */ s->request_type_str = SCEP_REQUEST_GETCERTINIT_STR; /* Signer cert */ signercert = s->signercert; signerkey = s->signerkey; /* Create inner PKCS#7 */ if (ctx->verbose){ qeo_log_i("creating inner PKCS#7"); } /* Read data in memory bio */ databio = BIO_new(BIO_s_mem()); if (i2d_pkcs7_issuer_and_subject_bio(databio, s->ias_getcertinit)) { qeo_log_e("error writing GetCertInitial data in bio"); goto error; } (void)BIO_flush(databio); break; } /* Below this is the common code for all request_type */ /* Read in the payload */ payload_len = BIO_get_mem_data(databio, &payload); if (ctx->verbose){ qeo_log_i("data payload size: %d bytes", payload_len); } /* Create encryption certificate stack */ if ((recipients = sk_X509_new(NULL) ) == NULL) { qeo_log_e("error creating certificate stack"); goto error; } if (sk_X509_push(recipients, op_info->racert) <= 0) { qeo_log_e("error adding recipient encryption certificate"); goto error; } /* Create BIO for encryption */ if ((encbio = BIO_new_mem_buf(payload, payload_len)) == NULL ) { qeo_log_e("error creating data bio"); goto error; } /* Encrypt */ if (!(p7enc = PKCS7_encrypt(recipients, encbio, ctx->enc_alg, PKCS7_BINARY))) { qeo_log_e("request payload encrypt failed"); goto error; } if (ctx->verbose){ qeo_log_i("successfully encrypted payload"); } /* Write encrypted data */ memorybio = BIO_new(BIO_s_mem()); if (i2d_PKCS7_bio(memorybio, p7enc) <= 0) { qeo_log_e("error writing encrypted data"); goto error; } (void)BIO_flush(memorybio); BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); len = BIO_get_mem_data(memorybio, &buffer); BIO_free(memorybio); memorybio=NULL; if (ctx->verbose){ qeo_log_i("envelope size: %d bytes", len); } if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, p7enc); } /* Create outer PKCS#7 */ if (ctx->verbose){ qeo_log_i("creating outer PKCS#7"); } s->request_p7 = PKCS7_new(); if (s->request_p7 == NULL ) { qeo_log_e("failed creating PKCS#7 for signing"); goto error; } if (!PKCS7_set_type(s->request_p7, NID_pkcs7_signed)) { qeo_log_e("failed setting PKCS#7 type"); goto error; } /* Add signer certificate and signature */ PKCS7_add_certificate(s->request_p7, signercert); if ((si = PKCS7_add_signature(s->request_p7, signercert, signerkey, ctx->sig_alg)) == NULL ) { qeo_log_e("error adding PKCS#7 signature"); goto error; } if (ctx->verbose){ qeo_log_i("signature added successfully"); } /* Set signed attributes */ if (ctx->verbose){ qeo_log_i("adding signed attributes"); } attributes = sk_X509_ATTRIBUTE_new_null(); add_attribute_string(attributes, ctx->nid_transId, s->transaction_id, ctx); add_attribute_string(attributes, ctx->nid_messageType, s->request_type_str, ctx); add_attribute_octet(attributes, ctx->nid_senderNonce, s->sender_nonce, s->sender_nonce_len, ctx); PKCS7_set_signed_attributes(si, attributes); sk_X509_ATTRIBUTE_pop_free(attributes, X509_ATTRIBUTE_free); /* Add contentType */ if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))) { qeo_log_e("error adding NID_pkcs9_contentType"); goto error; } /* Create new content */ if (!PKCS7_content_new(s->request_p7, NID_pkcs7_data)) { qeo_log_e("failed setting PKCS#7 content type"); goto error; } /* Write data */ pkcs7bio = PKCS7_dataInit(s->request_p7, NULL ); if (pkcs7bio == NULL ) { qeo_log_e("error opening bio for writing PKCS#7 data"); goto error; } if (len != BIO_write(pkcs7bio, buffer, len)) { qeo_log_e("error writing PKCS#7 data"); goto error; } if (ctx->verbose){ qeo_log_i("PKCS#7 data written successfully"); } /* Finalize PKCS#7 */ if (!PKCS7_dataFinal(s->request_p7, pkcs7bio)) { qeo_log_e("error finalizing outer PKCS#7"); goto error; } if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, s->request_p7); } /* base64-encode the data */ if (ctx->verbose){ qeo_log_i("applying base64 encoding"); } /* Create base64 filtering bio */ memorybio = BIO_new(BIO_s_mem()); outbio = BIO_push(BIO_new(BIO_f_base64()), memorybio); /* Copy PKCS#7 */ i2d_PKCS7_bio(outbio, s->request_p7); (void)BIO_flush(outbio); payload_len = BIO_get_mem_data(memorybio, &payload); s->request_payload = (char*) malloc(sizeof(char)*payload_len); if (!s->request_payload){ goto error; } s->request_len = payload_len; memcpy(s->request_payload, payload, s->request_len); if (ctx->verbose){ qeo_log_i("base64 encoded payload size: %d bytes", payload_len); } ret = 0; error: BIO_free(databio); BIO_free(encbio); BIO_free_all(pkcs7bio); BIO_free(memorybio); BIO_free(outbio); if (recipients != NULL){ sk_X509_free(recipients);/* Only free the stack, not the certificates */ } PKCS7_free(p7enc); OPENSSL_free(buffer); return ret; }
/* * Unwrap PKCS#7 data and decrypt if necessary */ int pkcs7_unwrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info, char* data, int datalen) { BIO *memorybio = NULL; BIO *outbio = NULL; BIO *pkcs7bio = NULL; int i, bytes, used; STACK_OF(PKCS7_SIGNER_INFO) *sk; PKCS7 *p7enc = NULL; PKCS7_SIGNER_INFO *si; STACK_OF(X509_ATTRIBUTE) *attribs; char *p = NULL; unsigned char buffer[1024]; X509 *recipientcert; EVP_PKEY *recipientkey; int ret = SCEP_PKISTATUS_P7; /* Create new memory BIO for outer PKCS#7 */ memorybio = BIO_new(BIO_s_mem()); /* Read in data */ if (ctx->verbose){ qeo_log_i("reading outer PKCS#7"); } if (BIO_write(memorybio, data, datalen) <= 0) { qeo_log_e("error reading PKCS#7 data"); goto error; } if (ctx->verbose){ qeo_log_i("PKCS#7 payload size: %d bytes", datalen); } s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL ); if (s->reply_p7 == NULL ) { qeo_log_e("error retrieving PKCS#7 data"); goto error; } if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, s->reply_p7); } /* Make sure this is a signed PKCS#7 */ if (!PKCS7_type_is_signed(s->reply_p7)) { qeo_log_e("PKCS#7 is not signed!"); goto error; } /* Create BIO for content data */ pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL ); if (pkcs7bio == NULL ) { qeo_log_e("cannot get PKCS#7 data"); goto error; } /* Copy enveloped data from PKCS#7 */ outbio = BIO_new(BIO_s_mem()); used = 0; for (;;) { bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer)); used += bytes; if (bytes <= 0) break; BIO_write(outbio, buffer, bytes); } (void)BIO_flush(outbio); if (ctx->verbose){ qeo_log_i("PKCS#7 contains %d bytes of enveloped data", used); } /* Get signer */ sk = PKCS7_get_signer_info(s->reply_p7); if (sk == NULL ) { qeo_log_e("cannot get signer info!"); goto error; } /* Verify signature */ if (ctx->verbose){ qeo_log_i("verifying signature"); } si = sk_PKCS7_SIGNER_INFO_value(sk, 0); if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, op_info->racert) <= 0) { qeo_log_e("error verifying signature"); goto error; } if (ctx->verbose){ qeo_log_i("signature ok"); } /* Get signed attributes */ if (ctx->verbose){ qeo_log_i("finding signed attributes"); } attribs = PKCS7_get_signed_attributes(si); if (attribs == NULL ) { qeo_log_e("no attributes found"); goto error; } /* Transaction id */ if ((get_signed_attribute(attribs, ctx->nid_transId, V_ASN1_PRINTABLESTRING, &p, ctx)) == 1) { qeo_log_e("cannot find transId"); goto error; } if (ctx->verbose){ qeo_log_i("reply transaction id: %s", p); } if (strncmp(s->transaction_id, p, strlen(p))) { qeo_log_e("transaction id mismatch"); goto error; } free(p); p=NULL; /* Message type, should be of type CertRep */ if (get_signed_attribute(attribs, ctx->nid_messageType, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find messageType"); goto error; } if (atoi(p) != 3) { qeo_log_e("wrong message type in reply"); goto error; } if (ctx->verbose){ qeo_log_i("reply message type is good"); } free(p); p=NULL; /* Recipient nonces: */ if (get_signed_attribute(attribs, ctx->nid_recipientNonce, V_ASN1_OCTET_STRING, &p, ctx) == 1) { qeo_log_e("cannot find recipientNonce"); goto error; } s->reply_recipient_nonce = p; p = NULL; if (ctx->verbose) { qeo_log_i("recipientNonce in reply"); } /* * Compare recipient nonce to original sender nonce * The draft says nothing about this, but it makes sense to me.. * XXXXXXXXXXXXXX check */ for (i = 0; i < 16; i++) { if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) { if (ctx->verbose) qeo_log_e("corrupted nonce received"); /* Instead of exit, break out */ break; } } /* Get pkiStatus */ if (get_signed_attribute(attribs, ctx->nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find pkiStatus"); /* This is a mandatory attribute.. */ goto error; } switch (atoi(p)) { case SCEP_PKISTATUS_SUCCESS: qeo_log_i("pkistatus: SUCCESS"); s->pki_status = SCEP_PKISTATUS_SUCCESS; break; case SCEP_PKISTATUS_FAILURE: qeo_log_i("pkistatus: FAILURE"); s->pki_status = SCEP_PKISTATUS_FAILURE; break; case SCEP_PKISTATUS_PENDING: qeo_log_i("pkistatus: PENDING"); s->pki_status = SCEP_PKISTATUS_PENDING; break; default: qeo_log_e("wrong pkistatus in reply"); goto error; } free(p); p=NULL; /* Get failInfo */ if (s->pki_status == SCEP_PKISTATUS_FAILURE) { if (get_signed_attribute(attribs, ctx->nid_failInfo, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) { qeo_log_e("cannot find failInfo"); goto error; } switch (atoi(p)) { case SCEP_FAILINFO_BADALG: s->fail_info = SCEP_FAILINFO_BADALG; qeo_log_i("reason: %s", SCEP_FAILINFO_BADALG_STR); break; case SCEP_FAILINFO_BADMSGCHK: s->fail_info = SCEP_FAILINFO_BADMSGCHK; qeo_log_i("reason: %s", SCEP_FAILINFO_BADMSGCHK_STR); break; case SCEP_FAILINFO_BADREQ: s->fail_info = SCEP_FAILINFO_BADREQ; qeo_log_i("reason: %s", SCEP_FAILINFO_BADREQ_STR); break; case SCEP_FAILINFO_BADTIME: s->fail_info = SCEP_FAILINFO_BADTIME; qeo_log_i("reason: %s", SCEP_FAILINFO_BADTIME_STR); break; case SCEP_FAILINFO_BADCERTID: s->fail_info = SCEP_FAILINFO_BADCERTID; qeo_log_i("reason: %s", SCEP_FAILINFO_BADCERTID_STR); break; default: qeo_log_e("wrong failInfo in " "reply"); goto error; } free(p); p=NULL; } /* If FAILURE or PENDING, we can return */ if (s->pki_status != SCEP_PKISTATUS_SUCCESS) { /* There shouldn't be any more data... */ if (ctx->verbose && (used != 0)) { qeo_log_e("illegal size of payload"); } return (0); } /* We got success and expect data */ if (used == 0) { qeo_log_e("illegal size of payload"); goto error; } /* Decrypt the inner PKCS#7 */ recipientcert = s->signercert; recipientkey = s->signerkey; if (ctx->verbose){ qeo_log_i("reading inner PKCS#7"); } p7enc = d2i_PKCS7_bio(outbio, NULL ); if (p7enc == NULL ) { qeo_log_e("cannot read inner PKCS#7"); goto error; } BIO_free(outbio);/* No longer need it */ outbio = NULL; if (ctx->debug) { qeo_log_i("printing PEM fomatted PKCS#7"); PEM_write_PKCS7(stdout, p7enc); } /* Decrypt the data */ outbio = BIO_new(BIO_s_mem()); if (ctx->verbose){ qeo_log_i("decrypting inner PKCS#7"); } if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) { qeo_log_e("error decrypting inner PKCS#7"); goto error; } (void)BIO_flush(outbio); /* Write decrypted data */ PKCS7_free(s->reply_p7); s->reply_p7 = d2i_PKCS7_bio(outbio, NULL ); ret = 0; error: free(p); BIO_free(outbio); BIO_free_all(pkcs7bio); BIO_free(memorybio); PKCS7_free(p7enc); return ret; }
qeo_mgmt_client_retcode_t qeo_mgmt_json_util_parseGetFWDMessage(const char* data, ssize_t length, qeo_mgmt_client_forwarder_cb callback, void* cookie) { json_error_t json_error = {0}; qeo_mgmt_client_retcode_t result = QMGMTCLIENT_EBADREPLY; json_t* message = json_loadb(data, length, JSON_REJECT_DUPLICATES, &json_error); qeo_mgmt_client_forwarder_t* fwd = NULL; do { json_t* fwdArray; ssize_t fwdSize; ssize_t i; if (message == NULL) { qeo_log_w("Failed to parse json message %s (%s:%d:%d)", json_error.text, json_error.source, json_error.line, json_error.column); qeo_log_w("Data = (%s)", data); //JSON parsing error break; } if (!json_is_object(message)) { qeo_log_w("invalid message received - top level is not a JSON object"); break; } fwdArray = json_object_get(message, "forwarders"); if (fwdArray == NULL || !json_is_array(fwdArray)) { qeo_log_w("root object did not contain a field 'forwarders' of type array (%p)", fwdArray); } fwdSize = json_array_size(fwdArray); qeo_log_i("Found an array of %d forwarder(s) in message\n", fwdSize); for (i = 0; i < fwdSize; i++) { qeo_mgmt_client_retcode_t cb_result; json_t* fwdObject = json_array_get(fwdArray, i); json_t* idString; json_t* locatorArray; ssize_t nrOfLocators; ssize_t j; if (!json_is_object(fwdObject)) { qeo_log_w("unexpected content in fwdArray - object expected"); break; } idString = json_object_get(fwdObject, "id"); if (idString == NULL || !json_is_string(idString)) { qeo_log_w("forwarder object did not contain a string field called 'id' (%p)", idString); break; } locatorArray = json_object_get(fwdObject, "locators"); if (locatorArray == NULL || !json_is_array(locatorArray)) { qeo_log_w("forwarder object did not contain an array field called 'nrOfLocators' (%p)", locatorArray); break; } nrOfLocators = json_array_size(locatorArray); qeo_log_i("found forwarder with id='%s' and %d locator(s)", json_string_value(idString), nrOfLocators); fwd = malloc(sizeof(qeo_mgmt_client_forwarder_t)); if (fwd == NULL) { qeo_log_w("fwd == NULL"); result = QMGMTCLIENT_EMEM; break; } fwd->nrOfLocators = nrOfLocators; fwd->locators = calloc(nrOfLocators, sizeof(qeo_mgmt_client_locator_t)); fwd->deviceID = qeo_mgmt_util_hex_to_int(json_string_value(idString)); if (fwd->deviceID == -1){ qeo_log_w("Invalid device id inside json message"); break; } if (fwd->locators == NULL) { qeo_log_w("fwd->locators == NULL"); result = QMGMTCLIENT_EMEM; break; } for (j = 0; j < nrOfLocators; j++) { json_t* endpointObj = json_array_get(locatorArray, j); json_t* typeString = json_object_get(endpointObj,"type"); json_t* addrString = json_object_get(endpointObj,"address"); json_t* portInt = json_object_get(endpointObj,"port"); if (portInt == NULL || !json_is_integer(portInt)) { qeo_log_w("locator object did not contain a integer field called 'port' (%p)", portInt); break; } if (addrString == NULL || !json_is_string(addrString)) { qeo_log_w("locator object did not contain a string field called 'address' (%p)", addrString); break; } if (typeString == NULL || !json_is_string(typeString)) { qeo_log_w("locator object did not contain a string field called 'type' (%p)", typeString); break; } qeo_log_i("locator object %d = {type = '%s', address = '%s', port = %d}", j, json_string_value(typeString), json_string_value(addrString), (int) json_integer_value(portInt)); //valid locator fwd->locators[j].port = (int) json_integer_value(portInt); if (fwd->locators[j].port < -1 || fwd->locators[j].port > 0xffff){ qeo_log_w("Invalid port inside locator"); break; } fwd->locators[j].type = _get_locator_type(json_string_value(typeString)); fwd->locators[j].address = strdup(json_string_value(addrString)); //check value; don't forget to free! if (fwd->locators[j].address == NULL) { qeo_log_w("locator->address == NULL"); break; } } if (j != nrOfLocators){ break; } cb_result = callback(fwd, cookie); fwd = NULL; //pointer is handed over; set it to NULL so we wont free it. if (cb_result != QMGMTCLIENT_OK) {//the callback reports an error abort. result = cb_result; break; } } if (i != fwdSize){ break; } qeo_log_i("Successfully walked JSON object tree..."); result = QMGMTCLIENT_OK; } while(0); if (message) { json_decref(message); } if (fwd) { //if an error occurred, then the 'fwd' is not freed. qeo_mgmt_client_free_forwarder(fwd); } return result; }
void notify_cb(DDS_DomainId_t domain_id, DDS_BuiltinTopicKey_t *client_key, DDS_ActivitiesClientState state) { qeo_log_i("Domain: %d, topic: %x-%x-%x, state: %d", domain_id, client_key->value[0], client_key->value[1], client_key->value[2], state); }
qeo_mgmt_client_retcode_t qeo_mgmt_curl_util_http_get_with_cb(qeo_mgmt_client_ctx_t* mg_ctx, const char* url, char *header, curl_write_callback data_cb, void *write_cookie){ qeo_mgmt_client_retcode_t ret = QMGMTCLIENT_EFAIL; struct curl_slist *chunk = (header != NULL)?curl_slist_append(NULL, header):NULL; long http_status = 0; char correlation_id[CURL_UTIL_CORRELATION_ID_MAX_SIZE]; curl_opt_helper opts[] = { { CURLOPT_WRITEFUNCTION, (void*) data_cb }, { CURLOPT_WRITEDATA, (void*)write_cookie}, { CURLOPT_FAILONERROR, (void*)1 }, { CURLOPT_HTTPHEADER, (void*) chunk}}; bool reset = false; do { CURL* ctx; if ((mg_ctx == NULL) || (mg_ctx->curl_ctx == NULL) || (url == NULL) || (data_cb == NULL)){ ret = QMGMTCLIENT_EINVAL; break; } ctx = mg_ctx->curl_ctx; if ((header != NULL) && (chunk == NULL)) { ret = QMGMTCLIENT_EMEM; break; } reset = true; if (CURLE_OK != qeo_mgmt_curl_util_set_opts(opts, sizeof(opts) / sizeof(curl_opt_helper), mg_ctx)) { ret = QMGMTCLIENT_EINVAL; break; } qeo_log_i("Start fetching data from <%s>", url); ret = qeo_mgmt_curl_util_perform(ctx, url, NULL); if (ret != QMGMTCLIENT_OK) { break; } if (curl_easy_getinfo(ctx, CURLINFO_RESPONSE_CODE, &http_status) == CURLE_OK) { if (http_status >= 400){ ret = qeo_mgmt_curl_util_translate_rc(CURLE_HTTP_RETURNED_ERROR); curl_util_log_http_error_description(ctx, correlation_id); break; } } qeo_log_i("Successfully downloaded data"); } while (0); if (reset == true){ /* Make sure we reset all configuration for next calls */ curl_easy_reset(mg_ctx->curl_ctx); } if (chunk != NULL){ curl_slist_free_all(chunk); } if (ret != QMGMTCLIENT_OK) { qeo_log_w("Failure getting %s",url); } return ret; }
static void client_state_machine_eval_ul(qeo_factory_t *factory, client_state_events_t event, qeo_mgmt_client_locator_t *locator, int64_t device_id) { qeo_log_i("received event %s in state %s", client_event_to_str(event), client_state_to_str(factory->fwd.u.client.state)); switch (factory->fwd.u.client.state) { case FWD_CLIENT_STATE_INIT: switch (event) { case CLIENT_EVENT_START: factory->fwd.device_id = -1; if (QEO_OK == client_start_timer(factory, 1)) { factory->fwd.u.client.state = FWD_CLIENT_STATE_WAIT; } if (QEO_OK != qeocore_reader_enable(factory->fwd.reader)) { qeo_log_e("error enabling forwarder topic reader"); } if (QEO_OK != fwd_get_list(factory)) { qeo_log_e("error requesting list of forwarders"); } break; default: qeo_log_e("unexpected event %s in state %s", client_event_to_str(event), client_state_to_str(factory->fwd.u.client.state)); break; } break; case FWD_CLIENT_STATE_WAIT: switch (event) { case CLIENT_EVENT_TIMEOUT: if (QEO_OK == client_start_timer(factory, 0)) { factory->fwd.u.client.state = FWD_CLIENT_STATE_WAIT; } if (QEO_OK != fwd_get_list(factory)) { qeo_log_e("error requesting list of forwarders"); } break; case CLIENT_EVENT_LOC_SRV_DATA_RECEIVED: fwd_client_reconfig(factory, locator, device_id); factory->fwd.u.client.state = FWD_CLIENT_STATE_WAIT_READER; break; case CLIENT_EVENT_FWD_DATA_RECEIVED: fwd_client_reconfig(factory, locator, device_id); DDS_Timer_stop(factory->fwd.timer); factory->fwd.u.client.state = FWD_CLIENT_STATE_READY; break; default: qeo_log_e("unexpected event %s in state %s", client_event_to_str(event), client_state_to_str(factory->fwd.u.client.state)); break; } break; case FWD_CLIENT_STATE_WAIT_READER: switch (event) { case CLIENT_EVENT_TIMEOUT: if (QEO_OK == client_start_timer(factory, 0)) { factory->fwd.u.client.state = FWD_CLIENT_STATE_WAIT; } fwd_locator_destroy(factory); factory->fwd.device_id = -1; if (QEO_OK != fwd_get_list(factory)) { qeo_log_e("error requesting list of forwarders"); } break; case CLIENT_EVENT_FWD_DATA_RECEIVED: DDS_Timer_stop(factory->fwd.timer); factory->fwd.u.client.state = FWD_CLIENT_STATE_READY; if (factory->fwd.device_id != device_id) { fwd_client_reconfig(factory, locator, device_id); } break; default: qeo_log_e("unexpected event %s in state %s", client_event_to_str(event), client_state_to_str(factory->fwd.u.client.state)); break; } break; case FWD_CLIENT_STATE_READY: switch (event) { case CLIENT_EVENT_FWD_DATA_REMOVED: if (QEO_OK == client_start_timer(factory, 1)) { factory->fwd.u.client.state = FWD_CLIENT_STATE_WAIT; } fwd_locator_destroy(factory); factory->fwd.device_id = -1; if (QEO_OK != fwd_get_list(factory)) { qeo_log_e("error requesting list of forwarders"); } break; default: qeo_log_e("unexpected event %s in state %s", client_event_to_str(event), client_state_to_str(factory->fwd.u.client.state)); break; } break; } qeo_log_i("new state %s", client_state_to_str(factory->fwd.u.client.state)); }