aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/command_line
diff options
context:
space:
mode:
authorLuca Muscariello <lumuscar+fdio@cisco.com>2019-01-17 13:47:57 +0100
committerLuca Muscariello <lumuscar+fdio@cisco.com>2019-01-17 16:32:51 +0100
commitbac3da61644515f05663789b122554dc77549286 (patch)
tree898210bc8e70371d77de7d446a26c5dd4fd1165a /hicn-light/src/command_line
parentd5165246787301d0f13b646fda5e8a8567aef5ac (diff)
This is the first commit of the hicn projectv19.01
Change-Id: I6f2544ad9b9f8891c88cc4bcce3cf19bd3cc863f Signed-off-by: Luca Muscariello <lumuscar+fdio@cisco.com>
Diffstat (limited to 'hicn-light/src/command_line')
-rwxr-xr-xhicn-light/src/command_line/CMakeLists.txt2
-rwxr-xr-xhicn-light/src/command_line/controller/CMakeLists.txt23
-rwxr-xr-xhicn-light/src/command_line/controller/hicnLightControl_main.c284
-rwxr-xr-xhicn-light/src/command_line/daemon/CMakeLists.txt23
-rwxr-xr-xhicn-light/src/command_line/daemon/hicnLightDaemon_main.c336
5 files changed, 668 insertions, 0 deletions
diff --git a/hicn-light/src/command_line/CMakeLists.txt b/hicn-light/src/command_line/CMakeLists.txt
new file mode 100755
index 000000000..16c23dc5c
--- /dev/null
+++ b/hicn-light/src/command_line/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(controller)
+add_subdirectory(daemon)
diff --git a/hicn-light/src/command_line/controller/CMakeLists.txt b/hicn-light/src/command_line/controller/CMakeLists.txt
new file mode 100755
index 000000000..b53e610a1
--- /dev/null
+++ b/hicn-light/src/command_line/controller/CMakeLists.txt
@@ -0,0 +1,23 @@
+# 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.
+
+list(APPEND CONTROLLER_SRC
+ hicnLightControl_main.c
+)
+
+build_executable(${HICN_LIGHT_CONTROL}
+ SOURCES ${CONTROLLER_SRC}
+ LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
+ DEPENDS hicn-light
+ COMPONENT hicn-light
+)
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;
+}
diff --git a/hicn-light/src/command_line/daemon/CMakeLists.txt b/hicn-light/src/command_line/daemon/CMakeLists.txt
new file mode 100755
index 000000000..fd6cc9310
--- /dev/null
+++ b/hicn-light/src/command_line/daemon/CMakeLists.txt
@@ -0,0 +1,23 @@
+# 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.
+
+list(APPEND DAEMON_SRC
+ hicnLightDaemon_main.c
+)
+
+build_executable(${HICN_LIGHT_DAEMON}
+ SOURCES ${DAEMON_SRC}
+ LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
+ DEPENDS hicn-light
+ COMPONENT hicn-light
+) \ No newline at end of file
diff --git a/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c b/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c
new file mode 100755
index 000000000..f6d521711
--- /dev/null
+++ b/hicn-light/src/command_line/daemon/hicnLightDaemon_main.c
@@ -0,0 +1,336 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <src/config.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <parc/algol/parc_FileOutputStream.h>
+#include <parc/logging/parc_LogLevel.h>
+#include <parc/logging/parc_LogReporterFile.h>
+#include <parc/logging/parc_LogReporterTextStdout.h>
+
+#include <parc/assert/parc_Assert.h>
+
+#include <src/core/dispatcher.h>
+#include <src/core/forwarder.h>
+
+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 _usage(int exitCode) {
+ printf(
+ "Usage: daemon [--port port] [--daemon] [--capacity objectStoreSize] "
+ "[--log facility=level] [--log-file filename] [--config file]\n");
+ printf("\n");
+ printf(
+ "hicn-light run as a daemon is the program to launch the forwarder, "
+ "either as a console program\n");
+ printf(
+ "or a background daemon (detatched from console). Once running, use the "
+ "program controller to\n");
+ printf("configure hicn-light.\n");
+ printf("\n");
+ printf(
+ "The configuration file contains configuration lines as per "
+ "controller\n");
+ printf(
+ "If logging level or content store capacity is set in the configuraiton "
+ "file, it overrides the command_line\n");
+ printf(
+ "When a configuration file is specified, no default listeners on 'port' "
+ "are setup. Only 'add listener' lines\n");
+ printf("in the configuration file matter.\n");
+ printf("\n");
+ printf(
+ "If no configuration file is specified, daemon will listen on TCP and "
+ "UDP ports specified by\n");
+ printf(
+ "the --port flag (or default port). It will listen on both IPv4 and "
+ "IPv6 if available.\n");
+ printf("\n");
+ printf("Options:\n");
+ printf("--port = tcp port for in-bound connections\n");
+ printf("--daemon = start as daemon process\n");
+ printf("--objectStoreSize = maximum number of content objects to cache\n");
+ printf(
+ "--log = sets a facility to a given log level. You can have "
+ "multiple of these.\n");
+ printf(
+ " facilities: all, config, core, io, message, "
+ "processor\n");
+ printf(
+ " levels: debug, info, notice, warning, error, "
+ "critical, alert, off\n");
+ printf(" example: daemon --log io=debug --log core=off\n");
+ printf(
+ "--log-file = file to write log messages to (required in daemon "
+ "mode)\n");
+ printf("--config = configuration filename\n");
+ printf("\n");
+ exit(exitCode);
+}
+
+static void _setLogLevelToLevel(int logLevelArray[LoggerFacility_END],
+ LoggerFacility facility,
+ const char *levelString) {
+ PARCLogLevel level = parcLogLevel_FromString(levelString);
+
+ if (level < PARCLogLevel_All) {
+ // we have a good facility and level
+ logLevelArray[facility] = level;
+ } else {
+ printf("Invalid log level string %s\n", levelString);
+ _usage(EXIT_FAILURE);
+ }
+}
+
+/**
+ * string: "facility=level"
+ * Set the right thing in the logger
+ */
+static void _setLogLevel(int logLevelArray[LoggerFacility_END],
+ const char *string) {
+ char *tofree = parcMemory_StringDuplicate(string, strlen(string));
+ char *p = tofree;
+
+ char *facilityString = strsep(&p, "=");
+ if (facilityString) {
+ char *levelString = p;
+
+ if (strcasecmp(facilityString, "all") == 0) {
+ for (LoggerFacility facility = 0; facility < LoggerFacility_END;
+ facility++) {
+ _setLogLevelToLevel(logLevelArray, facility, levelString);
+ }
+ } else {
+ LoggerFacility facility;
+ for (facility = 0; facility < LoggerFacility_END; facility++) {
+ if (strcasecmp(facilityString, logger_FacilityString(facility)) == 0) {
+ break;
+ }
+ }
+
+ if (facility < LoggerFacility_END) {
+ _setLogLevelToLevel(logLevelArray, facility, levelString);
+ } else {
+ printf("Invalid facility string %s\n", facilityString);
+ _usage(EXIT_FAILURE);
+ }
+ }
+ }
+
+ parcMemory_Deallocate((void **)&tofree);
+}
+
+static void _daemonize(void) {
+ if (getppid() == 1) {
+ // already a daemon
+ return;
+ }
+
+ int forkReturn = fork();
+ parcTrapUnexpectedStateIf(forkReturn < 0, "Fork error");
+
+ if (forkReturn > 0) {
+ // parent exits
+ exit(EXIT_SUCCESS);
+ }
+
+ // Child daemon detaches
+ printf("child continuing, pid = %u\n", getpid());
+
+ // get a new process group independent from old parent
+ setsid();
+
+ /* close all descriptors */
+ for (int i = getdtablesize(); i >= 0; --i) {
+ close(i);
+ }
+
+ // reset errno because it might be seg to EBADF from the close calls above
+ errno = 0;
+
+ // Redirect stdin and stdout and stderr to /dev/null
+ const char *devnull = "/dev/null";
+ int nullfile = open(devnull, O_RDWR);
+ parcAssertTrue(nullfile >= 0, "Error opening file '%s': (%d) %s", devnull,
+ errno, strerror(errno));
+
+ int ret;
+ ret = dup(nullfile);
+ parcAssertTrue(ret == 1, "Error duping fd 1 got %d file: (%d) %s", ret, errno,
+ strerror(errno));
+ ret = dup(nullfile);
+ parcAssertTrue(ret == 2, "Error duping fd 2, got %d file: (%d) %s", ret,
+ errno, strerror(errno));
+
+ // forwarder will capture signals
+}
+
+static Logger *_createLogfile(const char *logfile) {
+ int logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IWUSR | S_IRUSR);
+ if (logfd < 0) {
+ fprintf(stderr, "Error opening %s for writing: (%d) %s\n", logfile, errno,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ chmod(logfile, S_IRWXU);
+
+ PARCFileOutputStream *fos = parcFileOutputStream_Create(logfd);
+ PARCOutputStream *pos = parcFileOutputStream_AsOutputStream(fos);
+ PARCLogReporter *reporter = parcLogReporterFile_Create(pos);
+
+ Logger *logger = logger_Create(reporter, parcClock_Wallclock());
+
+ parcOutputStream_Release(&pos);
+ parcLogReporter_Release(&reporter);
+
+ return logger;
+}
+
+int main(int argc, const char *argv[]) {
+ _displayForwarderLogo();
+
+ uint16_t port = PORT_NUMBER;
+ uint16_t configurationPort = 2001;
+ bool daemon = false;
+ int capacity = -1;
+ const char *configFileName = NULL;
+
+ char *logfile = NULL;
+
+ if (argc == 2 && strcasecmp(argv[1], "-h") == 0) {
+ _usage(EXIT_SUCCESS);
+ }
+
+ int logLevelArray[LoggerFacility_END];
+ for (int i = 0; i < LoggerFacility_END; i++) {
+ logLevelArray[i] = -1;
+ }
+
+ for (int i = 0; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ if (strcmp(argv[i], "--config") == 0) {
+ configFileName = argv[i + 1];
+ i++;
+ } else if (strcmp(argv[i], "--port") == 0) {
+ port = atoi(argv[i + 1]);
+ i++;
+ } else if (strcmp(argv[i], "--daemon") == 0) {
+ daemon = true;
+ } else if (strcmp(argv[i], "--capacity") == 0 ||
+ strcmp(argv[i], "-c") == 0) {
+ capacity = atoi(argv[i + 1]);
+ i++;
+ } else if (strcmp(argv[i], "--log") == 0) {
+ _setLogLevel(logLevelArray, argv[i + 1]);
+ i++;
+ } else if (strcmp(argv[i], "--log-file") == 0) {
+ if (logfile) {
+ // error cannot repeat
+ fprintf(stderr, "Cannot specify --log-file more than once\n");
+ _usage(EXIT_FAILURE);
+ }
+
+ logfile = parcMemory_StringDuplicate(argv[i + 1], strlen(argv[i + 1]));
+ i++;
+ } else {
+ _usage(EXIT_FAILURE);
+ }
+ }
+ }
+
+ // set restrictive umask, in case we create any files
+ umask(027);
+
+ if (daemon && (logfile == NULL)) {
+ fprintf(stderr, "Must specify a logfile when running in daemon mode\n");
+ _usage(EXIT_FAILURE);
+ }
+
+ if (daemon) {
+ // inside this call, parent will EXIT_SUCCESS and child will continue
+ _daemonize();
+ }
+
+ Logger *logger = NULL;
+ if (logfile) {
+ logger = _createLogfile(logfile);
+ parcMemory_Deallocate((void **)&logfile);
+ } else {
+ PARCLogReporter *stdoutReporter = parcLogReporterTextStdout_Create();
+ logger = logger_Create(stdoutReporter, parcClock_Wallclock());
+ parcLogReporter_Release(&stdoutReporter);
+ }
+
+ for (int i = 0; i < LoggerFacility_END; i++) {
+ if (logLevelArray[i] > -1) {
+ logger_SetLogLevel(logger, i, logLevelArray[i]);
+ }
+ }
+
+ // this will update the clock to the tick clock
+ Forwarder *forwarder = forwarder_Create(logger);
+
+ Configuration *configuration = forwarder_GetConfiguration(forwarder);
+
+ if (capacity > -1) {
+ configuration_SetObjectStoreSize(configuration, capacity);
+ }
+
+ if (configFileName) {
+ forwarder_SetupAllListeners(forwarder, port, NULL);
+ forwarder_SetupFromConfigFile(forwarder, configFileName);
+ } else {
+ // NULL to not setup AF_UNIX
+ forwarder_SetupAllListeners(forwarder, port, NULL);
+ }
+
+ Dispatcher *dispatcher = forwarder_GetDispatcher(forwarder);
+
+ logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
+ "hicn-light running port %d configuration-port %d", port,
+ configurationPort);
+
+ dispatcher_Run(dispatcher);
+
+ logger_Log(logger, LoggerFacility_Core, PARCLogLevel_Alert, "daemon",
+ "hicn-light exiting port %d", port);
+
+ forwarder_Destroy(&forwarder);
+
+ sleep(2);
+
+ logger_Release(&logger);
+ return 0;
+}