RDK Documentation (Open Sourced RDK Components)
rdk_dynamic_logger.c
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 /**
21  * @file rdk_dynamic_logger.c
22  */
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <arpa/inet.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <sys/select.h>
30 #include <sys/time.h>
31 
32 #include "rdk_dynamic_logger.h"
33 
34 #define DL_PORT 12035
35 #define DL_SIGNATURE "COMC"
36 #define DL_SIGNATURE_LEN 4
37 
38 static int g_dl_socket = -1;
39 extern char *__progname;
40 
41 static char * rdk_dyn_log_logLevelToString(unsigned char log_level)
42 {
43  int negate = 0;
44  unsigned char negate_mask = 0x80;
45 
46  if(negate_mask == (log_level & negate_mask)) {
47  negate = 1;
48  log_level = log_level & (~negate_mask) ;
49  }
50 
51  switch(log_level){
52  case RDK_LOG_FATAL:
53  return (negate) ? "!FATAL":"FATAL";
54  case RDK_LOG_ERROR:
55  return (negate) ? "!ERROR":"ERROR";
56  case RDK_LOG_WARN:
57  return (negate) ? "!WARNING":"WARNING";
58  case RDK_LOG_NOTICE:
59  return (negate) ? "!NOTICE":"NOTICE";
60  case RDK_LOG_INFO:
61  return (negate) ? "!INFO":"INFO";
62  case RDK_LOG_DEBUG:
63  return (negate) ? "!DEBUG":"DEBUG";
64  case RDK_LOG_TRACE1:
65  return (negate) ? "!TRACE1":"TRACE1";
66  case RDK_LOG_TRACE2:
67  return (negate) ? "!TRACE2":"TRACE2";
68  case RDK_LOG_TRACE3:
69  return (negate) ? "!TRACE3":"TRACE3";
70  case RDK_LOG_TRACE4:
71  return (negate) ? "!TRACE4":"TRACE4";
72  case RDK_LOG_TRACE5:
73  return (negate) ? "!TRACE5":"TRACE5";
74  case RDK_LOG_TRACE6:
75  return (negate) ? "!TRACE6":"TRACE6";
76  case RDK_LOG_TRACE7:
77  return (negate) ? "!TRACE7":"TRACE7";
78  case RDK_LOG_TRACE8:
79  return (negate) ? "!TRACE8":"TRACE8";
80  case RDK_LOG_TRACE9:
81  return (negate) ? "!TRACE9":"TRACE9";
82  }
83 
84  return NULL;
85 }
86 
87 static void rdk_dyn_log_validateComponentName(const unsigned char *buf)
88 {
89  unsigned char log_level = 0;
90  int app_len, comp_len, i = DL_SIGNATURE_LEN;
91  char *loggingLevel = NULL, comp_name[64] = {0};
92 
93  if(0 != memcmp(buf,DL_SIGNATURE,i)) {
94  return;
95  }
96 
97  log_level = buf[++i];
98  app_len = buf[++i];
99 
100  if(0 != memcmp(buf+(++i),__progname,app_len)) {
101  /* The received msg is not intended for this process */
102  return;
103  }
104 
105  i += app_len;
106  comp_len = buf[i];
107 
108  loggingLevel = rdk_dyn_log_logLevelToString(log_level);
109  if(NULL != loggingLevel) {
110  memcpy(comp_name,buf+(++i),comp_len);
111  RDK_LOG_ControlCB(comp_name, NULL, loggingLevel, 0);
112  fprintf(stderr,"%s(): Set %s loglevel for the component %s of the process %s\n",__func__,loggingLevel,comp_name,__progname);
113  }
114 }
115 
116 void rdk_dyn_log_processPendingRequest()
117 {
118  char buf[128] = {0};
119  struct sockaddr_in sender_addr;
120  struct timeval tv;
121  int numbytes, addr_len, ret, i = 0;
122  fd_set rfds;
123 
124  if(-1 == g_dl_socket)
125  return;
126 
127  memset(&sender_addr,0,sizeof(sender_addr));
128  while(1) {
129  FD_ZERO(&rfds);
130  FD_SET(g_dl_socket, &rfds);
131  addr_len = sizeof(sender_addr);
132 
133  tv.tv_sec = 0;
134  tv.tv_usec = 0;
135  ret = select(g_dl_socket+1,&rfds,NULL,NULL,&tv);
136  if(ret <= 0)
137  break;
138 
139  if ((numbytes=recvfrom(g_dl_socket, buf, sizeof(buf), 0, (struct sockaddr *)&sender_addr, &addr_len)) == -1) {
140  fprintf(stderr,"%s recvfrom failed %s\n",__func__,strerror(errno));
141  return;
142  }
143 
144  /*
145  * msg_format {
146  * char m_signature[4];
147  * uchar8 m_msgLength;
148  * uchar8 m_logLevel;
149  * uchar8 m_appLength;
150  * char m_appname[m_appLength];
151  * uchar8 m_compNameLength;
152  * char m_compName[m_compNameLength];
153  * }
154  *
155  * Ensure that the we handle msgs only from localhost
156  */
157  if((0 == strcmp("127.0.0.1",inet_ntoa(sender_addr.sin_addr))) &&
158  (numbytes == buf[4]+DL_SIGNATURE_LEN+1)) {
159  rdk_dyn_log_validateComponentName(buf);
160  }
161  }
162 }
163 
164 void rdk_dyn_log_init()
165 {
166  struct sockaddr_in my_addr;
167  int opt = 1;
168 
169  if ((g_dl_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
170  fprintf(stderr, "%s() Socket creation failed. %s\n",__func__,strerror(errno));
171  return;
172  }
173 
174  memset(&my_addr,0,sizeof(my_addr));
175  my_addr.sin_family = AF_INET;
176  my_addr.sin_port = htons(DL_PORT);
177  my_addr.sin_addr.s_addr = inet_addr("127.255.255.255");
178 
179  if (-1 == setsockopt(g_dl_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int))) {
180  fprintf(stderr, "%s() setsockopt error %s\n",__func__,strerror(errno));
181  close(g_dl_socket);
182  g_dl_socket = -1;
183  return;
184  }
185 
186  if (-1 == bind(g_dl_socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))) {
187  fprintf(stderr, "%s() bind error %s\n",__func__,strerror(errno));
188  close(g_dl_socket);
189  g_dl_socket = -1;
190  return;
191  }
192 
193  fprintf(stderr, "%sg_dl_socket = %d __progname = %s \n",__func__,g_dl_socket,__progname);
194 }
195 
196 void rdk_dyn_log_deInit()
197 {
198  close(g_dl_socket);
199  g_dl_socket = -1;
200 }