1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.metricshub.wbem.sblim.slp.internal.sa;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 import java.net.InetAddress;
50 import java.util.Arrays;
51 import java.util.Date;
52 import java.util.SortedMap;
53 import java.util.TreeMap;
54 import org.metricshub.wbem.sblim.slp.ServiceLocationException;
55 import org.metricshub.wbem.sblim.slp.internal.msg.RequestMessage;
56 import org.metricshub.wbem.sblim.slp.internal.msg.SLPMessage;
57
58
59
60
61
62
63 public class MessageTable {
64
65 private static class RequestDescriptor implements Comparable<RequestDescriptor> {
66 private byte[] iSrcAddress;
67
68 private byte[] iRequest;
69
70
71
72
73
74
75
76
77 public RequestDescriptor(InetAddress pSource, SLPMessage pRequest) throws ServiceLocationException {
78 this.iSrcAddress = pSource.getAddress();
79 this.iRequest =
80 (pRequest instanceof RequestMessage)
81 ? ((RequestMessage) pRequest).serializeWithoutResponders(false, true, true)
82 : pRequest.serialize(false, true, true);
83 }
84
85 public int compareTo(RequestDescriptor pObj) {
86 RequestDescriptor that = pObj;
87 int cmp = compare(this.iSrcAddress, that.iSrcAddress);
88 if (cmp != 0) return cmp;
89 return compare(this.iRequest, that.iRequest);
90 }
91
92 private static int compare(byte[] pBytes0, byte[] pBytes1) {
93 int len = Math.min(pBytes0.length, pBytes1.length);
94 for (int i = 0; i < len; i++) {
95 int cmp = pBytes0[i] & 0xff - pBytes1[i] & 0xff;
96 if (cmp != 0) return cmp;
97 }
98 return pBytes0.length - pBytes1.length;
99 }
100
101 @Override
102 public boolean equals(Object pObj) {
103 if (!(pObj instanceof RequestDescriptor)) return false;
104 RequestDescriptor that = (RequestDescriptor) pObj;
105 return compare(this.iSrcAddress, that.iSrcAddress) == 0 && compare(this.iRequest, that.iRequest) == 0;
106 }
107
108 @Override
109 public int hashCode() {
110 return Arrays.hashCode(this.iSrcAddress) + Arrays.hashCode(this.iRequest);
111 }
112 }
113
114 private static class TableEntry {
115 private long iTime;
116
117 private RequestDescriptor iReqDesc;
118
119 private byte[] iResponse;
120
121
122
123
124
125
126
127
128 public TableEntry(long pTime, RequestDescriptor pReqKey, byte[] pResponse) {
129 this.iTime = pTime;
130 this.iReqDesc = pReqKey;
131 this.iResponse = pResponse;
132 }
133
134
135
136
137
138
139 public long getTime() {
140 return this.iTime;
141 }
142
143
144
145
146
147
148 public void setTime(long pTime) {
149 this.iTime = pTime;
150 }
151
152
153
154
155
156
157 public RequestDescriptor getRequestDescriptor() {
158 return this.iReqDesc;
159 }
160
161
162
163
164
165
166 public byte[] getResponse() {
167 return this.iResponse;
168 }
169 }
170
171
172
173
174 private static final long KEEPIN = 30;
175
176
177
178
179 private SortedMap<Long, TableEntry> iTimeMap = new TreeMap<Long, TableEntry>();
180
181
182
183
184 private SortedMap<RequestDescriptor, TableEntry> iReqMap = new TreeMap<RequestDescriptor, TableEntry>();
185
186
187
188
189
190
191
192
193
194 public synchronized byte[] getResponse(InetAddress pSource, SLPMessage pRequest) throws ServiceLocationException {
195 long now = getSecs();
196 RequestDescriptor reqDesc = new RequestDescriptor(pSource, pRequest);
197 TableEntry entry = this.iReqMap.get(reqDesc);
198 if (entry == null) return null;
199 clean();
200 updateTime(entry, now);
201 return entry.getResponse();
202 }
203
204
205
206
207
208
209
210
211
212 public synchronized void addResponse(InetAddress pSource, SLPMessage pRequest, byte[] pRespond)
213 throws ServiceLocationException {
214 insert(new TableEntry(getSecs(), new RequestDescriptor(pSource, pRequest), pRespond));
215 clean();
216 }
217
218 private void clean() {
219 long now = getSecs();
220 Long timeStamp;
221 while ((timeStamp = this.iTimeMap.firstKey()) != null) {
222 if (now - timeStamp.longValue() < KEEPIN) break;
223 TableEntry entry = this.iTimeMap.get(timeStamp);
224 remove(entry);
225 }
226 }
227
228 private void insert(TableEntry pEntry) {
229 this.iTimeMap.put(Long.valueOf(pEntry.getTime()), pEntry);
230 this.iReqMap.put(pEntry.getRequestDescriptor(), pEntry);
231 }
232
233 private void remove(TableEntry pEntry) {
234 this.iTimeMap.remove(Long.valueOf(pEntry.getTime()));
235 this.iReqMap.remove(pEntry.getRequestDescriptor());
236 }
237
238 private void updateTime(TableEntry pEntry, long pTime) {
239 remove(pEntry);
240 pEntry.setTime(pTime);
241 insert(pEntry);
242 }
243
244 private static long getSecs() {
245 return new Date().getTime() / 1000;
246 }
247 }