static void on_di_data_available(const qeocore_reader_t *reader, const qeocore_data_t *data, uintptr_t userdata){ qeo_retcode_t ret = QEO_OK; switch (qeocore_data_get_status(data)) { case QEOCORE_NOTIFY: qeo_log_d("Notify received"); break; case QEOCORE_DATA: qeo_log_d("Data received"); ret = qeo_walk_tsm_for_unmarshal(_types, org_qeo_system_DeviceInfo_type, data, (uintptr_t)&_rcvd_di, QEO_T2D_FLAGS_ALL, &_di_ucbs); break; case QEOCORE_NO_MORE_DATA: qeo_log_d("No more data received"); break; case QEOCORE_REMOVE: qeo_log_d("remove received"); break; case QEOCORE_ERROR: qeo_log_e("no callback called due to prior error"); break; } ck_assert_int_eq(ret, QEO_OK); }
X509_NAME* cnhelper_create_dn(const qeo_platform_device_info *info) { X509_NAME* dn = NULL; do { dn = X509_NAME_new(); if (dn) { char devicename[MAX_CN_LENGTH]; strncpy(devicename, info->userFriendlyName, sizeof(devicename)); if (devicename[sizeof(devicename)-1] != '\0'){ strncpy(&devicename[sizeof(devicename)-4], "...", 4); qeo_log_w("Device name exceeds the maximal allowed length of <%d> characters, cutting it off to <%s>.", sizeof(devicename)-1, devicename); } //TODO: now only the friendly name is forwarded to the server, in the future this needs to be extended if (!X509_NAME_add_entry_by_NID(dn, NID_commonName, MBSTRING_ASC, (unsigned char* ) devicename, -1, -1, 0)) { X509_NAME_free(dn); dn = NULL; break; } } qeo_log_d("created DN for device"); } while (0); return dn; }
curl_socket_t qmcu_socket_open_function(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr) { curl_socket_t sock = socket(addr->family, addr->socktype, addr->protocol); if (sock >= 0 && clientp) { qeo_mgmt_client_ctx_t* ctx = (qeo_mgmt_client_ctx_t*) clientp; if (_lock_fd_mutex(ctx)) { if (ctx->is_closed) { qeo_log_d("management thread shutdown requested, not creating socket"); close(sock); _unlock_fd_mutex(ctx); return CURL_SOCKET_BAD; } qeo_mgmt_fd_link_t* new_fd_link = malloc(sizeof(qeo_mgmt_fd_link_t)); if (new_fd_link) { new_fd_link->fd = sock; new_fd_link->next = NULL; if (ctx->fd_list == NULL) { ctx->fd_list = new_fd_link; } else { qeo_mgmt_fd_link_t* link = ctx->fd_list; while (link->next) { link = link->next; } link->next = new_fd_link; } } _unlock_fd_mutex(ctx); } } return sock; }
qeo_retcode_t qeo_json_get_device_id(char **json_device_id) { qeo_retcode_t ret = QEO_EINVAL; const qeo_platform_device_info *qeo_dev_info = NULL; json_t *device_id = NULL; char *upper = NULL; char *lower = NULL; do { if (NULL == json_device_id) { qeo_log_e("NULL == json_device_id"); break; } qeo_dev_info = qeo_platform_get_device_info(); if (qeo_dev_info == NULL) { qeo_log_d("qeo_platform_get_device_info failed"); ret = QEO_EFAIL; break; } device_id = json_object(); if (NULL == device_id) { qeo_log_e("unable to create new JSON object"); break; } if (-1 == asprintf(&upper, "%" PRId64, qeo_dev_info->qeoDeviceId.upperId)) { qeo_log_e("asprintf failed"); break; } if (-1 == asprintf(&lower, "%" PRId64, qeo_dev_info->qeoDeviceId.lowerId)) { qeo_log_e("asprintf failed"); break; } if (0 != json_object_set_new(device_id, "upper", json_string(upper))) { qeo_log_e("json_object_set_new failed"); break; } if (0 != json_object_set_new(device_id, "lower", json_string(lower))) { qeo_log_e("json_object_set_new failed"); break; } *json_device_id = json_dumps(device_id, JSON_INDENT(4)); ret = QEO_OK; } while (0); free(upper); free(lower); return ret; }
/** 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; }
/*####################################################################### # STATIC FUNCTION IMPLEMENTATION # ########################################################################*/ static int verify_server_cb(int ok, X509_STORE_CTX *ctx) { qeo_log_d("Verifying server, pre-verify is %s", ok ? "ok" : "not ok"); if (!ok) { X509 *err_cert = X509_STORE_CTX_get_current_cert(ctx); int err = X509_STORE_CTX_get_error(ctx); int depth = X509_STORE_CTX_get_error_depth(ctx); char subj[256], issuer[256]; X509_NAME_oneline(X509_get_subject_name(err_cert), subj, sizeof(subj)); X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), issuer, sizeof(issuer)); qeo_log_e("peer certificate verification failed: %s (@depth=%d, subject=%s, issuer=%s)", X509_verify_cert_error_string(err), depth, subj, issuer); } /* no extra verification needed */ return ok; }
void qeo_mgmt_curl_util_shutdown_connections(qeo_mgmt_client_ctx_t* ctx) { qeo_log_d("qeo_mgmt_curl_util_shutdown_connections"); if (ctx) { if (_lock_fd_mutex(ctx)) { qeo_mgmt_fd_link_t* fd_link = ctx->fd_list; while (fd_link) { shutdown(fd_link->fd, SHUT_RDWR); fd_link = fd_link->next; } ctx->is_closed = true; _unlock_fd_mutex(ctx); } else { qeo_log_e("Can't take mgmt ctx lock"); } } }
static qeo_retcode_t object_add_member(const qeo_factory_t *factory, qeocore_type_t *type, const char *member_name, json_t *member) { qeo_retcode_t result = QEO_EFAIL; qeocore_type_t *qeoType = NULL; qeocore_member_id_t qeo_member_id = QEOCORE_MEMBER_ID_DEFAULT; json_t *member_key = json_object_get(member, KEY_KEY); // optional => BOOLEAN json_t *member_id = json_object_get(member, KEY_ID); // optional => INTxx assert(factory != NULL); if (((NULL != member_key) && !json_is_boolean(member_key)) || ((NULL != member_id) && !json_is_integer(member_id)) || (NULL == member_name)) { // syntax error return QEO_EINVAL; } qeo_log_d("Processing %s", member_name); qeoType = build_member_type(factory, member); if (NULL == qeoType) { qeo_log_e("Could not build member_type"); return result; } bool is_key = (member_key && json_is_true(member_key)); do { result = qeocore_type_struct_add(type, // container qeoType, // new member to add member_name, // name of member &qeo_member_id, // member id is_key ? QEOCORE_FLAG_KEY : 0); // flag if (QEO_OK != result) { qeo_log_e("qeocore_type_struct_add failed for member %s", member_name); break; } qeocore_type_free(qeoType); // Modify the json member to add/update the qeo member id json_object_set_new(member, KEY_ID, json_integer(qeo_member_id)); } while (0); return result; }
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; }
static qeocore_type_t *build_object(const qeo_factory_t *factory, json_t *typedesc) { qeocore_type_t *qeoType = NULL; const char *name = NULL; json_t *value = NULL; qeo_retcode_t ret = QEO_EFAIL; bool iret = true; const char *topic = NULL; assert(typedesc != NULL); assert(factory != NULL); do { json_t *type_topic = json_object_get(typedesc, KEY_TOPIC); if ((NULL == type_topic) || !json_is_string(type_topic)) { qeo_log_e("Invalid type_topic (%p)", type_topic); return qeoType; } json_t *properties = json_object_get(typedesc, KEY_PROPERTIES); if ((NULL == properties) || !json_is_object(properties)) { qeo_log_e("Invalid properties (%p)", properties); return qeoType; } topic = json_string_value(type_topic); //Replace all "::" with ".", because there's a mismatch in topic definitions found in the TSM structs, with "." and the QDM topic definitions with "::" find_and_replace((char *) topic, "::", "."); qeoType = qeocore_type_struct_new(topic); if (qeoType == NULL) { qeo_log_e("qeocore_type_struct_new failed for topic:%s", topic); break; } qeo_log_d("Registered new struct with name %s", topic); void *iter = json_object_iter(properties); while (iter) { name = json_object_iter_key(iter); if (name == NULL) { qeo_log_e("name == NULL"); iret = false; break; } value = json_object_iter_value(iter); if (value == NULL) { qeo_log_e("value == NULL"); iret = false; break; } if (!json_is_object(value)) { qeo_log_e("no json object"); iret = false; break; } if (QEO_OK != object_add_member(factory, qeoType, name, value)) { qeo_log_e("object add member failed"); iret = false; break; } iter = json_object_iter_next(properties, iter); } if (true != iret) { break; } if (QEO_OK != qeocore_type_register(factory, qeoType, topic)) { qeo_log_e("failed to register type: %s", topic); } ret = QEO_OK; } while (0); if (ret != QEO_OK) { qeocore_type_free(qeoType); qeoType = NULL; } return qeoType; }
static qeo_mgmt_client_retcode_t qeo_mgmt_curl_util_https_put_with_cb(qeo_mgmt_client_ctx_t *mg_ctx, const char* url, char *header, qeo_mgmt_client_ssl_ctx_cb ssl_cb, void *ssl_cookie, curl_read_callback data_cb, void *read_cookie, intptr_t length) { curl_ssl_ctx_helper curlsslhelper = { ssl_cb, ssl_cookie }; char correlation_id[CURL_UTIL_CORRELATION_ID_MAX_SIZE]; qeo_mgmt_client_retcode_t ret = QMGMTCLIENT_EFAIL; struct curl_slist *chunk = (header != NULL)?curl_slist_append(NULL, header):NULL; long http_status = 0; curl_opt_helper opts[] = { { CURLOPT_INFILESIZE, (void*) length }, /* keep this at index 0; value is update in code */ { CURLOPT_UPLOAD, (void*)1 }, { CURLOPT_READFUNCTION, (void*) data_cb }, { CURLOPT_READDATA, (void*)read_cookie}, { CURLOPT_HTTPHEADER, (void*) chunk}, { CURLOPT_SSL_VERIFYPEER, (void*)0 }, { CURLOPT_SSL_CTX_FUNCTION, (void*)qeo_mgmt_curl_sslctx_cb }, { CURLOPT_SSL_CTX_DATA, (void*)&curlsslhelper }, }; bool reset = false; do { CURL* ctx; if ((mg_ctx == NULL ) || (mg_ctx->curl_ctx == NULL) || (url == NULL) || (ssl_cb == NULL) || (data_cb == NULL)){ ret = QMGMTCLIENT_EINVAL; break; } ctx = mg_ctx->curl_ctx; reset = true; if (CURLE_OK != qeo_mgmt_curl_util_set_opts(opts, sizeof(opts) / sizeof(curl_opt_helper), mg_ctx)) { ret = QMGMTCLIENT_EINVAL; break; } ret = qeo_mgmt_curl_util_perform(ctx, url, correlation_id); if (curl_easy_getinfo(ctx, CURLINFO_RESPONSE_CODE, &http_status) == CURLE_OK) { qeo_log_d("returned status code %ld", http_status); 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; } } } 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 in https_put_%s",url); } return ret; }