Fix of compilation issue .[Issue-Id: ODUHIGH- 323]
[o-du/l2.git] / src / o1 / TcpServer.cpp
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2020] [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 TcpServer class that listens for Netconf Alarm messages
20    on a TCP socket from ODU. It calls the AlarmManager functions for raising 
21    or clearing the alarms based on the actions received 
22 */
23
24 #include "TcpServer.hpp"
25 #include "Alarm.hpp"
26 #include "AlarmManager.hpp"
27 #include "Config.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 "InitConfig.hpp"
40
41 using std::map;
42 using std::pair;
43
44 /* Destructor */
45 TcpServer::~TcpServer()
46 {
47
48 }
49
50
51 /*******************************************************************
52  *
53  * @brief Read the data from the connected client application
54  *
55  * @details
56  *
57  *    Function : readMessage
58  *
59  *    Functionality:
60  *      - Reads the data from the connected client application
61  *
62  * @params[in] File descriptor
63  * @return No. of bytes read
64  *
65  ******************************************************************/
66 int TcpServer::readMessage(int fd)
67 {
68    AlarmRecord *alrmRec = NULL;
69    char recvBuf[BUFLEN];
70    Alarm alrm;
71    bzero(&recvBuf,sizeof(recvBuf));
72    
73    int nbytes = read (fd, &recvBuf, sizeof(recvBuf));
74    
75    if (nbytes > 0)
76    {
77       MsgHeader *msgHdr = (MsgHeader*)recvBuf;
78
79       O1_LOG("\nO1 TcpServer :\nBuf size %ld", sizeof(recvBuf));
80       O1_LOG("\nO1 TcpServer :\nMsgType %d",msgHdr->msgType);
81       O1_LOG("\nO1 TcpServer :\nAction %d",msgHdr->action);
82       
83       if ( msgHdr->msgType == ALARM ){
84          uint16_t alrmId;
85          alrmRec = (AlarmRecord*) recvBuf;
86          O1_LOG("\nO1 TcpServer :\nAction %d\nalarm ID %s\n%d\n%s\n%d\n%s\n%s\nbytes %d",
87                      alrmRec->msgHeader.action,
88                      alrmRec->alarmId,
89                      alrmRec->perceivedSeverity,
90                      alrmRec->additionalText,
91                      alrmRec->eventType,
92                      alrmRec->specificProblem,
93                      alrmRec->additionalInfo,
94                      nbytes
95                      );
96       
97          /*Fill the alarm structure */
98          sscanf(alrmRec->alarmId,"%hu",&alrmId);
99          alrm.setAlarmId(alrmId);
100          alrm.setPerceivedSeverity(alrmRec->perceivedSeverity);
101          alrm.setAdditionalText(alrmRec->additionalText);
102          alrm.setEventType(alrmRec->eventType);
103          alrm.setSpecificProblem(alrmRec->specificProblem);
104          alrm.setAdditionalInfo(alrmRec->additionalInfo);
105       }
106
107       switch(msgHdr->action)
108       {
109          case RAISE_ALARM: 
110                      if(AlarmManager::instance().raiseAlarm(alrm))
111                      {
112                         O1_LOG("\nO1 TcpServer : Alarm raised for alarm Id %s", alrmRec->alarmId);
113                      }
114                      else
115                      {
116                         O1_LOG("\nO1 TcpServer : Error in raising alarm for alrm Id %s", alrmRec->alarmId);
117                      }
118                      break;  
119          case CLEAR_ALARM: 
120                      if(AlarmManager::instance().clearAlarm(alrm))
121                      {
122                         O1_LOG("\nO1 TcpServer : Alarm cleared for alarm Id %s", alrmRec->alarmId);
123                      }
124                      else
125                      {
126                         O1_LOG("\nO1 TcpServer : Error in clearing alarm for alarm Id %s", alrmRec->alarmId);
127                      }
128                      break;
129          case GET_STARTUP_CONFIG:
130                      {
131                         StartupConfig cfg;
132                                        InitConfig::instance().getCurrInterfaceConfig(cfg);
133                         O1_LOG("\nO1 TcpServer : cfg.DU_IPV4_Addr [%s]", cfg.DU_IPV4_Addr);
134                         O1_LOG("\nO1 TcpServer : cfg.DU_Port [%d]", cfg.DU_Port);
135                         O1_LOG("\nO1 TcpServer : cfg.CU_IPV4_Addr [%s]", cfg.CU_IPV4_Addr);
136                         O1_LOG("\nO1 TcpServer : cfg.CU_Port [%d]", cfg.CU_Port);
137                         O1_LOG("\nO1 TcpServer : cfg.RIC_IPV4_Addr [%s]", cfg.RIC_IPV4_Addr);
138                         O1_LOG("\nO1 TcpServer : cfg.RIC_Port [%d]", cfg.RIC_Port);
139                         if (write (fd, &cfg, sizeof(cfg)) < 0)
140                         {
141                            O1_LOG("\nO1 TcpServer : Error sending startup configuration \n");
142                         }
143                         break; 
144                      }
145          default:    
146                      O1_LOG("\nO1 TcpServer : No action performed"); 
147                      break;
148       }
149
150    }
151    return nbytes;
152 }
153
154
155 /*******************************************************************
156  *
157  * @brief Open a TCP socket and bind on the port
158  *
159  * @details
160  *
161  *    Function : makeSocket
162  *
163  *    Functionality:
164  *      -  Opens a TCP socket and bind on the port
165  *
166  * @params[in] void
167  * @return O1:SUCCESS - success
168  *         O1:FAILURE - failure
169  ******************************************************************/
170 int TcpServer::makeSocket() 
171 {
172    struct sockaddr_in name;
173    /* Create the socket. */
174    mSock = socket (PF_INET, SOCK_STREAM, 0);
175    if (mSock < 0)
176    {
177       O1_LOG("\nO1 TcpServer : Socket error");
178       return O1::FAILURE;
179    }
180    /* Give the socket a name. */
181    bzero(&name, sizeof(name));
182    name.sin_family = AF_INET;
183    name.sin_port = htons (mPort);
184    name.sin_addr.s_addr = htonl (INADDR_ANY);
185    if (bind (mSock, (struct sockaddr *) &name, sizeof (name)) < 0)
186    {
187       close(mSock);
188       O1_LOG("\nO1 TcpServer : Bind error");
189       return O1::FAILURE;
190    }
191    return O1::SUCCESS;
192 }
193
194
195 /*******************************************************************
196  *
197  * @brief Start TCP server in thread
198  *
199  * @details
200  *
201  *    Function : start
202  *
203  *    Functionality:
204  *      -  Start TCP server in thread
205  *
206  * @params[in] void
207  * @return true  - success
208  *         false - failure
209  ******************************************************************/
210 bool TcpServer::start()
211 {
212    return (pthread_create(&mThreadId, NULL, task, this) == 0);
213 }
214
215 /*******************************************************************
216  *
217  * @brief A TCP server to handle multiple connection
218  *
219  * @details
220  *
221  *    Function : run
222  *
223  *    Functionality:
224  *      -  A TCP server to handle multiple connection 
225  *         Uses select multiplexing
226  *
227  * @params[in] void
228  * @return true  - success
229  *         false - failure
230  ******************************************************************/
231 bool TcpServer::run()
232 {
233
234    fd_set active_fd_set, read_fd_set;
235    int i;
236    struct sockaddr_in clientName;
237    socklen_t size;
238    bool ret = true;;
239
240    /* Create the socket and set it up to accept connections. */
241    if( makeSocket() == O1::SUCCESS )
242    {
243       if (listen (mSock, 1) < 0)
244       {
245          O1_LOG("\nO1 TcpServer : Listen error");
246          close(mSock);
247          ret = false;
248       }
249       else
250       {
251          /* Initialize the set of active sockets. */
252          FD_ZERO (&active_fd_set);
253          FD_SET (mSock, &active_fd_set);
254
255          while (1)
256          {
257             /* Block until input arrives on one or more active sockets. */
258             read_fd_set = active_fd_set;
259             if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
260             {
261                O1_LOG("\nO1 TcpServer : Select error");
262                close(mSock);
263                ret = false;
264                break;
265             }
266
267             /* Service all the sockets with input pending. */
268             for (i = 0; i < FD_SETSIZE; ++i)
269             {
270                 if (FD_ISSET (i, &read_fd_set))
271                 {
272                    if (i == mSock)
273                    {
274                       /* Connection request on original socket. */
275                       int newFd;
276                       bzero(&clientName, sizeof(clientName));
277                       size = sizeof (clientName);
278                       newFd = accept(mSock,(struct sockaddr *) &clientName,&size);
279                       if (newFd < 0)
280                       {
281                          O1_LOG("\nO1 TcpServer : Accept error");
282                          close(mSock);
283                          ret = false;
284                          break;
285                       }
286                       O1_LOG("\nO1 TcpServer : Connected from host %s, port %hd.\n",
287                           inet_ntoa (clientName.sin_addr),
288                           ntohs (clientName.sin_port));
289                       FD_SET (newFd, &active_fd_set);
290                    }      
291                    else
292                    {
293                       /* Data arriving on an already-connected socket. */
294                       if (readMessage(i) < 0)
295                       {
296                          close (i);
297                          FD_CLR (i, &active_fd_set);
298                       }
299                    }
300                 }    
301              }/* for loop ends */     
302           } /* while(1) ends */
303       } /* else ends */
304    } /* outer if ends */
305    else
306    {
307       ret = false;
308    }
309    return ret;
310 }
311
312
313 /*******************************************************************
314  *
315  * @brief Static function for launching a TCP server instance
316  *        in a thread
317  *
318  * @details
319  *
320  *    Function : task
321  *
322  *    Functionality:
323  *      - Static function for launching a TCP server instance
324  *        in a thread
325  *
326  * @params[in] TcpServer instance
327  * @return void
328  ******************************************************************/
329 void* TcpServer::task(void *args)
330 {
331    TcpServer *tcpServer = (TcpServer*)args;
332    tcpServer->run();
333    return NULL;
334 }
335
336
337 /*******************************************************************
338  *
339  * @brief Wait for the thread to complete in the parent process
340  *
341  * @details
342  *
343  *    Function : wait
344  *
345  *    Functionality:
346  *      - Waits for the thread to complete in the parent process
347  *
348  * @params[in] void
349  * @return true   : success
350  *          false : failure
351  ******************************************************************/
352 bool TcpServer::wait()
353 {
354     return (pthread_join(mThreadId,NULL) == 0);
355 }
356
357
358
359 /**********************************************************************
360          End of file
361 **********************************************************************/