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 package org.metricshub.wbem.sblim.slp.internal.sa;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 import java.io.IOException;
48 import java.io.OutputStream;
49 import java.net.DatagramPacket;
50 import java.net.DatagramSocket;
51 import java.net.Socket;
52 import java.net.UnknownHostException;
53 import java.util.List;
54 import org.metricshub.wbem.sblim.slp.ServiceLocationException;
55 import org.metricshub.wbem.sblim.slp.ServiceURL;
56 import org.metricshub.wbem.sblim.slp.internal.IPv6MulticastAddressFactory;
57 import org.metricshub.wbem.sblim.slp.internal.Net;
58 import org.metricshub.wbem.sblim.slp.internal.SLPConfig;
59 import org.metricshub.wbem.sblim.slp.internal.SLPDefaults;
60 import org.metricshub.wbem.sblim.slp.internal.TRC;
61 import org.metricshub.wbem.sblim.slp.internal.msg.AttributeReply;
62 import org.metricshub.wbem.sblim.slp.internal.msg.AttributeRequest;
63 import org.metricshub.wbem.sblim.slp.internal.msg.FunctionIDs;
64 import org.metricshub.wbem.sblim.slp.internal.msg.MsgFactory;
65 import org.metricshub.wbem.sblim.slp.internal.msg.ReplyMessage;
66 import org.metricshub.wbem.sblim.slp.internal.msg.RequestMessage;
67 import org.metricshub.wbem.sblim.slp.internal.msg.SLPMessage;
68 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceAcknowledgment;
69 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceDeregistration;
70 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceRegistration;
71 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceReply;
72 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceRequest;
73 import org.metricshub.wbem.sblim.slp.internal.msg.ServiceTypeReply;
74
75
76
77
78
79 public class ServiceAgent implements FunctionIDs {
80 private boolean iUseV4 = Net.hasIPv4() && SLPConfig.getGlobalCfg().useIPv4(), iUseV6 =
81 Net.hasIPv6() && SLPConfig.getGlobalCfg().useIPv6();
82
83 boolean iStarted;
84
85 private volatile boolean iSkipFirstRequest;
86
87 private DatagramThread iDGThread = new DatagramThread(this);
88
89 private TCPThread iTCPThread = new TCPThread(this);
90
91 private ServiceTable iSrvTable = new ServiceTable(this.iDGThread);
92
93 private MessageTable iMsgTable = new MessageTable();
94
95
96
97
98
99
100
101 public static void main(String[] pArgs) throws IOException {
102 if (pArgs != null && pArgs.length >= 1) {
103 int port = Integer.parseInt(pArgs[0]);
104 SLPConfig.getGlobalCfg().setPort(port);
105 }
106 ServiceAgent srvAgent = new ServiceAgent();
107 srvAgent.start();
108 TRC.debug("starting idle loop");
109 while (true) {
110 try {
111 Thread.sleep(100);
112 } catch (InterruptedException e) {
113
114 }
115 }
116 }
117
118
119
120
121
122
123 public void setSkipFirstRequest(boolean pValue) {
124 this.iSkipFirstRequest = pValue;
125 }
126
127
128
129
130
131
132 public void start() throws IOException {
133 if (this.iStarted) return;
134
135 TRC.debug("start receivers");
136 if (this.iUseV4 || this.iUseV6) {
137 this.iTCPThread.start();
138 this.iDGThread.start();
139 TRC.debug("wait4 TCP init");
140 this.iTCPThread.wait4init();
141 TRC.debug("wait4 Datagram init");
142 this.iDGThread.wait4init();
143 }
144 this.iStarted = true;
145 TRC.debug("receivers started");
146
147 if (this.iUseV4) this.iDGThread.joinGroup(SLPConfig.getMulticastAddress());
148 if (this.iUseV6) {
149 this.iDGThread.joinGroup(IPv6MulticastAddressFactory.getSrvLocAddress(SLPDefaults.IPV6_MULTICAST_SCOPE));
150 }
151 }
152
153
154
155
156 public void stop() {
157
158 if (this.iUseV4 || this.iUseV6) {
159 this.iTCPThread.stop();
160 this.iDGThread.stop();
161 }
162 this.iStarted = false;
163 }
164
165
166
167
168
169
170
171 public void processMessage(DatagramSocket pDGSock, DatagramPacket pPacket) {
172 byte[] reply;
173 SLPMessage msg;
174 try {
175 msg = MsgFactory.parse(pPacket);
176 } catch (Exception e) {
177
178 TRC.debug("Message parsing error!", e);
179 return;
180 }
181
182 try {
183 TRC.debug("processing: " + msg);
184 reply = this.iMsgTable.getResponse(pPacket.getAddress(), msg);
185 if (reply == null) {
186 SLPMessage replyMsg = makeReply(msg);
187 if (replyMsg != null) {
188 TRC.debug("response : " + replyMsg);
189 reply = replyMsg.serialize(false, true, true);
190 this.iMsgTable.addResponse(pPacket.getAddress(), msg, reply);
191
192 if (this.iSkipFirstRequest) {
193 TRC.debug("refusing response");
194 return;
195 }
196 }
197 } else {
198 TRC.debug("cached response");
199 }
200 } catch (ServiceLocationException e) {
201 TRC.debug(e.toString(), e);
202 reply = makeErrorReply(msg, e);
203 }
204 if (reply != null) {
205 try {
206 TRC.debug("sending response");
207 pDGSock.send(new DatagramPacket(reply, reply.length, pPacket.getAddress(), pPacket.getPort()));
208 } catch (IOException e) {
209 TRC.error(e);
210 }
211 }
212 }
213
214
215
216
217
218
219 public void processMessage(Socket pStreamSock) {
220 byte[] reply;
221 SLPMessage msg;
222 try {
223 msg = MsgFactory.parse(pStreamSock.getInputStream());
224 } catch (Exception e) {
225
226 TRC.debug("Message parsing error!", e);
227 return;
228 }
229 try {
230 SLPMessage replyMsg = makeReply(msg);
231 reply = replyMsg == null ? null : replyMsg.serialize(false, false, true);
232 } catch (ServiceLocationException e) {
233 reply = makeErrorReply(msg, e);
234 }
235 if (reply != null) {
236 try {
237 OutputStream os = pStreamSock.getOutputStream();
238 os.write(reply);
239 os.flush();
240 } catch (IOException e) {
241 TRC.error(e);
242 }
243 }
244 try {
245 pStreamSock.close();
246 } catch (IOException e) {
247 TRC.error(e);
248 }
249 }
250
251
252
253
254
255
256
257 private SLPMessage makeReply(SLPMessage pRequest) throws ServiceLocationException {
258 try {
259 SLPMessage msg = pRequest instanceof RequestMessage
260 ? makeReply4Request((RequestMessage) pRequest)
261 : makeReply4Others(pRequest);
262 if (msg != null) msg.setXID(pRequest.getXID());
263 return msg;
264 } catch (UnknownHostException e) {
265 TRC.error(e);
266 throw new ServiceLocationException(ServiceLocationException.NETWORK_ERROR);
267 } catch (IOException e) {
268 TRC.error(e);
269 throw new ServiceLocationException(ServiceLocationException.NETWORK_ERROR);
270 }
271 }
272
273 private ReplyMessage makeReply4Request(RequestMessage pRequest) {
274 ReplyMessage replyMsg;
275 List<String> scopes = pRequest.getScopeList();
276 switch (pRequest.getFunctionID()) {
277 case SRV_RQST:
278 ServiceRequest srvRqst = (ServiceRequest) pRequest;
279 if (SLPDefaults.DA_SERVICE_TYPE.equals(srvRqst.getServiceType())) return null;
280 List<ServiceURL> urlList = this.iSrvTable.getServiceURLs(srvRqst.getServiceType(), scopes);
281 TRC.debug("srvReply : " + urlList);
282 replyMsg = new ServiceReply(0, urlList);
283 break;
284 case ATTR_RQST:
285 AttributeRequest attrRqst = (AttributeRequest) pRequest;
286 replyMsg = new AttributeReply(0, this.iSrvTable.getAttributes(attrRqst.getServiceURL(), scopes));
287 break;
288 case SRV_TYPE_RQST:
289
290
291 replyMsg = new ServiceTypeReply(0, this.iSrvTable.getServiceTypes(scopes));
292 break;
293 default:
294 return null;
295 }
296 return replyMsg;
297 }
298
299 private SLPMessage makeReply4Others(SLPMessage pRequest) throws IOException {
300 switch (pRequest.getFunctionID()) {
301 case SRV_REG:
302 ServiceRegistration srvReg = (ServiceRegistration) pRequest;
303 this.iSrvTable.add(srvReg.getServiceURL(), srvReg.getAttributeList(), srvReg.getScopeList());
304 return new ServiceAcknowledgment(0);
305 case SRV_DEREG:
306 ServiceDeregistration srvDereg = (ServiceDeregistration) pRequest;
307 this.iSrvTable.remove(srvDereg.getServiceURL());
308 return new ServiceAcknowledgment(0);
309 default:
310
311 return null;
312 }
313 }
314
315 private static byte[] makeErrorReply(SLPMessage pRequest, ServiceLocationException pE) {
316 return makeErrorReply(pRequest, pE.getErrorCode());
317 }
318
319
320
321
322
323
324 private static byte[] makeErrorReply(SLPMessage pRequest, int pErrorCode) {
325 ReplyMessage replyMsg;
326 switch (pRequest.getFunctionID()) {
327 case SRV_RQST:
328 replyMsg = new ServiceReply(pErrorCode, null);
329 break;
330 case ATTR_RQST:
331 replyMsg = new AttributeReply(pErrorCode, null);
332 break;
333 case SRV_TYPE_RQST:
334 replyMsg = new ServiceTypeReply(pErrorCode, null);
335 break;
336 case SRV_REG:
337 case SRV_DEREG:
338 replyMsg = new ServiceAcknowledgment(pErrorCode);
339 break;
340 default:
341 return null;
342 }
343 replyMsg.setXID(pRequest.getXID());
344 try {
345 return replyMsg.serialize(false, true, true);
346 } catch (ServiceLocationException se) {
347 TRC.error(se);
348 return null;
349 }
350 }
351 }