summaryrefslogtreecommitdiffstats
path: root/hicn-light/src/command_line/controller/hicnLightControl_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/command_line/controller/hicnLightControl_main.c')
-rwxr-xr-xhicn-light/src/command_line/controller/hicnLightControl_main.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/hicn-light/src/command_line/controller/hicnLightControl_main.c b/hicn-light/src/command_line/controller/hicnLightControl_main.c
new file mode 100755
index 000000000..4641bddf5
--- /dev/null
+++ b/hicn-light/src/command_line/controller/hicnLightControl_main.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <src/config.h>
+
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include <parc/assert/parc_Assert.h>
+#include <string.h>
+
+#include <parc/security/parc_IdentityFile.h>
+#include <parc/security/parc_Security.h>
+
+#include <parc/algol/parc_ArrayList.h>
+#include <parc/algol/parc_List.h>
+#include <parc/algol/parc_Memory.h>
+#include <parc/algol/parc_SafeMemory.h>
+
+#include <src/core/dispatcher.h>
+#include <src/core/forwarder.h>
+
+#include <errno.h>
+#include <src/config/controlRoot.h>
+#include <src/config/controlState.h>
+
+#include <src/utils/commands.h>
+
+size_t commandOutputLen = 0; // preserve the number of structs composing
+ // payload in case on not interactive call.
+
+// REMINDER: when a new_command is added, the following array has to be updated
+// with the sizeof(new_command). It allows to allocate the buffer for receiving
+// the payload of the DAEMON RESPONSE after the header has beed read. Each
+// command identifier (typedef enum command_id) corresponds to a position in the
+// following array.
+static int payloadLengthController[LAST_COMMAND_VALUE] = {
+ sizeof(add_listener_command),
+ sizeof(add_connection_command),
+ sizeof(list_connections_command), // needed when get response from FWD
+ sizeof(add_route_command),
+ sizeof(list_routes_command), // needed when get response from FWD
+ sizeof(remove_connection_command),
+ sizeof(remove_route_command),
+ sizeof(cache_store_command),
+ sizeof(cache_serve_command),
+ 0, // cache clear
+ sizeof(set_strategy_command),
+ sizeof(set_wldr_command),
+ sizeof(add_punting_command),
+ sizeof(list_listeners_command), // needed when get response from FWD
+ sizeof(mapme_activator_command),
+ sizeof(mapme_activator_command),
+ sizeof(mapme_timing_command),
+ sizeof(mapme_timing_command)};
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+typedef struct controller_main_state {
+ ControlState *controlState;
+} ControlMainState;
+
+static void _displayForwarderLogo(void){
+ const char cli_banner [] =
+ "\033[0;31m ____ ___ _ \033[0m __ _ __ _ __ __\n"
+ "\033[0;31m / __// _ \\ (_)___ \033[0m / / (_)____ ___ ____/ /(_)___ _ / / / /_\n"
+ "\033[0;31m / _/ / // /_ / // _ \\ \033[0m / _ \\ / // __// _ \\___/ // // _ `// _ \\/ __/\n"
+ "\033[0;31m/_/ /____/(_)/_/ \\___/ \033[0m/_//_//_/ \\__//_//_/ /_//_/ \\_, //_//_/\\__/\n"
+ " /___/ \n";
+ printf("%s", cli_banner);
+ printf("\n");
+}
+
+static void _displayUsage(char *programName) {
+ printf("Usage: %s -h\n", programName);
+ printf(
+ "hicn-light is the 1.0 source, which runs on each end system and as a "
+ "software source\n");
+ printf(
+ "on intermediate systems. controller is the program to configure the "
+ "source, daemon.\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("-h = This help screen\n");
+ printf(
+ "commands = configuration line to send to hicn-light (use 'help' "
+ "for list)\n");
+ printf("\n");
+}
+
+static int _parseArgs(int argc, char *argv[], char **keystorePath,
+ char **keystorePassword, PARCList *commandList) {
+ static struct option longFormOptions[] = {
+ {"help", no_argument, 0, 'h'},
+ {"keystore", required_argument, 0, 'k'},
+ {"password", required_argument, 0, 'p'},
+ {0, 0, 0, 0}};
+
+ int c;
+
+ while (1) {
+ // getopt_long stores the option index here.
+ int optionIndex = 0;
+
+ c = getopt_long(argc, argv, "hk:p:", longFormOptions, &optionIndex);
+
+ // Detect the end of the options.
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'k':
+ *keystorePath = optarg;
+ break;
+
+ case 'p':
+ *keystorePassword = optarg;
+ break;
+
+ case 'h':
+ default:
+ _displayUsage(argv[0]);
+ return 0;
+ }
+ }
+
+ // Any remaining parameters get put in the command list.
+ if (optind < argc) {
+ while (optind < argc) {
+ parcList_Add(commandList, argv[optind]);
+ optind++;
+ }
+ }
+
+ return 1;
+}
+
+struct iovec *_writeAndReadMessage(ControlState *state, struct iovec *msg) {
+ parcAssertNotNull(msg, "Parameter msg must be non-null");
+ int sockfd = controlState_GetSockfd(state);
+
+ // check if request has a payload
+ if (((header_control_message *)msg[0].iov_base)->length >
+ 0) { // command with payload
+ // write header + payload (compatibility issue: two write needed instead of
+ // the writev)
+ if (write(sockfd, msg[0].iov_base, msg[0].iov_len) < 0 ||
+ write(sockfd, msg[1].iov_base, msg[1].iov_len) < 0) {
+ printf("\nError while sending the Message: cannot write on socket \n");
+ exit(EXIT_FAILURE);
+ }
+ parcMemory_Deallocate(&msg[1].iov_base);
+ } else { // command without payload, e.g. 'list'
+ // write header only
+ if (write(sockfd, msg[0].iov_base, msg[0].iov_len) < 0) {
+ printf("\nError while sending the Message: cannot write on socket \n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ parcMemory_Deallocate(&msg[0].iov_base);
+
+ // ======= RECEIVE =======
+
+ header_control_message *headerResponse =
+ (header_control_message *)parcMemory_AllocateAndClear(
+ sizeof(header_control_message));
+ if (recv(sockfd, headerResponse, sizeof(header_control_message), 0) < 0) {
+ printf("\nError in Receiving the Message \n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (headerResponse->messageType < RESPONSE_LIGHT ||
+ headerResponse->messageType >= LAST_MSG_TYPE_VALUE) {
+ char *checkFinMsg = parcMemory_Reallocate(headerResponse, 32);
+ if (recv(sockfd, checkFinMsg, sizeof(checkFinMsg),
+ MSG_PEEK | MSG_DONTWAIT) == 0) {
+ // if recv returns zero, that means the connection has been closed:
+ close(sockfd);
+ printf("\nConnection terminated by the Daemon. Exiting... \n");
+ exit(EXIT_SUCCESS);
+ } else {
+ printf("\nError: Unrecognized message type received \n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ void *payloadResponse = NULL;
+
+ if ((commandOutputLen = headerResponse->length) > 0) {
+ payloadResponse = parcMemory_AllocateAndClear(
+ payloadLengthController[headerResponse->commandID] *
+ headerResponse->length);
+
+ if (recv(sockfd, payloadResponse,
+ payloadLengthController[headerResponse->commandID] *
+ headerResponse->length,
+ 0) < 0) {
+ printf("\nError in Receiving the Message \n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ struct iovec *response =
+ parcMemory_AllocateAndClear(sizeof(struct iovec) * 2);
+
+ response[0].iov_base = headerResponse;
+ response[0].iov_len = sizeof(header_control_message);
+ response[1].iov_base = payloadResponse;
+ response[1].iov_len = payloadLengthController[headerResponse->commandID] *
+ headerResponse->length;
+
+ return response;
+}
+
+int main(int argc, char *argv[]) {
+ _displayForwarderLogo();
+
+ if (argc == 2 && strcmp("-h", argv[1]) == 0) {
+ _displayUsage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+
+ PARCList *commands =
+ parcList(parcArrayList_Create(NULL), PARCArrayListAsPARCList);
+
+ if (!_parseArgs(argc, argv, NULL, NULL, commands)) {
+ parcList_Release(&commands);
+ exit(EXIT_FAILURE);
+ }
+
+ ControlMainState mainState;
+ mainState.controlState =
+ controlState_Create(&mainState, _writeAndReadMessage, true);
+
+ controlState_RegisterCommand(mainState.controlState,
+ controlRoot_HelpCreate(mainState.controlState));
+ controlState_RegisterCommand(mainState.controlState,
+ controlRoot_Create(mainState.controlState));
+
+ if (parcList_Size(commands) > 0) {
+ controlState_SetInteractiveFlag(mainState.controlState, false);
+ controlState_DispatchCommand(mainState.controlState, commands);
+ char **commandOutputMain =
+ controlState_GetCommandOutput(mainState.controlState);
+ if (commandOutputMain != NULL && commandOutputLen > 0) {
+ for (size_t j = 0; j < commandOutputLen; j++) {
+ printf("Output %zu: %s \n", j, commandOutputMain[j]);
+ }
+ controlState_ReleaseCommandOutput(mainState.controlState,
+ commandOutputMain, commandOutputLen);
+ }
+ // release
+
+ } else {
+ controlState_Interactive(mainState.controlState);
+ }
+
+ parcList_Release(&commands);
+
+ controlState_Destroy(&mainState.controlState);
+
+ return EXIT_SUCCESS;
+}