412d28820830a97928f26a9a7e75199f8d3c26b1
[o-du/l2.git] / src / o1 / UnixSocketServer.cpp
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2020-2021] [HCL Technologies Ltd.]                          #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /* This file contains UnixSocketServer class that listens for Netconf Alarm 
20    messages on a Unix socket from ODU. It calls the AlarmManager functions
21    for raising or clearing the alarms based on the actions received 
22 */
23
24 #include "UnixSocketServer.hpp"
25 #include "Alarm.hpp"
26 #include "AlarmManager.hpp"
27 #include "ConfigInterface.h"
28 #include "GlobalDefs.hpp"
29 #include <iostream>
30 #include <cstdio>
31 #include <cerrno>
32 #include <cstdlib>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #include <arpa/inet.h>
39 #include <sys/un.h>
40 #include "InitConfig.hpp"
41
42
43 using std::map;
44 using std::pair;
45
46 /*******************************************************************
47  *
48  * @brief Constructor
49  *
50  * @details
51  *
52  *    Function : UnixSocketServer
53  *
54  *    Functionality:
55  *      - Constructor intialization
56  *
57  * @params[in] socket path
58  * @return None
59  ******************************************************************/
60 UnixSocketServer::UnixSocketServer(const string& sockPath)
61                                    : mSockPath(sockPath),
62                                      mIsRunning(false)
63 {
64
65 }  
66   
67 /*******************************************************************
68  *
69  * @brief Destructor
70  *
71  * @details
72  *
73  *    Function : ~UnixSocketServer
74  *
75  *    Functionality:
76  *      - Destructor
77  *
78  * @params[in] None
79  * @return None
80  ******************************************************************/
81 UnixSocketServer::~UnixSocketServer()
82 {
83
84 }
85
86
87 /*******************************************************************
88  *
89  * @brief Read the data from the connected client application
90  *
91  * @details
92  *
93  *    Function : readMessage
94  *
95  *    Functionality:
96  *      - Reads the data from the connected client application
97  *
98  * @params[in] File descriptor
99  * @return No. of bytes read
100  *
101  ******************************************************************/
102 int UnixSocketServer::readMessage(int fd)
103 {
104    AlarmRecord *alrmRec = NULL;
105    char recvBuf[BUFLEN];
106    Alarm alrm;
107    bzero(&recvBuf,sizeof(recvBuf));
108    
109    int nbytes = read (fd, &recvBuf, sizeof(recvBuf));
110    
111    if (nbytes > 0)
112    {
113       MsgHeader *msgHdr = (MsgHeader*)recvBuf;
114
115       O1_LOG("\nO1 UnixSocketServer :\nMsgType %d",msgHdr->msgType);
116       
117       if ( msgHdr->msgType == ALARM ){
118          uint16_t alrmId;
119          alrmRec = (AlarmRecord*) recvBuf;
120          O1_LOG("\nO1 UnixSocketServer :\n"
121                    "Action %d\n"
122                    "Alarm ID %s\n" 
123                    "Severity %d\n" 
124                    "Additional Text %s\n"
125                    "Specific Problem %s\n"
126                    "Additional Info %s\n"
127                    "Alarm Raise Time %s\n",
128                    alrmRec->msgHeader.action,
129                    alrmRec->alarmId,
130                    alrmRec->perceivedSeverity,
131                    alrmRec->additionalText,
132                    alrmRec->specificProblem,
133                    alrmRec->additionalInfo,
134                    alrmRec->alarmRaiseTime
135                 );
136       
137          /*Fill the alarm structure */
138          sscanf(alrmRec->alarmId,"%hu",&alrmId);
139          alrm.setAlarmId(alrmId);
140          alrm.setPerceivedSeverity(alrmRec->perceivedSeverity);
141          alrm.setAdditionalText(alrmRec->additionalText);
142          alrm.setEventType(alrmRec->eventType);
143          alrm.setSpecificProblem(alrmRec->specificProblem);
144          alrm.setAdditionalInfo(alrmRec->additionalInfo);
145       }
146
147       switch(msgHdr->action)
148       {
149          case RAISE_ALARM: 
150
151                      if(AlarmManager::instance().raiseAlarm(alrm))
152                      {
153                         O1_LOG("\nO1 UnixSocketServer : "
154                                "Alarm raised for alarm Id %s",
155                                 alrmRec->alarmId);
156
157                         // triggering VES notification for the risen Alarm
158
159                         VesEventHandler vesEvtHdr;
160                         if(vesEvtHdr.prepare(VesEventType::FAULT_NOTIFICATION, &alrm)) {
161                            vesEvtHdr.send();
162                         }
163
164                      }
165
166                      else
167                      {
168                         O1_LOG("\nO1 UnixSocketServer : "
169                                "Error in raising alarm for alrm Id %s",
170                                 alrmRec->alarmId);
171                      }
172                      break;  
173                      
174          case CLEAR_ALARM: 
175                      if(AlarmManager::instance().clearAlarm(alrm))
176                      {
177                         O1_LOG("\nO1 UnixSocketServer : "
178                                "Alarm cleared for alarm Id %s",
179                                 alrmRec->alarmId);
180
181                         // triggering VES notification for the cleared Alarm
182                         VesEventHandler vesEvtHdr;
183                         if(vesEvtHdr.prepare(VesEventType::FAULT_NOTIFICATION, &alrm)) {
184                            vesEvtHdr.send();
185                         }
186                      }
187                      else
188                      {
189                         O1_LOG("\nO1 UnixSocketServer : "
190                                "Error in clearing alarm for alarm Id %s",
191                                 alrmRec->alarmId);
192                      }
193                      break;
194 #if 0
195          case GET_STARTUP_CONFIG:
196                      {
197                         StartupConfig cfg;
198                                        InitConfig::instance().getCurrInterfaceConfig(cfg);
199                         O1_LOG("\nO1 UnixSocketServer : "
200                                "cfg.DU_IPV4_Addr [%s]",
201                                 cfg.DU_IPV4_Addr);
202                         O1_LOG("\nO1 UnixSocketServer : "
203                                "cfg.DU_Port [%d]", 
204                                 cfg.DU_Port);
205                         O1_LOG("\nO1 UnixSocketServer : "
206                                "cfg.CU_IPV4_Addr [%s]", 
207                                 cfg.CU_IPV4_Addr);
208                         O1_LOG("\nO1 UnixSocketServer : "
209                                "cfg.CU_Port [%d]", 
210                                 cfg.CU_Port);
211                         O1_LOG("\nO1 UnixSocketServer : "
212                                "cfg.RIC_IPV4_Addr [%s]", 
213                                 cfg.RIC_IPV4_Addr);
214                         O1_LOG("\nO1 UnixSocketServer : "
215                                "cfg.RIC_Port [%d]", 
216                                 cfg.RIC_Port);
217                         if (write (fd, &cfg, sizeof(cfg)) < 0)
218                         {
219                            O1_LOG("\nO1 UnixSocketServer : "
220                                   "Error sending startup configuration \n");
221                         }
222                         break; 
223                      }
224 #endif
225          default:    
226                      O1_LOG("\nO1 UnixSocketServer : No action performed"); 
227                      break;
228       }
229
230    }
231    return nbytes;
232 }
233
234
235 /*******************************************************************
236  *
237  * @brief Open a Unix socket and bind on the port
238  *
239  * @details
240  *
241  *    Function : makeSocket
242  *
243  *    Functionality:
244  *      -  Opens a Unix socket and bind on the port
245  *
246  * @params[in] void
247  * @return O1:SUCCESS - success
248  *         O1:FAILURE - failure
249  ******************************************************************/
250
251 int UnixSocketServer::makeSocket() 
252 {
253    struct sockaddr_un name;
254    /* Create the socket. */
255    mSock = socket (AF_UNIX, SOCK_STREAM, 0);
256    if (mSock < 0)
257    {
258       O1_LOG("\nO1 UnixSocketServer : Socket error");
259       return O1::FAILURE;
260    }
261    /* Give the socket a name. */
262    bzero(&name, sizeof(name));
263    name.sun_family = AF_UNIX;
264
265    /* Remove the socket file if it already exists */ 
266    if ( unlink(mSockPath.c_str()) == 0)
267    {
268       O1_LOG("\nO1 UnixSocketServer : "
269              "Removing the existing socket path %s",
270               mSockPath.c_str());
271    }        
272    strcpy(name.sun_path, mSockPath.c_str());
273    if (bind (mSock, (struct sockaddr *) &name, sizeof (name)) < 0)
274    {
275       close(mSock);
276       O1_LOG("\nO1 UnixSocketServer : Bind error");
277       return O1::FAILURE;
278    }
279    return O1::SUCCESS;
280 }
281
282
283 /*******************************************************************
284  *
285  * @brief A Unix server to handle multiple connection
286  *
287  * @details
288  *
289  *    Function : run
290  *
291  *    Functionality:
292  *      -  A Unix server to handle multiple connection 
293  *         Uses select multiplexing
294  *
295  * @params[in] void
296  * @return true  - success
297  *         false - failure
298  ******************************************************************/
299 bool UnixSocketServer::run()
300 {
301
302    fd_set active_fd_set, read_fd_set;
303    int i;
304    struct sockaddr_un clientName;
305    socklen_t size;
306    mIsRunning = true;
307
308    /* Create the socket and set it up to accept connections. */
309    if( makeSocket() == O1::SUCCESS )
310    {
311       if (listen (mSock, 1) < 0)
312       {
313          O1_LOG("\nO1 UnixSocketServer : Listen error");
314          close(mSock);
315          mIsRunning = false;
316       }
317       else
318       {
319          /* Initialize the set of active sockets. */
320          FD_ZERO (&active_fd_set);
321          FD_SET (mSock, &active_fd_set);
322
323          while (1)
324          {
325             /* Block until input arrives on one or more active sockets. */
326             read_fd_set = active_fd_set;
327             if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
328             {
329                O1_LOG("\nO1 UnixSocketServer : Select error");
330                close(mSock);
331                mIsRunning = false;
332                break;
333             }
334
335             /* Service all the sockets with input pending. */
336             for (i = 0; i < FD_SETSIZE; ++i)
337             {
338                 if (FD_ISSET (i, &read_fd_set))
339                 {
340                    if (i == mSock)
341                    {
342                       /* Connection request on original socket. */
343                       int newFd;
344                       bzero(&clientName, sizeof(clientName));
345                       size = sizeof (clientName);
346                       newFd = accept(mSock,(struct sockaddr *) &clientName,&size);
347                       if (newFd < 0)
348                       {
349                          O1_LOG("\nO1 UnixSocketServer : Accept error");
350                          close(mSock);
351                          mIsRunning = false;
352                          break;
353                       }
354                       O1_LOG("\nO1 UnixSocketServer : Connected from client\n");
355                       FD_SET (newFd, &active_fd_set);
356                    }      
357                    else
358                    {
359                       /* Data arriving on an already-connected socket. */
360                       if (readMessage(i) < 0)
361                       {
362                          close (i);
363                          FD_CLR (i, &active_fd_set);
364                       }
365                    }
366                 }    
367              }/* for loop ends */     
368           } /* while(1) ends */
369       } /* else ends */
370    } /* outer if ends */
371    else
372    {
373       mIsRunning = false;
374    }
375    return mIsRunning;
376 }
377
378
379 /*******************************************************************
380  *
381  * @brief Clean up open socket
382  *
383  * @details
384  *
385  *    Function : cleanUp
386  *
387  *    Functionality:
388  *      -  Performs any clean ups before stopping the thread
389  *
390  * @params[in] void
391  * @return void
392  ******************************************************************/
393 void UnixSocketServer::cleanUp(void)
394 {
395    close(mSock);
396    O1_LOG("\nO1 UnixSocketServer : Cleaning up Closing socket \n");
397 }
398
399 /*******************************************************************
400  *
401  * @brief Check if the server is running
402  *
403  * @details
404  *
405  *    Function : isRunning
406  *
407  *    Functionality:
408  *      -  Returns the running status of the server
409  *
410  * @params[in] void
411  * @return true : running
412  *         false: not running
413  ******************************************************************/
414 bool UnixSocketServer::isRunning() const
415 {
416    return mIsRunning;
417 }
418
419 /**********************************************************************
420          End of file
421 **********************************************************************/