+/**
+ *
+ * @param sctpParams
+ */
+void handleConfigChange(sctp_params_t *sctpParams) {
+ char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ const struct inotify_event *event;
+ char *ptr;
+
+ path p = (sctpParams->configFilePath + "/" + sctpParams->configFileName).c_str();
+ auto endlessLoop = true;
+ while (endlessLoop) {
+ auto len = read(sctpParams->inotifyFD, buf, sizeof buf);
+ if (len == -1) {
+ if (errno != EAGAIN) {
+ mdclog_write(MDCLOG_ERR, "read %s ", strerror(errno));
+ endlessLoop = false;
+ continue;
+ }
+ else {
+ endlessLoop = false;
+ continue;
+ }
+ }
+
+ for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) {
+ event = (const struct inotify_event *)ptr;
+ if (event->mask & (uint32_t)IN_ISDIR) {
+ continue;
+ }
+
+ // the directory name
+ if (sctpParams->inotifyWD == event->wd) {
+ // not the directory
+ }
+ if (event->len) {
+ if (!(sctpParams->configFileName.compare(event->name))) {
+ continue;
+ }
+ }
+ // only the file we want
+ if (event->mask & (uint32_t)IN_CLOSE_WRITE) {
+ if (exists(p)) {
+ const int size = 2048;
+ auto fileSize = file_size(p);
+ if (fileSize > size) {
+ mdclog_write(MDCLOG_ERR, "File %s larger than %d", p.string().c_str(), size);
+ return;
+ }
+ } else {
+ mdclog_write(MDCLOG_ERR, "Configuration File %s not exists", p.string().c_str());
+ return;
+ }
+
+ ReadConfigFile conf;
+ if (conf.openConfigFile(p.string()) == -1) {
+ mdclog_write(MDCLOG_ERR, "Filed to open config file %s, %s",
+ p.string().c_str(), strerror(errno));
+ return;
+ }
+
+ auto tmpStr = conf.getStringValue("loglevel");
+ if (tmpStr.length() == 0) {
+ mdclog_write(MDCLOG_ERR, "illigal loglevel. Set loglevel to MDCLOG_INFO");
+ tmpStr = "info";
+ }
+ transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+
+ if ((tmpStr.compare("debug")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_DEBUG");
+ sctpParams->logLevel = MDCLOG_DEBUG;
+ } else if ((tmpStr.compare("info")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_INFO");
+ sctpParams->logLevel = MDCLOG_INFO;
+ } else if ((tmpStr.compare("warning")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_WARN");
+ sctpParams->logLevel = MDCLOG_WARN;
+ } else if ((tmpStr.compare("error")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Log level set to MDCLOG_ERR");
+ sctpParams->logLevel = MDCLOG_ERR;
+ } else {
+ mdclog_write(MDCLOG_ERR, "illigal loglevel = %s. Set loglevel to MDCLOG_INFO", tmpStr.c_str());
+ sctpParams->logLevel = MDCLOG_INFO;
+ }
+ mdclog_level_set(sctpParams->logLevel);
+
+
+ tmpStr = conf.getStringValue("trace");
+ if (tmpStr.length() == 0) {
+ mdclog_write(MDCLOG_ERR, "illigal trace. Set trace to stop");
+ tmpStr = "stop";
+ }
+
+ transform(tmpStr.begin(), tmpStr.end(), tmpStr.begin(), ::tolower);
+ if ((tmpStr.compare("start")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Trace set to: start");
+ sctpParams->trace = true;
+ } else if ((tmpStr.compare("stop")) == 0) {
+ mdclog_write(MDCLOG_INFO, "Trace set to: stop");
+ sctpParams->trace = false;
+ } else {
+ mdclog_write(MDCLOG_ERR, "Trace was set to wrong value %s, set to stop", tmpStr.c_str());
+ sctpParams->trace = false;
+ }
+ jsonTrace = sctpParams->trace;
+ endlessLoop = false;
+ }
+ }
+ }
+}
+
+/**
+ *
+ * @param event
+ * @param message
+ * @param rmrMessageBuffer
+ * @param params
+ * @param pSpan
+ */
+void handleEinprogressMessages(struct epoll_event &event,
+ ReportingMessages_t &message,
+ RmrMessagesBuffer_t &rmrMessageBuffer,
+ sctp_params_t *params,
+ otSpan *pSpan) {
+#ifdef __TRACING__
+ auto lspan = opentracing::Tracer::Global()->StartSpan(
+ __FUNCTION__, { opentracing::ChildOf(&pSpan->get()->context()) });
+#else
+ otSpan lspan = 0;
+#endif
+ auto *peerInfo = (ConnectedCU_t *)event.data.ptr;
+ memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+
+ mdclog_write(MDCLOG_INFO, "file descriptor %d got EPOLLOUT", peerInfo->fileDescriptor);
+ auto retVal = 0;
+ socklen_t retValLen = 0;
+ auto rc = getsockopt(peerInfo->fileDescriptor, SOL_SOCKET, SO_ERROR, &retVal, &retValLen);
+ if (rc != 0 || retVal != 0) {
+ if (rc != 0) {
+ rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+ "%s|Failed SCTP Connection, after EINPROGRESS the getsockopt%s",
+ peerInfo->enodbName, strerror(errno));
+ } else if (retVal != 0) {
+ rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+ "%s|Failed SCTP Connection after EINPROGRESS, SO_ERROR",
+ peerInfo->enodbName);
+ }
+
+ message.message.asndata = rmrMessageBuffer.sendMessage->payload;
+ message.message.asnLength = rmrMessageBuffer.sendMessage->len;
+ mdclog_write(MDCLOG_ERR, "%s", rmrMessageBuffer.sendMessage->payload);
+ message.message.direction = 'N';
+ if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &lspan) != 0) {
+ mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
+ }
+ memset(peerInfo->asnData, 0, peerInfo->asnLength);
+ peerInfo->asnLength = 0;
+ peerInfo->mtype = 0;
+#ifdef __TRACING__
+ lspan->Finish();
+#endif
+ return;
+ }
+
+ peerInfo->isConnected = true;
+
+ if (modifyToEpoll(params->epoll_fd, peerInfo, (EPOLLIN | EPOLLET), params->sctpMap, peerInfo->enodbName,
+ peerInfo->mtype, &lspan) != 0) {
+ mdclog_write(MDCLOG_ERR, "epoll_ctl EPOLL_CTL_MOD");
+#ifdef __TRACING__
+ lspan->Finish();
+#endif
+ return;
+ }
+
+ message.message.asndata = (unsigned char *)peerInfo->asnData;
+ message.message.asnLength = peerInfo->asnLength;
+ message.message.messageType = peerInfo->mtype;
+ memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+ num_of_messages.fetch_add(1, std::memory_order_release);
+ if (mdclog_level_get() >= MDCLOG_DEBUG) {
+ mdclog_write(MDCLOG_DEBUG, "send the delayed SETUP/ENDC SETUP to sctp for %s",
+ message.message.enodbName);
+ }
+ if (sendSctpMsg(peerInfo, message, params->sctpMap, &lspan) != 0) {
+ if (mdclog_level_get() >= MDCLOG_DEBUG) {
+ mdclog_write(MDCLOG_DEBUG, "Error write to SCTP %s %d", __func__, __LINE__);
+ }
+#ifdef __TRACING__
+ lspan->Finish();
+#endif
+ return;
+ }
+
+ memset(peerInfo->asnData, 0, peerInfo->asnLength);
+ peerInfo->asnLength = 0;
+ peerInfo->mtype = 0;
+#ifdef __TRACING__
+ lspan->Finish();
+#endif
+}
+
+
+void handlepoll_error(struct epoll_event &event,
+ ReportingMessages_t &message,
+ RmrMessagesBuffer_t &rmrMessageBuffer,
+ sctp_params_t *params,
+ otSpan *pSpan) {
+#ifdef __TRACING__
+ auto lspan = opentracing::Tracer::Global()->StartSpan(
+ __FUNCTION__, { opentracing::ChildOf(&pSpan->get()->context()) });
+#else
+ otSpan lspan = 0;
+#endif
+ if (event.data.fd != params->rmrListenFd) {
+ auto *peerInfo = (ConnectedCU_t *)event.data.ptr;
+ mdclog_write(MDCLOG_ERR, "epoll error, events %0x on fd %d, RAN NAME : %s",
+ event.events, peerInfo->fileDescriptor, peerInfo->enodbName);
+
+ rmrMessageBuffer.sendMessage->len = snprintf((char *)rmrMessageBuffer.sendMessage->payload, 256,
+ "%s|Failed SCTP Connection",
+ peerInfo->enodbName);
+ message.message.asndata = rmrMessageBuffer.sendMessage->payload;
+ message.message.asnLength = rmrMessageBuffer.sendMessage->len;
+
+ memcpy(message.message.enodbName, peerInfo->enodbName, sizeof(peerInfo->enodbName));
+ message.message.direction = 'N';
+ if (sendRequestToXapp(message, RIC_SCTP_CONNECTION_FAILURE, rmrMessageBuffer, &lspan) != 0) {
+ mdclog_write(MDCLOG_ERR, "SCTP_CONNECTION_FAIL message failed to send to xAPP");
+ }
+
+ close(peerInfo->fileDescriptor);
+ cleanHashEntry((ConnectedCU_t *) event.data.ptr, params->sctpMap, &lspan);
+ } else {
+ mdclog_write(MDCLOG_ERR, "epoll error, events %0x on RMR FD", event.events);
+ }
+#ifdef __TRACING__
+ lspan->Finish();
+#endif
+
+}