Development of NETCONF RPCs for tr-069 adapter to
[oam/tr069-adapter.git] / acs / cpe / src / main / java / org / commscope / tr069adapter / acs / cpe / handler / DeviceEventHandler.java
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : tr-069-adapter
4  * =================================================================================================
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.
6  * =================================================================================================
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You
9  * may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14  * either express or implied. See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ===============LICENSE_END=======================================================================
17  */
18
19 package org.commscope.tr069adapter.acs.cpe.handler;
20
21 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.CONNECTION_REQUEST;
22 import static org.commscope.tr069adapter.acs.common.utils.AcsConstants.SEPERATOR;
23
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29
30 import javax.servlet.http.HttpServletResponse;
31
32 import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;
33 import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;
34 import org.commscope.tr069adapter.acs.common.OperationResponse;
35 import org.commscope.tr069adapter.acs.common.dto.DeviceOperationRequestDetails;
36 import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode;
37 import org.commscope.tr069adapter.acs.common.exception.SessionManagerException;
38 import org.commscope.tr069adapter.acs.common.exception.TR069EventProcessingException;
39 import org.commscope.tr069adapter.acs.common.inform.AbstractDeviceInform;
40 import org.commscope.tr069adapter.acs.common.inform.TransferCompleteInform;
41 import org.commscope.tr069adapter.acs.common.requestprocessor.service.TR069DeviceEventHandler;
42 import org.commscope.tr069adapter.acs.common.response.DeviceInformResponse;
43 import org.commscope.tr069adapter.acs.common.utils.ErrorCode;
44 import org.commscope.tr069adapter.acs.cpe.TR069RPC;
45 import org.commscope.tr069adapter.acs.cpe.builder.DeviceInformBuilder;
46 import org.commscope.tr069adapter.acs.cpe.builder.DeviceRPCBuilder;
47 import org.commscope.tr069adapter.acs.cpe.builder.DeviceRPCResponseBuilder;
48 import org.commscope.tr069adapter.acs.cpe.rpc.Fault;
49 import org.commscope.tr069adapter.acs.cpe.rpc.Inform;
50 import org.commscope.tr069adapter.acs.cpe.rpc.TransferComplete;
51 import org.commscope.tr069adapter.common.timer.TimerException;
52 import org.commscope.tr069adapter.common.timer.TimerServiceManagerAPI;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.slf4j.MDC;
56 import org.springframework.beans.factory.annotation.Autowired;
57 import org.springframework.stereotype.Component;
58
59 @Component
60 public class DeviceEventHandler {
61
62   private static final Logger logger = LoggerFactory.getLogger(DeviceEventHandler.class);
63   public static final String PATTERN = "[\n|\r|\t]";
64
65   private static final String CLIENT_STR = "client";
66
67   @Autowired
68   private DeviceInformBuilder deviceInformBuilder;
69
70   @Autowired
71   private DeviceRPCBuilder deviceRPCBuilder;
72
73   @Autowired
74   private DeviceRPCResponseBuilder deviceRPCResponseBuilder;
75
76   @Autowired
77   private TR069DeviceEventHandler tr069DeviceEventHandler;
78
79   @Autowired
80   private TimerServiceManagerAPI timerServiceManagerAPI;
81
82   @Autowired
83   private DeviceValidator deviceValidtor;
84
85   private static Map<String, List<String>> informParameter = null;
86
87   static {
88     informParameter = new HashMap<>();
89     List<String> parameters = new ArrayList<>();
90     parameters.add("InternetGatewayDevice.DeviceInfo.HardwareVersion");
91     parameters.add("InternetGatewayDevice.DeviceInfo.SoftwareVersion");
92     parameters.add("InternetGatewayDevice.DeviceInfo.ProvisioningCode");
93     parameters.add("InternetGatewayDevice.ManagementServer.ConnectionRequestURL");
94     parameters.add("InternetGatewayDevice.ManagementServer.ParameterKey");
95     informParameter.put("InternetGatewayDevice", parameters);
96
97     List<String> deviceParameters = new ArrayList<>();
98     deviceParameters.add("Device.DeviceInfo.HardwareVersion");
99     deviceParameters.add("Device.DeviceInfo.SoftwareVersion");
100     deviceParameters.add("Device.DeviceInfo.ProvisioningCode");
101     deviceParameters.add("Device.ManagementServer.ConnectionRequestURL");
102     deviceParameters.add("Device.ManagementServer.ParameterKey");
103     informParameter.put("Device", deviceParameters);
104   }
105
106   /**
107    * @param inform
108    * @param authorizationHeader
109    * @return
110    * @throws TR069EventProcessingException
111    */
112   public DeviceInformResponse processDeviceInform(Inform inform, String authorizationHeader)
113       throws TR069EventProcessingException {
114
115     DeviceInformResponse deviceInformResponse = null;
116     try {
117       String deviceId = inform.getSn();
118       MDC.put(CLIENT_STR, deviceId);
119
120       logger.info("Processing the device Inform event");
121
122       logger.debug("Authorization header received in the request -> {}", authorizationHeader);
123       Boolean isAuthorized = deviceValidtor.isDeviceAuthorized(inform, authorizationHeader);
124       logger.info("Is device authentication successful: {}", isAuthorized);
125       if (!isAuthorized.booleanValue()) {
126         TR069EventProcessingException ex =
127             new TR069EventProcessingException(ErrorCode.UNAUTHORIZED_EVENT, "Authorization failed");
128         String exceptionMessage = ex.getMessage().replaceAll(PATTERN, "_");
129         logger.error(exceptionMessage);
130         throw ex;
131       }
132
133       logger.debug("The root element is: {}", inform.getRoot());
134       // Canceling any connection initiator timer running, due to inform event
135       stopConnectionInitiatorTimer(inform.getSn());
136
137       if (!deviceValidtor.validateDevice(inform.getSn(), inform.getOui(), inform.getProductClass())
138           .booleanValue()) {
139         TR069EventProcessingException ex =
140             new TR069EventProcessingException(ErrorCode.OUI_OR_PC_MISMATCH);
141         logger.error(ex.getMessage());
142         throw ex;
143       }
144
145       if (!validateInformParameters(inform)) {
146         TR069EventProcessingException ex =
147             new TR069EventProcessingException(ErrorCode.INVALID_PARAMS_IN_INFORM);
148         logger.error(ex.getMessage());
149         throw ex;
150       }
151
152       AbstractDeviceInform deviceInform = deviceInformBuilder.constructDeviceInform(inform);
153       if (deviceInform == null) {
154         TR069EventProcessingException ex =
155             new TR069EventProcessingException(ErrorCode.INVALID_PARAMS_IN_INFORM);
156         logger.error(ex.getMessage());
157         throw ex;
158       }
159
160       logger.debug("Sending the device inform to TR069 Request Processor to process");
161       deviceInformResponse = tr069DeviceEventHandler.processDeviceInform(deviceInform);
162
163     } catch (TR069EventProcessingException tr069Ex) {
164       throw tr069Ex;
165     } catch (Exception e) {
166       TR069EventProcessingException ex =
167           new TR069EventProcessingException(ErrorCode.FAILED_PROCESSING_INFORM, e.getMessage());
168       String exceptionMessage = ex.getMessage().replaceAll(PATTERN, "_");
169       logger.error(exceptionMessage);
170       throw ex;
171     } finally {
172       MDC.remove(CLIENT_STR);
173     }
174
175     return deviceInformResponse;
176
177   }
178
179   /**
180    * @param tc
181    * @return
182    * @throws TR069EventProcessingException
183    */
184   public DeviceInformResponse processTransferComplete(TransferComplete tc)
185       throws TR069EventProcessingException {
186
187     logger.debug("Processing Transfer Complete");
188
189     String startTime = tc.getStartTime();
190     String completeTime = tc.getCompleteTime();
191     int faultCode = tc.getFaultCode();
192     String faultString = tc.getFaultString();
193     String commandKey = tc.getCommandKey();
194
195     DeviceInformResponse deviceInformResponse = null;
196
197     try {
198       MDC.put(CLIENT_STR, commandKey);
199       TransferCompleteInform transferCompleteInform = new TransferCompleteInform();
200       transferCompleteInform.setCommandKey(tc.getCommandKey());
201       transferCompleteInform.setCompleteTime(completeTime);
202       transferCompleteInform.setFaultCode(faultCode);
203       transferCompleteInform.setFaultString(faultString);
204       transferCompleteInform.setStartTime(startTime);
205
206       logger.debug("TransferComplete inform received with Start time");
207
208       transferCompleteInform.setDeviceDetails(tr069DeviceEventHandler.getDeviceDetails(commandKey));
209       deviceInformResponse = tr069DeviceEventHandler.processDeviceInform(transferCompleteInform);
210       logger.debug("Successfully processed the TRANSFER COMPLETE Inform");
211
212     } catch (Exception e) {
213       throw new TR069EventProcessingException(ErrorCode.FAILED_PROCESSING_INFORM, e.getMessage());
214     } finally {
215       MDC.remove(CLIENT_STR);
216     }
217
218     return deviceInformResponse;
219   }
220
221   /**
222    * @param msg
223    * @param sessionId
224    * @return
225    * @throws TR069EventProcessingException
226    */
227   public TR069RPC processRPCResponse(TR069RPC msg, String sessionId)
228       throws TR069EventProcessingException {
229     DeviceOperationRequestDetails deviceOperationRequestDetails = null;
230     try {
231       deviceOperationRequestDetails =
232           tr069DeviceEventHandler.getOpRequestDetailsBySessionId(sessionId);
233       if (null == deviceOperationRequestDetails
234           || null == deviceOperationRequestDetails.getDeviceDetails()) {
235         sessionId = sessionId.replaceAll(PATTERN, "_");
236         logger.error("Response with invalid session ID: {}", sessionId);
237         return null;
238       }
239
240       String deviceId = deviceOperationRequestDetails.getDeviceDetails().getDeviceId();
241       MDC.put(CLIENT_STR, deviceId);
242       DeviceRPCResponse deviceRPCResponse = new DeviceRPCResponse();
243       deviceRPCResponse.setDeviceDetails(deviceOperationRequestDetails.getDeviceDetails());
244       deviceRPCResponse.setOperationId(deviceOperationRequestDetails.getOperationId());
245       OperationResponse operationResponse = null;
246       if (msg instanceof Fault) {
247         Fault values = (Fault) msg;
248         logger.info("{} ID->{} faultCode->{} faultString->{}", values.getName(), values.getId(),
249             values.getCwmpFaultCode(), values.getFaultStringCwmp());
250         deviceRPCResponse.setFaultKey(values.getCwmpFaultCode());
251         deviceRPCResponse.setFaultString(
252             values.getFaultStringCwmp() + ": Error code: " + values.getCwmpFaultCode());
253
254         TR069OperationCode operationCode =
255             (TR069OperationCode) deviceOperationRequestDetails.getOpCode();
256         operationResponse = constructResponseForFault(operationCode);
257         if (operationResponse != null) {
258           operationResponse.setStatus(1);
259           operationResponse.setParameterDTOs(new ArrayList<>());
260         }
261       } else {
262         operationResponse = deviceRPCResponseBuilder.constructDeviceRPCResponse(msg);
263       }
264       deviceRPCResponse.setOperationResponse(operationResponse);
265
266       DeviceRPCRequest deviceRPCRequest =
267           tr069DeviceEventHandler.processDeviceRPCResponse(deviceRPCResponse);
268       if (null != deviceRPCRequest) {
269         return deviceRPCBuilder.constructDeviceRPC(deviceRPCRequest);
270       }
271     } catch (SessionManagerException e) {
272       logger.error("Error while getting device detail for the session id: {}", sessionId);
273     } catch (Exception e) {
274       throw new TR069EventProcessingException(ErrorCode.FAILED_PROCESSING_RPC_RESPONSE,
275           msg.getName(), e.getMessage());
276     } finally {
277       MDC.remove(CLIENT_STR);
278     }
279
280     return null;
281   }
282
283   /**
284    * @param sessionId
285    * @return
286    * @throws TR069EventProcessingException
287    */
288   public TR069RPC processEmptyRequest(String sessionId) throws TR069EventProcessingException {
289     try {
290       DeviceOperationRequestDetails deviceOperationRequestDetails =
291           tr069DeviceEventHandler.getOpRequestDetailsBySessionId(sessionId);
292       DeviceRPCRequest deviceRPCRequest = null;
293       String deviceId = deviceOperationRequestDetails.getDeviceDetails().getDeviceId();
294       MDC.put(CLIENT_STR, deviceId);
295       deviceRPCRequest = tr069DeviceEventHandler
296           .processEmptyDeviceRequest(deviceOperationRequestDetails.getDeviceDetails());
297       if (null == deviceRPCRequest) {
298         return null;
299       } else {
300         logger.debug("There exists a NBI request to process.");
301         return deviceRPCBuilder.constructDeviceRPC(deviceRPCRequest);
302       }
303     } catch (SessionManagerException e) {
304       logger.error("Error while processing empty request, reason: {}", e.getMessage());
305     } catch (Exception e) {
306       throw new TR069EventProcessingException(ErrorCode.EMPTY_REQUEST_PROCESSING_ERROR,
307           e.getMessage());
308     } finally {
309       MDC.remove(CLIENT_STR);
310     }
311     return null;
312   }
313
314   /**
315    * @param operationCode
316    * @return
317    */
318   private OperationResponse constructResponseForFault(TR069OperationCode operationCode) {
319     OperationResponse operationResponse = null;
320     if (operationCode.equals(TR069OperationCode.ADD_OBJECT)) {
321       operationResponse = new org.commscope.tr069adapter.acs.common.response.AddObjectResponse();
322     } else if (operationCode.equals(TR069OperationCode.DELETE_OBJECT)) {
323       operationResponse = new org.commscope.tr069adapter.acs.common.response.DeleteObjectResponse();
324     } else if (operationCode.equals(TR069OperationCode.SET_PARAMETER_VALUES)) {
325       operationResponse =
326           new org.commscope.tr069adapter.acs.common.response.SetParameterValueResponse();
327     } else if (operationCode.equals(TR069OperationCode.GET_PARAMETER_VALUES)) {
328       operationResponse =
329           new org.commscope.tr069adapter.acs.common.response.GetParameterValueResponse();
330     } else if (operationCode.equals(TR069OperationCode.GET_PARAMETER_ATTRIBUTES)) {
331       operationResponse =
332           new org.commscope.tr069adapter.acs.common.response.GetParameterAttributeResponse();
333     }
334     return operationResponse;
335   }
336
337   /**
338    * @param serialNumber
339    */
340   public void stopConnectionInitiatorTimer(String serialNumber) {
341     String timerId = serialNumber + SEPERATOR + CONNECTION_REQUEST;
342     try {
343       logger
344           .debug("Canceling the Connection initiation timer, as Inform is been sent by the device");
345       timerServiceManagerAPI.stopTimer(timerId);
346     } catch (TimerException e) {
347       logger.error(
348           "An exception occurred while stopping the connection initiator session timer, Reason: {}",
349           e.getMessage());
350     }
351   }
352
353   /**
354    * @param lastInform
355    * @return
356    */
357   private boolean validateInformParameters(Inform lastInform) {
358     boolean validate = false;
359     String root = lastInform.getRoot();
360     if (!informParameter.containsKey(root))
361       return validate;
362     List<String> params = informParameter.get(root);
363     Set<String> keySet = lastInform.getParams().keySet();
364     validate = true;
365     for (String param : params) {
366       if (!keySet.contains(param)) {
367         logger.warn("This param Not found in the inform {}", param);
368         validate = false;
369         break;
370       }
371     }
372     return validate;
373   }
374
375   /**
376    * @param tr069ex
377    * @return
378    */
379   public int handleException(TR069EventProcessingException tr069ex) {
380
381     int errorresponseCode = 0;
382
383     ErrorCode errorCode = tr069ex.getErrorCode();
384     switch (errorCode) {
385       case UNSUPPORTED_CHARACTER_ENCODING:
386       case INVALID_PARAMS_IN_INFORM:
387       case FAILED_PROCESSING_INFORM:
388         errorresponseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
389         break;
390       case UNAUTHORIZED_EVENT:
391         errorresponseCode = HttpServletResponse.SC_UNAUTHORIZED;
392         break;
393       default:
394         break;
395     }
396
397     return errorresponseCode;
398   }
399
400   /***************************************************************************************************************************/
401
402   public void setDeviceInformBuilder(DeviceInformBuilder deviceInformBuilder) {
403     this.deviceInformBuilder = deviceInformBuilder;
404   }
405
406   public void setDeviceRPCBuilder(DeviceRPCBuilder deviceRPCBuilder) {
407     this.deviceRPCBuilder = deviceRPCBuilder;
408   }
409
410   public void setDeviceRPCResponseBuilder(DeviceRPCResponseBuilder deviceRPCResponseBuilder) {
411     this.deviceRPCResponseBuilder = deviceRPCResponseBuilder;
412   }
413
414   public void setTr069DeviceEventHandler(TR069DeviceEventHandler tr069DeviceEventHandler) {
415     this.tr069DeviceEventHandler = tr069DeviceEventHandler;
416   }
417
418   public void setTimerServiceManagerAPI(TimerServiceManagerAPI timerServiceManagerAPI) {
419     this.timerServiceManagerAPI = timerServiceManagerAPI;
420   }
421
422   public void setDeviceAuthenticator(DeviceValidator deviceAuthenticator) {
423     this.deviceValidtor = deviceAuthenticator;
424   }
425
426 }