23 #include "rmh_monitor.h"
25 #include <sys/select.h>
29 RMH_Result RMHMonitor_PrintUsage(
RMHMonitor *app) {
30 RMH_PrintMsg(
"usage: rmh_monitor [-?|-h|--help] [-n|--no_timestamp] [-t|--trace]\n");
32 RMH_PrintMsg(
" --help Print this help message\n");
33 RMH_PrintMsg(
" --no_timestamp Do not prefix each line with a timestamp\n");
34 RMH_PrintMsg(
" --timestamp Prefix each line with a timestamp\n");
35 RMH_PrintMsg(
" --out-file Write log messages to a file\n");
36 RMH_PrintMsg(
" --debug Enable API trace messages\n");
47 void RMHMonitor_RMHCallback(
const enum RMH_Event event,
const struct RMH_EventData *eventData,
void* userContext){
51 case RMH_EVENT_API_PRINT:
52 RMH_PrintMsg(
"%s", eventData->RMH_EVENT_API_PRINT.logMsg);
54 case RMH_EVENT_DRIVER_PRINT:
55 RMH_PrintMsg(
"%s", eventData->RMH_EVENT_DRIVER_PRINT.logMsg);
58 RMHMonitor_Queue_Enqueue(app, event, eventData);
68 RMH_Result RMHMonitor_ParseArguments(
RMHMonitor *app,
const int argc,
const char *argv[]) {
71 while (argc && i<argc) {
72 const char* option = argv[i];
75 if (option[0] ==
'-') {
76 if (strcmp(option,
"-t") == 0 || strcmp(option,
"--trace") == 0) {
77 app->apiLogLevel |= RMH_LOG_TRACE;
78 }
else if (strcmp(option,
"-n") == 0 || strcmp(option,
"--no_timestamp") == 0) {
79 app->printTimestamp =
false;
80 app->userSetTimestamps =
true;
81 }
else if (strcmp(option,
"-p") == 0 || strcmp(option,
"--timestamp") == 0) {
82 app->printTimestamp =
true;
83 app->userSetTimestamps =
true;
84 }
else if (strcmp(option,
"-s") == 0 || strcmp(option,
"--service_mode") == 0) {
85 app->serviceMode =
true;
86 }
else if (strcmp(option,
"-o") == 0 || strcmp(option,
"--out-file") == 0) {
87 app->out_file_name = argv[++i];;
88 }
else if (strcmp(option,
"-?") == 0 || strcmp(option,
"-h") == 0 || strcmp(option,
"--help") == 0) {
91 RMH_PrintWrn(
"Unknown option '%s'! Skipping\n", option);
96 RMH_PrintWrn(
"Unknown argument '%s'! Skipping\n", option);
114 RMH_PrintErr(
"Unable to connect to RMH. Ensure MoCA is running...\n");
120 RMH_EVENT_MOCA_RESET | \
121 RMH_EVENT_MOCA_VERSION_CHANGED | \
122 RMH_EVENT_ADMISSION_STATUS_CHANGED | \
123 RMH_EVENT_NODE_JOINED | \
124 RMH_EVENT_NODE_DROPPED | \
125 RMH_EVENT_NC_ID_CHANGED | \
126 RMH_EVENT_LOW_BANDWIDTH | \
127 RMH_EVENT_API_PRINT) != RMH_SUCCESS) {
128 RMH_PrintErr(
"Failed setting callback events!\n");
134 RMH_PrintErr(
"Failed to set the log level!\n");
138 app->eventThreadRunning=
true;
139 if (pthread_create(&app->eventThread, NULL, (
void *)RMHMonitor_Event_Thread, app) != 0) {
140 RMH_PrintErr(
"Failed creating event thread!");
146 if(pthread_join(app->eventThread, &ret)) {
147 RMH_PrintErr(
"Failed doing pthread_join");
149 app->eventThreadRunning=
false;
150 return ret ? true :
false;
156 RMH_Result pRMHMonitor_RFC_GetBool(
RMHMonitor* app,
const char*name,
bool *value) {
157 RFC_ParamData_t rfcParam;
158 WDMP_STATUS wdmpStatus;
160 wdmpStatus = getRFCParameter(
"RMH", name, &rfcParam);
161 if (wdmpStatus != WDMP_SUCCESS) {
162 if (wdmpStatus != WDMP_ERR_VALUE_IS_EMPTY) {
163 RMH_PrintErr(
"Failed reading from RFC -- %s -- Returned error '%s' (%u)\n", rfcParam.name, getRFCErrorString(wdmpStatus), wdmpStatus);
169 if (0 == strcasecmp(rfcParam.value,
"TRUE")) {
172 else if (0 == strcasecmp(rfcParam.value,
"FALSE")) {
176 RMH_PrintErr(
"Unexpected value reading from RFC -- %s -- Returned '%s' which is type %u. Expecting type WDMP_BOOLEAN(%u)\n", rfcParam.name, rfcParam.value, getRFCErrorString(wdmpStatus), rfcParam.type, WDMP_BOOLEAN);
186 int main(
const int argc,
const char *argv[])
190 RMH_Result result=RMH_FAILURE;
192 struct timeval timeout;
193 bool rmhEnableStatusLogging =
false;
196 memset(app, 0,
sizeof(*app));
197 app->apiLogLevel = RMH_LOG_DEFAULT;
199 if (RMH_SUCCESS == pRMHMonitor_RFC_GetBool(app,
"Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RMHLogging.Enable", &rmhEnableStatusLogging)) {
200 if (rmhEnableStatusLogging ==
false) {
201 RMH_PrintErr(
"RMH Loogging has been disabled via RFC. Exiting\n");
208 FD_SET(fileno(stdin), &fdset);
211 if (select(fileno(stdin)+1, &fdset, NULL, NULL, &timeout) == 1) {
212 app->serviceMode =
true;
216 if (RMHMonitor_ParseArguments(app, argc, argv) != RMH_SUCCESS) {
217 RMHMonitor_PrintUsage(app);
221 if (!app->userSetTimestamps) {
223 app->printTimestamp = !app->serviceMode;
226 if (app->out_file_name) {
227 app->out_file=fopen(app->out_file_name,
"w");
228 if ( !app->out_file ) {
229 RMH_PrintErr(
"Failed to open file '%s' for writing. Falling back to stdout\n", app->out_file_name);
234 TAILQ_INIT(&app->eventQueue);
235 app->eventNotify=RMHMonitor_Semaphore_Create();
236 if (!app->eventNotify) {
237 RMH_PrintErr(
"Failed RMHMonitor_Semaphore_Create!\n");
242 RMHMonitor_Semaphore_Reset(app->eventNotify);
245 if (pthread_mutex_init(&app->eventQueueProtect, NULL) != 0) {
246 RMH_PrintErr(
"Failed to create eventQueueProtect mutex!\n");
247 goto exit_err_eventNotify;
250 if (!app->serviceMode) {
251 RMH_PrintMsg(
"Begin monitoring MoCA status. Press Ctrl+C to exit...\n");
257 app->appPrefix=
"[ INIT ] ";
258 RMH_PrintMsg(
"Attempting to connect to MoCA\n");
260 reconnect=RMHMonitor_Connect(app);
268 if (!reconnect)
break;
270 RMH_PrintErr(
"There was a failure communicating with the MoCA driver. Sleeping %u seconds before attempting to reconnect...\n", app->reconnectSeconds);
272 usleep(app->reconnectSeconds*1000000);
273 app->reconnectSeconds+=5;
274 if (app->reconnectSeconds > 60) app->reconnectSeconds = 60;
277 RMH_PrintMsg(
"Exit status monitor\n");
280 fclose(app->out_file);
288 pthread_mutex_destroy (&app->eventQueueProtect);
290 exit_err_eventNotify:
292 if (app->eventNotify) {
293 RMHMonitor_Semaphore_Destroy(app->eventNotify);
294 app->eventNotify = NULL;