1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "ves_file_ready.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/http_client.h"
24 #include "utils/nts_utils.h"
29 #include <sysrepo/values.h>
31 #include "core/framework.h"
32 #include "core/session.h"
33 #include "core/xpath.h"
35 static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
36 static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location, int port);
37 static cJSON* ves_create_file_ready_fields(const char* file_location);
39 static sr_subscription_ctx_t *ves_file_ready_subscription = 0;
41 int ves_file_ready_feature_get_status(void) {
42 return (ves_file_ready_subscription != 0);
45 int ves_file_ready_feature_start(sr_session_ctx_t *current_session) {
46 assert(current_session);
49 if(ves_file_ready_subscription == 0) {
50 int rc = sr_rpc_subscribe(current_session, NTS_NF_RPC_FILE_READY_SCHEMA_XPATH, ves_file_ready_invoke_pm_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &ves_file_ready_subscription);
52 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
53 return NTS_ERR_FAILED;
63 int ves_file_ready_feature_stop(void) {
66 if(ves_file_ready_subscription) {
67 int rc = sr_unsubscribe(ves_file_ready_subscription);
69 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
70 return NTS_ERR_FAILED;
73 vsftp_daemon_deinit();
75 ves_file_ready_subscription = 0;
81 static int ves_file_ready_invoke_pm_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
82 int ssh_base_port = 0;
83 int tls_base_port = 0;
84 sr_session_ctx_t *current_session = 0;
86 int rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session);
88 log_error("could not start sysrepo session\n");
89 return NTS_ERR_FAILED;
92 nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(current_session);
93 if(mp == UNKNOWN_MAPPING) {
94 log_error("mount-point-addressing-method failed\n");
95 sr_session_stop(current_session);
96 return NTS_ERR_FAILED;
98 else if(mp == DOCKER_MAPPING) {
99 ssh_base_port = STANDARD_NETCONF_PORT;
100 tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections;
103 ssh_base_port = framework_environment.host.ssh_base_port;
104 tls_base_port = framework_environment.host.tls_base_port;
109 if((framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections) > 1) {
110 for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
111 int rc = ves_file_ready_send_message(current_session, input[0].data.string_val, port);
112 if(rc != NTS_ERR_OK) {
113 log_error("ves_file_ready_send_message failed\n");
118 for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
119 int rc = ves_file_ready_send_message(current_session, input[0].data.string_val, port);
120 if(rc != NTS_ERR_OK) {
121 log_error("ves_file_ready_send_message failed\n");
127 int rc = ves_file_ready_send_message(current_session, input[0].data.string_val, 0);
128 if(rc != NTS_ERR_OK) {
129 log_error("ves_file_ready_send_message failed\n");
134 rc = sr_session_stop(current_session);
135 if(rc != SR_ERR_OK) {
136 log_error("could not stop sysrepo session\n");
137 return NTS_ERR_FAILED;
141 rc = sr_new_values(*output_cnt, output);
142 if(SR_ERR_OK != rc) {
146 rc = sr_val_set_xpath(output[0], NTS_NF_RPC_FILE_READY_SCHEMA_XPATH"/status");
147 if(SR_ERR_OK != rc) {
152 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
155 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
161 static int ves_file_ready_send_message(sr_session_ctx_t *session, const char *file_location, int port) {
163 assert(file_location);
166 static int sequence_number = 0;
168 cJSON *post_data_json = cJSON_CreateObject();
169 if(post_data_json == 0) {
170 log_error("could not create cJSON object\n");
171 return NTS_ERR_FAILED;
174 cJSON *event = cJSON_CreateObject();
176 log_error("could not create cJSON object\n");
177 cJSON_Delete(post_data_json);
178 return NTS_ERR_FAILED;
181 if(cJSON_AddItemToObject(post_data_json, "event", event) == 0) {
182 log_error("cJSON_AddItemToObject failed\n");
183 cJSON_Delete(post_data_json);
184 return NTS_ERR_FAILED;
187 cJSON *common_event_header = ves_create_common_event_header("notification", "Notification-gnb_Nokia-FileReady", framework_environment.settings.hostname, port, "Normal", sequence_number++);
188 if(common_event_header == 0) {
189 log_error("could not create cJSON object\n");
190 cJSON_Delete(post_data_json);
191 return NTS_ERR_FAILED;
194 if(cJSON_AddItemToObject(event, "commonEventHeader", common_event_header) == 0) {
195 log_error("cJSON_AddItemToObject failed\n");
196 cJSON_Delete(post_data_json);
197 return NTS_ERR_FAILED;
200 cJSON *file_ready_fields = ves_create_file_ready_fields(file_location);
201 if(file_ready_fields == 0) {
202 log_error("could not create cJSON object\n");
203 cJSON_Delete(post_data_json);
204 return NTS_ERR_FAILED;
207 if(cJSON_AddItemToObject(event, "notificationFields", file_ready_fields) == 0) {
208 log_error("cJSON_AddItemToObject failed\n");
209 cJSON_Delete(post_data_json);
210 return NTS_ERR_FAILED;
213 char *post_data = cJSON_PrintUnformatted(post_data_json);
214 cJSON_Delete(post_data_json);
216 log_error("cJSON_PrintUnformatted failed\n");
217 return NTS_ERR_FAILED;
221 ves_details_t *ves_details = ves_endpoint_details_get(session);
223 log_error("ves_endpoint_details_get failed\n");
225 return NTS_ERR_FAILED;
228 rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
229 ves_details_free(ves_details);
232 if(rc != NTS_ERR_OK) {
233 log_error("http_request failed\n");
234 return NTS_ERR_FAILED;
240 static cJSON* ves_create_file_ready_fields(const char* file_location) {
241 assert(file_location);
243 cJSON *file_ready_fields = cJSON_CreateObject();
244 if(file_ready_fields == 0) {
245 log_error("could not create JSON object\n");
249 if(cJSON_AddStringToObject(file_ready_fields, "changeIdentifier", "PM_MEAS_FILES") == 0) {
250 log_error("cJSON_AddStringToObject failed\n");
251 cJSON_Delete(file_ready_fields);
255 if(cJSON_AddStringToObject(file_ready_fields, "changeType", "FileReady") == 0) {
256 log_error("cJSON_AddStringToObject failed\n");
257 cJSON_Delete(file_ready_fields);
261 if(cJSON_AddStringToObject(file_ready_fields, "notificationFieldsVersion", "2.0") == 0) {
262 log_error("cJSON_AddStringToObject failed\n");
263 cJSON_Delete(file_ready_fields);
267 cJSON *array_of_named_hash_map = cJSON_CreateArray();
268 if(array_of_named_hash_map == 0) {
269 log_error("could not create JSON object\n");
270 cJSON_Delete(file_ready_fields);
274 if(cJSON_AddItemToObject(file_ready_fields, "arrayOfNamedHashMap", array_of_named_hash_map) == 0) {
275 log_error("cJSON_AddStringToObject failed\n");
276 cJSON_Delete(file_ready_fields);
280 cJSON *additional_fields_entry = cJSON_CreateObject();
281 if(additional_fields_entry == 0) {
282 log_error("could not create JSON object\n");
283 cJSON_Delete(file_ready_fields);
287 char *filename = strrchr(file_location, '/');
290 if(cJSON_AddStringToObject(additional_fields_entry, "name", "dummy_file.tar.gz") == 0) {
291 log_error("cJSON_AddStringToObject failed\n");
292 cJSON_Delete(file_ready_fields);
297 if(cJSON_AddStringToObject(additional_fields_entry, "name", filename + 1) == 0) {
298 log_error("cJSON_AddStringToObject failed\n");
299 cJSON_Delete(file_ready_fields);
304 cJSON *hash_map = cJSON_CreateObject();
306 log_error("could not create JSON object\n");
307 cJSON_Delete(file_ready_fields);
311 if(cJSON_AddItemToObject(additional_fields_entry, "hashMap", hash_map) == 0) {
312 log_error("cJSON_AddStringToObject failed\n");
313 cJSON_Delete(file_ready_fields);
317 if(cJSON_AddStringToObject(hash_map, "location", file_location) == 0) {
318 log_error("cJSON_AddStringToObject failed\n");
319 cJSON_Delete(file_ready_fields);
323 if(cJSON_AddStringToObject(hash_map, "compression", "gzip") == 0) {
324 log_error("cJSON_AddStringToObject failed\n");
325 cJSON_Delete(file_ready_fields);
329 if(cJSON_AddStringToObject(hash_map, "fileFormatType", "org.3GPP.32.435#measCollec") == 0) {
330 log_error("cJSON_AddStringToObject failed\n");
331 cJSON_Delete(file_ready_fields);
335 if(cJSON_AddStringToObject(hash_map, "fileFormatVersion", "V5") == 0) {
336 log_error("cJSON_AddStringToObject failed\n");
337 cJSON_Delete(file_ready_fields);
341 if(cJSON_AddItemToArray(array_of_named_hash_map, additional_fields_entry) == 0) {
342 log_error("cJSON_AddStringToObject failed\n");
343 cJSON_Delete(file_ready_fields);
347 return file_ready_fields;