47ce09475cdd310213c091e2e963d7c837778de9
[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 "GlobalDefs.hpp"
28 #include <iostream>
29 #include <cstdio>
30 #include <cerrno>
31 #include <cstdlib>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netdb.h>
37 #include <arpa/inet.h>
38
39 using std::map;
40 using std::pair;
41
42 /* Destructor */
43 TcpServer::~TcpServer()
44 {
45
46 }
47
48
49 /********************************************************************** 
50    Description : Read the data from the connected client application 
51    Params[In]  : fd - File descriptor
52    Return      : int - No of bytes read 
53 **********************************************************************/
54 int TcpServer::readMessage(int fd)
55 {
56    AlarmRecord alrmRec;
57    bzero(&alrmRec,sizeof(alrmRec));
58    int nbytes = read (fd, &alrmRec, sizeof(alrmRec));
59    if (nbytes > 0)
60    {
61       Alarm alrm;
62       uint16_t alrmId;
63       O1_LOG("\nO1 TcpServer :\nAction %d\nalarm ID %s\n%d\n%s\n%d\n%s\n%s\nbytes %d",
64                      alrmRec.msgHeader.action,
65                      alrmRec.alarmId,
66                      alrmRec.perceivedSeverity,
67                      alrmRec.additionalText,
68                      alrmRec.eventType,
69                      alrmRec.specificProblem,
70                      alrmRec.additionalInfo,
71                      nbytes
72                      );
73       
74       /*Fill the alarm structure */
75       sscanf(alrmRec.alarmId,"%hu",&alrmId);
76       alrm.setAlarmId(alrmId);
77       alrm.setPerceivedSeverity(alrmRec.perceivedSeverity);
78       alrm.setAdditionalText(alrmRec.additionalText);
79       alrm.setEventType(alrmRec.eventType);
80       alrm.setSpecificProblem(alrmRec.specificProblem);
81       alrm.setAdditionalInfo(alrmRec.additionalInfo);
82
83       switch(alrmRec.msgHeader.action)
84       {
85          case RAISE: 
86                      if(AlarmManager::instance().raiseAlarm(alrm))
87                      {
88                         O1_LOG("\nO1 TcpServer : Alarm raised for alarm Id %s", alrmRec.alarmId);
89                      }
90                      else
91                      {
92                         O1_LOG("\nO1 TcpServer : Error in raising alarm for alrm Id %s", alrmRec.alarmId);
93                      }
94                      break;  
95          case CLEAR: 
96                      if(AlarmManager::instance().clearAlarm(alrm))
97                      {
98                         O1_LOG("\nO1 TcpServer : Alarm cleared for alarm Id %s", alrmRec.alarmId);
99                      }
100                      else
101                      {
102                         O1_LOG("\nO1 TcpServer : Error in clearing alarm for alarm Id %s", alrmRec.alarmId);
103                      }
104                      break;
105          default:    
106                      O1_LOG("\nO1 TcpServer : No action performed"); 
107                      break;
108       }
109
110    }
111    return nbytes;
112 }
113
114
115 /********************************************************************** 
116    Description : Open a TCP socket and bind on the port
117    Params[In]  : None
118    Return      : O1::SUCCESS - socket open and bind successful
119                  O1::FAILURE - socket open and bind failed
120 **********************************************************************/
121 int TcpServer::makeSocket() 
122 {
123    struct sockaddr_in name;
124    /* Create the socket. */
125    mSock = socket (PF_INET, SOCK_STREAM, 0);
126    if (mSock < 0)
127    {
128       O1_LOG("\nO1 TcpServer : Socket error");
129       return O1::FAILURE;
130    }
131    /* Give the socket a name. */
132    bzero(&name, sizeof(name));
133    name.sin_family = AF_INET;
134    name.sin_port = htons (mPort);
135    name.sin_addr.s_addr = htonl (INADDR_ANY);
136    if (bind (mSock, (struct sockaddr *) &name, sizeof (name)) < 0)
137    {
138       close(mSock);
139       O1_LOG("\nO1 TcpServer : Bind error");
140       return O1::FAILURE;
141    }
142    return O1::SUCCESS;
143 }
144
145
146 /********************************************************************** 
147    Description : Start TCP server in thread    
148    Params[In]  : None
149    Return      : true  - task launched in pthread successfully
150                  false - task failed to launch
151 **********************************************************************/
152 bool TcpServer::start()
153 {
154    return (pthread_create(&mThreadId, NULL, task, this) == 0);
155 }
156
157 /********************************************************************** 
158    Description : A TCP server to handle multiple connection using
159                  select multiplexing    
160    Params[In]  : None
161    Return      : true  - task launched in pthread successfully
162                  false - task failed to launch
163 **********************************************************************/
164 bool TcpServer::run()
165 {
166
167    fd_set active_fd_set, read_fd_set;
168    int i;
169    struct sockaddr_in clientName;
170    socklen_t size;
171    bool ret = true;;
172
173    /* Create the socket and set it up to accept connections. */
174    if( makeSocket() == O1::SUCCESS )
175    {
176       if (listen (mSock, 1) < 0)
177       {
178          O1_LOG("\nO1 TcpServer : Listen error");
179          close(mSock);
180          ret = false;
181       }
182       else
183       {
184          /* Initialize the set of active sockets. */
185          FD_ZERO (&active_fd_set);
186          FD_SET (mSock, &active_fd_set);
187
188          while (1)
189          {
190             /* Block until input arrives on one or more active sockets. */
191             read_fd_set = active_fd_set;
192             if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
193             {
194                O1_LOG("\nO1 TcpServer : Select error");
195                close(mSock);
196                ret = false;
197                break;
198             }
199
200             /* Service all the sockets with input pending. */
201             for (i = 0; i < FD_SETSIZE; ++i)
202             {
203                 if (FD_ISSET (i, &read_fd_set))
204                 {
205                    if (i == mSock)
206                    {
207                       /* Connection request on original socket. */
208                       int newFd;
209                       bzero(&clientName, sizeof(clientName));
210                       size = sizeof (clientName);
211                       newFd = accept(mSock,(struct sockaddr *) &clientName,&size);
212                       if (newFd < 0)
213                       {
214                          O1_LOG("\nO1 TcpServer : Accept error");
215                          close(mSock);
216                          ret = false;
217                          break;
218                       }
219                       O1_LOG("\nO1 TcpServer : Connected from host %s, port %hd.\n",
220                           inet_ntoa (clientName.sin_addr),
221                           ntohs (clientName.sin_port));
222                       FD_SET (newFd, &active_fd_set);
223                    }      
224                    else
225                    {
226                       /* Data arriving on an already-connected socket. */
227                       if (readMessage(i) < 0)
228                       {
229                          close (i);
230                          FD_CLR (i, &active_fd_set);
231                       }
232                    }
233                 }    
234              }/* for loop ends */     
235           } /* while(1) ends */
236       } /* else ends */
237    } /* outer if ends */
238    else
239    {
240       ret = false;
241    }
242    return ret;
243 }
244
245
246 /********************************************************************** 
247    Description : Static function for launching a TCP server instance 
248                  in a thread    
249    Params[In]  : TcpServer instance
250    Return      : NULL
251 **********************************************************************/
252 void* TcpServer::task(void *args)
253 {
254    TcpServer *tcpServer = (TcpServer*)args;
255    tcpServer->run();
256    return NULL;
257 }
258
259
260 /********************************************************************** 
261    Description : Wait for the thread to complete in the parent process   
262    Params[In]  : None
263    Return      : true  - pthread join success
264                  false - pthread join failed
265 **********************************************************************/
266 bool TcpServer::wait()
267 {
268     return (pthread_join(mThreadId,NULL) == 0);
269 }
270
271
272
273 /**********************************************************************
274          End of file
275 **********************************************************************/