Merge "Cell down alarm notification [Issue-Id: ODUHIGH-430]"
[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 #include "UnixSocketServer.hpp"
24 #include "Alarm.hpp"
25 #include "CmInterface.h"
26 #include "GlobalDefs.hpp"
27 #include <iostream>
28 #include <cstdio>
29 #include <cerrno>
30 #include <cstdlib>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
35 #include <netdb.h>
36 #include <arpa/inet.h>
37 #include <sys/un.h>
38 #include "InitConfig.hpp"
39
40
41 using std::map;
42 using std::pair;
43
44 /*******************************************************************
45  *
46  * @brief Constructor
47  *
48  * @details
49  *
50  *    Function : UnixSocketServer
51  *
52  *    Functionality:
53  *      - Constructor intialization
54  *
55  * @params[in] socket path
56  * @return None
57  ******************************************************************/
58 UnixSocketServer::UnixSocketServer(const string& sockPath)
59                                    : mSockPath(sockPath),
60                                      mIsRunning(false) 
61 {
62
63 }
64  
65 /*******************************************************************
66  *
67  * @brief Destructor
68  *
69  * @details
70  *
71  *    Function : ~UnixSocketServer
72  *
73  *    Functionality:
74  *      - Destructor
75  *
76  * @params[in] None
77  * @return None
78  ******************************************************************/
79 UnixSocketServer::~UnixSocketServer()
80 {
81
82 }
83
84
85 /*******************************************************************
86  *
87  * @brief Read the data from the connected client application
88  *
89  * @details
90  *
91  *    Function : readMessage
92  *
93  *    Functionality:
94  *      - Reads the data from the connected client application
95  *
96  * @params[in] File descriptor
97  * @return No. of bytes read
98  *
99  ******************************************************************/
100 int UnixSocketServer::readMessage(int fd)
101 {
102    char recvBuf[BUFLEN];
103    bzero(&recvBuf,sizeof(recvBuf));
104
105    int nbytes = read (fd, &recvBuf, sizeof(recvBuf));
106
107    if (nbytes > 0)
108    {
109       /* sending message to all Unix Socket Server subscribers */
110       createMessage(recvBuf);
111
112    }
113
114    return nbytes;
115 }
116
117
118 /*******************************************************************
119  *
120  * @brief Open a Unix socket and bind on the port
121  *
122  * @details
123  *
124  *    Function : makeSocket
125  *
126  *    Functionality:
127  *      -  Opens a Unix socket and bind on the port
128  *
129  * @params[in] void
130  * @return O1:SUCCESS - success
131  *         O1:FAILURE - failure
132  ******************************************************************/
133
134 int UnixSocketServer::makeSocket()
135 {
136    struct sockaddr_un name;
137    /* Create the socket. */
138    mSock = socket (AF_UNIX, SOCK_STREAM, 0);
139    if (mSock < 0)
140    {
141       O1_LOG("\nO1 UnixSocketServer : Socket error");
142       return O1::FAILURE;
143    }
144    /* Give the socket a name. */
145    bzero(&name, sizeof(name));
146    name.sun_family = AF_UNIX;
147
148    /* Remove the socket file if it already exists */
149    if ( unlink(mSockPath.c_str()) == 0)
150    {
151       O1_LOG("\nO1 UnixSocketServer : "
152              "Removing the existing socket path %s",
153               mSockPath.c_str());
154    }
155    strcpy(name.sun_path, mSockPath.c_str());
156    if (bind (mSock, (struct sockaddr *) &name, sizeof (name)) < 0)
157    {
158       close(mSock);
159       O1_LOG("\nO1 UnixSocketServer : Bind error");
160       return O1::FAILURE;
161    }
162    return O1::SUCCESS;
163 }
164
165
166 /*******************************************************************
167  *
168  * @brief A Unix server to handle multiple connection
169  *
170  * @details
171  *
172  *    Function : run
173  *
174  *    Functionality:
175  *      -  A Unix server to handle multiple connection
176  *         Uses select multiplexing
177  *
178  * @params[in] void
179  * @return true  - success
180  *         false - failure
181  ******************************************************************/
182 bool UnixSocketServer::run()
183 {
184
185    fd_set active_fd_set, read_fd_set;
186    int i;
187    struct sockaddr_un clientName;
188    socklen_t size;
189    mIsRunning = true;
190
191    /* Create the socket and set it up to accept connections. */
192    if( makeSocket() == O1::SUCCESS )
193    {
194       if (listen (mSock, 1) < 0)
195       {
196          O1_LOG("\nO1 UnixSocketServer : Listen error");
197          close(mSock);
198          mIsRunning = false;
199       }
200       else
201       {
202          /* Initialize the set of active sockets. */
203          FD_ZERO (&active_fd_set);
204          FD_SET (mSock, &active_fd_set);
205
206          while (1)
207          {
208             /* Block until input arrives on one or more active sockets. */
209             read_fd_set = active_fd_set;
210             if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
211             {
212                O1_LOG("\nO1 UnixSocketServer : Select error");
213                close(mSock);
214                mIsRunning = false;
215                break;
216             }
217
218             /* Service all the sockets with input pending. */
219             for (i = 0; i < FD_SETSIZE; ++i)
220             {
221                 if (FD_ISSET (i, &read_fd_set))
222                 {
223                    if (i == mSock)
224                    {
225                       /* Connection request on original socket. */
226                       int newFd;
227                       bzero(&clientName, sizeof(clientName));
228                       size = sizeof (clientName);
229                       newFd = accept(mSock,(struct sockaddr *) &clientName,&size);
230                       if (newFd < 0)
231                       {
232                          O1_LOG("\nO1 UnixSocketServer : Accept error");
233                          close(mSock);
234                          mIsRunning = false;
235                          break;
236                       }
237                       O1_LOG("\nO1 UnixSocketServer : Connected from client\n");
238                       FD_SET (newFd, &active_fd_set);
239                    }
240                    else
241                    {
242                       /* Data arriving on an already-connected socket. */
243                       if (readMessage(i) < 0)
244                       {
245                          close (i);
246                          FD_CLR (i, &active_fd_set);
247                       }
248                    }
249                 }
250              }/* for loop ends */
251           } /* while(1) ends */
252       } /* else ends */
253    } /* outer if ends */
254    else
255    {
256       mIsRunning = false;
257    }
258    return mIsRunning;
259 }
260
261
262 /*******************************************************************
263  *
264  * @brief Clean up open socket
265  *
266  * @details
267  *
268  *    Function : cleanUp
269  *
270  *    Functionality:
271  *      -  Performs any clean ups before stopping the thread
272  *
273  * @params[in] void
274  * @return void
275  ******************************************************************/
276 void UnixSocketServer::cleanUp(void)
277 {
278    close(mSock);
279    O1_LOG("\nO1 UnixSocketServer : Cleaning up Closing socket \n");
280 }
281
282 /*******************************************************************
283  *
284  * @brief Check if the server is running
285  *
286  * @details
287  *
288  *    Function : isRunning
289  *
290  *    Functionality:
291  *      -  Returns the running status of the server
292  *
293  * @params[in] void
294  * @return true : running
295  *         false: not running
296  ******************************************************************/
297 bool UnixSocketServer::isRunning() const
298 {
299    return mIsRunning;
300 }
301
302 /**********************************************************************
303          End of file
304 **********************************************************************/