adding overwrite option
[lispflowmapping.git] / mappingservice / implementation / src / main / java / org / opendaylight / lispflowmapping / implementation / lisp / MapServer.java
1 /*
2  * Copyright (c) 2014 Contextream, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.lispflowmapping.implementation.lisp;
10
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import org.apache.commons.lang3.BooleanUtils;
17 import org.opendaylight.lispflowmapping.implementation.authentication.LispAuthenticationUtil;
18 import org.opendaylight.lispflowmapping.implementation.dao.MappingServiceKeyUtil;
19 import org.opendaylight.lispflowmapping.implementation.util.MapNotifyBuilderHelper;
20 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
21 import org.opendaylight.lispflowmapping.interfaces.dao.IMappingServiceKey;
22 import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry;
23 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceRLOC;
24 import org.opendaylight.lispflowmapping.interfaces.dao.MappingServiceValue;
25 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapNotifyHandler;
26 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapServerAsync;
27 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.MapNotify;
28 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.MapRegister;
29 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.eidtolocatorrecords.EidToLocatorRecord;
30 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.lispaddress.LispAddressContainer;
31 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.locatorrecords.LocatorRecord;
32 import org.opendaylight.yang.gen.v1.lispflowmapping.rev131031.mapnotifymessage.MapNotifyBuilder;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 public class MapServer implements IMapServerAsync {
37     private ILispDAO dao;
38     private volatile boolean shouldAuthenticate;
39     private volatile boolean shouldOverwriteRlocs;
40     private volatile boolean shouldIterateMask;
41     protected static final Logger logger = LoggerFactory.getLogger(MapServer.class);
42
43     public MapServer(ILispDAO dao) {
44         this(dao, true);
45     }
46
47     public MapServer(ILispDAO dao, boolean authenticate) {
48         this(dao, authenticate, true);
49     }
50
51     public MapServer(ILispDAO dao, boolean authenticate, boolean iterateAuthenticationMask) {
52         this.dao = dao;
53         this.shouldAuthenticate = authenticate;
54         this.shouldIterateMask = iterateAuthenticationMask;
55     }
56
57     public void handleMapRegister(MapRegister mapRegister, IMapNotifyHandler callback) {
58         if (dao == null) {
59             logger.warn("handleMapRegister called while dao is uninitialized");
60         } else {
61             boolean failed = false;
62             String password = null;
63             for (EidToLocatorRecord eidRecord : mapRegister.getEidToLocatorRecord()) {
64                 if (shouldAuthenticate) {
65                     password = getPassword(eidRecord.getLispAddressContainer(), eidRecord.getMaskLength());
66                     if (!LispAuthenticationUtil.validate(mapRegister, password)) {
67                         logger.warn("Authentication failed");
68                         failed = true;
69                         break;
70                     }
71                 }
72                 IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(eidRecord.getLispAddressContainer(),
73                         eidRecord.getMaskLength());
74                 MappingServiceValue value = null;
75                 Map<String, ?> locators = dao.get(key);
76                 if (locators != null) {
77                     value = (MappingServiceValue) locators.get("value");
78                 }
79                 if (value == null) {
80                     value = new MappingServiceValue();
81                 }
82                 if (value.getRlocs() == null || shouldOverwriteRlocs) {
83                     value.setRlocs(new ArrayList<MappingServiceRLOC>());
84                 }
85
86                 MappingEntry<MappingServiceValue> entry = new MappingEntry<MappingServiceValue>("value", value);
87                 if (eidRecord.getLocatorRecord() != null) {
88                     Map<LocatorRecord, MappingServiceRLOC> currentRLOCs = new HashMap<LocatorRecord, MappingServiceRLOC>();
89                     for (MappingServiceRLOC msr : value.getRlocs()) {
90                         currentRLOCs.put(msr.getRecord(), msr);
91                     }
92
93                     for (LocatorRecord locatorRecord : eidRecord.getLocatorRecord()) {
94                         if (currentRLOCs.containsKey(locatorRecord)) {
95                             currentRLOCs.get(locatorRecord).setAction(eidRecord.getAction()).setAuthoritative(eidRecord.isAuthoritative())
96                                     .setRegisterdDate(new Date(System.currentTimeMillis())).setTtl(eidRecord.getRecordTtl());
97                         } else {
98
99                             value.getRlocs().add(
100                                     new MappingServiceRLOC(locatorRecord, eidRecord.getRecordTtl(), eidRecord.getAction(), eidRecord
101                                             .isAuthoritative()));
102                         }
103                     }
104                 }
105                 dao.put(key, entry);
106
107             }
108             if (!failed) {
109                 MapNotifyBuilder builder = new MapNotifyBuilder();
110                 if (BooleanUtils.isTrue(mapRegister.isWantMapNotify())) {
111                     logger.trace("MapRegister wants MapNotify");
112                     MapNotifyBuilderHelper.setFromMapRegister(builder, mapRegister);
113                     if (shouldAuthenticate) {
114                         builder.setAuthenticationData(LispAuthenticationUtil.createAuthenticationData(builder.build(), password));
115                     }
116                     callback.handleMapNotify(builder.build());
117                 }
118             }
119         }
120     }
121
122     private String getPassword(LispAddressContainer prefix, int maskLength) {
123         while (maskLength >= 0) {
124             IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(prefix, maskLength);
125             Map<String, ?> daoMap = dao.get(key);
126             if (daoMap != null) {
127                 MappingServiceValue value = (MappingServiceValue) daoMap.get("value");
128                 if (value != null && value.getKey() != null) {
129                     return value.getKey();
130                 } else if (shouldIterateMask()) {
131                     maskLength -= 1;
132                 } else {
133                     return null;
134                 }
135             } else {
136                 maskLength -= 1;
137
138             }
139         }
140         return null;
141     }
142
143     public String getAuthenticationKey(LispAddressContainer address, int maskLen) {
144         return getPassword(address, maskLen);
145     }
146
147     public boolean removeAuthenticationKey(LispAddressContainer address, int maskLen) {
148         IMappingServiceKey key = MappingServiceKeyUtil.generateMappingServiceKey(address, maskLen);
149         Map<String, ?> daoMap = dao.get(key);
150         if (daoMap != null) {
151             MappingServiceValue value = (MappingServiceValue) daoMap.get("value");
152             if (value != null) {
153                 value.setKey(null);
154                 if (value.isEmpty()) {
155                     dao.remove(key);
156                 } else {
157                     dao.put(key, new MappingEntry<MappingServiceValue>("value", value));
158                 }
159                 return true;
160             } else {
161                 return false;
162             }
163         } else {
164             return false;
165         }
166     }
167
168     public boolean addAuthenticationKey(LispAddressContainer address, int maskLen, String key) {
169         IMappingServiceKey mappingServiceKey = MappingServiceKeyUtil.generateMappingServiceKey(address, maskLen);
170         Map<String, ?> daoMap = dao.get(mappingServiceKey);
171         MappingServiceValue value = null;
172         if (daoMap != null) {
173             value = (MappingServiceValue) daoMap.get("value");
174             if (value == null) {
175                 value = new MappingServiceValue();
176             }
177         } else {
178             value = new MappingServiceValue();
179         }
180         value.setKey(key);
181         MappingEntry<MappingServiceValue> entry = new MappingEntry<MappingServiceValue>("value", value);
182         dao.put(mappingServiceKey, entry);
183         return true;
184     }
185
186     public boolean shouldAuthenticate() {
187         return shouldAuthenticate;
188     }
189
190     public boolean shouldIterateMask() {
191         return shouldIterateMask;
192     }
193     
194     public boolean shouldOverwriteRlocs() {
195         return shouldOverwriteRlocs;
196     }
197     
198     public void setShouldIterateMask(boolean shouldIterateMask) {
199         this.shouldIterateMask = shouldIterateMask;
200     }
201
202     public void setShouldAuthenticate(boolean shouldAuthenticate) {
203         this.shouldAuthenticate = shouldAuthenticate;
204     }
205     
206     public void setShouldOverwriteRlocs(boolean shouldOverwriteRlocs) {
207         this.shouldOverwriteRlocs = shouldOverwriteRlocs;
208     }
209
210 }