20 | * // You could implements ISSDPMessageHandler or override SSDPDefaultMessageHandler
21 | *
22 | * ISSDPMessageHandler listener = new SSDPDefaultMessageHandler(){
23 | * @Override
24 | * public void processSSDPAliveMessage(AliveMessage ssdpMessage)
25 | * throws Exception {
26 | * // log message here
27 | * }
28 | * };
29 | *
30 | * @author Sebastien Dionne
31 | */
32 | public class SSDPDefaultMessageHandler implements ISSDPMessageHandler {
33 | private static Logger logger = Logger.getLogger(SSDPDefaultMessageHandler.class.getName());
34 |
35 | /**
36 | * {@inheritDoc}
37 | */
38 | @Override
39 | public void processSSDPAliveMessage(AliveMessage ssdpMessage) throws Exception {
40 | logger.warning("not implemented");
41 | }
42 |
43 | /**
44 | * {@inheritDoc}
45 | */
46 | @Override
47 | public void processSSDPByeByeMessage(ByeByeMessage ssdpMessage) throws Exception {
48 | logger.warning("not implemented");
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | */
54 | @Override
55 | public void processSSDPDiscoverMessage(String remoteAddr, int remotePort, DiscoverMessage ssdpMessage) throws Exception {
56 | logger.warning("not implemented");
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | @Override
63 | public void processSSDPUpdateMessage(UpdateMessage ssdpMessage) throws Exception {
64 | logger.warning("not implemented");
65 | }
66 |
67 | /**
68 | * {@inheritDoc}
69 | */
70 | @Override
71 | public void processSSDPDiscoverResponseMessage(DiscoverResponseMessage ssdpMessage) throws Exception {
72 | logger.warning("not implemented");
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/handler/SSDPDefaultResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.handler;
2 |
3 | import java.util.logging.Logger;
4 |
5 | import com.jerabi.ssdp.ISSDPControler;
6 | import com.jerabi.ssdp.message.ISSDPMessage;
7 | import com.jerabi.ssdp.message.helper.SSDPMessageHelper;
8 |
9 | /**
10 | * Provides a API to handle raw messages received.
11 | *
12 | * Normally the handle methods call {@link com.jerabi.ssdp.ISSDPControler} to process
13 | * the message and it call be used to filter the messages received.
14 | *
15 | * {@link com.jerabi.ssdp.handler.SSDPDiscoverResponseHandler} is a good
16 | * example of a ISSDPHandler that doesn't process DiscoverMessage (M-SEARCH)
17 | *
18 | * This class look like {@link ISSDPMessageHandler} but ISSDPMessageHandler actually process a {@link com.jerabi.ssdp.message.ISSDPMessage}
19 | * generated from the raw message received by this ISSDPHandler. Once a ISSDPMessage is generated, it's passed to the {@link com.jerabi.ssdp.ISSDPControler}.
20 | *
21 | * @author Sebastien Dionne
22 | * @see ISSDPMessageHandler
23 | */
24 | public class SSDPDefaultResponseHandler implements ISSDPResponseHandler {
25 | private Logger logger = Logger.getLogger(SSDPDefaultResponseHandler.class.getName());
26 |
27 | protected ISSDPControler controler = null;
28 |
29 | /**
30 | * Constructor
31 | * @param controler that will process {@link ISSDPMessage}
32 | */
33 | public SSDPDefaultResponseHandler(ISSDPControler controler) {
34 | this.controler = controler;
35 | }
36 |
37 | /**
38 | * {@inheritDoc}
39 | */
40 | @Override
41 | public ISSDPControler getSSDPControler() {
42 | return controler;
43 | }
44 |
45 | /**
46 | * {@inheritDoc}
47 | */
48 | @Override
49 | public void setSSDPControler(ISSDPControler controler) {
50 | this.controler = controler;
51 | }
52 |
53 | /**
54 | * {@inheritDoc}
55 | * The message received will be converted to ISSDPMessage
56 | * {@link SSDPMessageHelper#getSSDPMessage(String)}.
57 | *
58 | * The ISSDPMessage will be process by the ISSDPControler
59 | */
60 | public void handle(String message) throws Exception {
61 |
62 | logger.info("\n" + message);
63 |
64 | ISSDPMessage ssdpMessage = SSDPMessageHelper.getSSDPMessage(message);
65 |
66 | if(ssdpMessage!=null && controler!=null){
67 | controler.processSSDPMessage(ssdpMessage);
68 | }
69 |
70 | }
71 |
72 | /**
73 | * {@inheritDoc}
74 | * The message received will be converted to ISSDPMessage
75 | * {@link SSDPMessageHelper#getSSDPMessage(String)}.
76 | *
77 | * The ISSDPMessage will be process by the ISSDPControler
78 | */
79 | @Override
80 | public void handle(String remoteAddr, int remotePort, String message) throws Exception {
81 | logger.info("\n" + message);
82 |
83 | ISSDPMessage ssdpMessage = SSDPMessageHelper.getSSDPMessage(message);
84 |
85 | if(ssdpMessage!=null && controler!=null){
86 | controler.processSSDPMessage(remoteAddr, remotePort, ssdpMessage);
87 | }
88 |
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/handler/SSDPDiscoverResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.handler;
2 |
3 | import java.util.logging.Logger;
4 |
5 | import com.jerabi.ssdp.ISSDPControler;
6 | import com.jerabi.ssdp.message.ISSDPMessage;
7 | import com.jerabi.ssdp.message.helper.SSDPMessageHelper;
8 |
9 | /**
10 | * Provides a API to handle raw messages received but don't process DiscoverMessage (M-SEARCH).
11 | *
12 | * Normally the handle methods call {@link com.jerabi.ssdp.ISSDPControler} to process
13 | * the message and it call be used to filter the messages received.
14 | *
15 | * It should be used when you sending DiscoverMessage and don't want to handle the DiscoverMessage that you just sent.
16 | *
17 | * If you want to receive theses DiscoverMessage or change the filters to exclude messages, you could use {@link SSDPDefaultResponseHandler} instead.
18 | *
19 | * This class look like {@link ISSDPMessageHandler} but ISSDPMessageHandler actually process a {@link com.jerabi.ssdp.message.ISSDPMessage}
20 | * generated from the raw message received by this ISSDPHandler. Once a ISSDPMessage is generated, it's passed to the {@link com.jerabi.ssdp.ISSDPControler}.
21 | *
22 | * @author Sebastien Dionne
23 | * @see SSDPDefaultResponseHandler
24 | */
25 | public class SSDPDiscoverResponseHandler extends SSDPDefaultResponseHandler {
26 | private Logger logger = Logger.getLogger(SSDPDiscoverResponseHandler.class.getName());
27 |
28 | /**
29 | * Constructor
30 | * @param controler ISSDPControler that will process the {@link ISSDPMessage}.
31 | */
32 | public SSDPDiscoverResponseHandler(ISSDPControler controler) {
33 | super(controler);
34 | }
35 |
36 | /**
37 | * {@inheritDoc}
38 | * Exclude DiscoverMessage
39 | */
40 | @Override
41 | public void handle(String message) throws Exception {
42 |
43 | // we shouldn't received M_SEARCH.. but just in case, we skip it.
44 | if(message!=null && !message.startsWith("M-SEARCH")){
45 | logger.info("\n" + message);
46 |
47 | ISSDPMessage ssdpMessage = SSDPMessageHelper.getSSDPMessage(message);
48 |
49 | if(ssdpMessage!=null && controler!=null){
50 | controler.processSSDPMessage(ssdpMessage);
51 | }
52 |
53 | }
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/listener/SSDPMulticastListener.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.listener;
2 |
3 | import java.net.InetAddress;
4 | import java.net.InetSocketAddress;
5 | import java.net.NetworkInterface;
6 | import java.net.SocketTimeoutException;
7 | import java.util.List;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | import com.jerabi.ssdp.handler.ISSDPResponseHandler;
12 | import com.jerabi.ssdp.network.IMulticastListener;
13 | import com.jerabi.ssdp.network.SSDPNetworkFactory;
14 | import com.jerabi.ssdp.util.SSDPContants;
15 | import com.jerabi.ssdp.util.State;
16 | import com.jerabi.ssdp.util.StateHolder;
17 |
18 | /**
19 | * Provides API to listen for multicast messages over network.
20 | *
21 | * @author Sebastien Dionne
22 | * @example.
23 | *
24 | * // You need pass a ISSDPHandler to handle the multicast messages received.
25 | * SSDPMulticastListener listener = new SSDPMulticastListener(SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT, true);
26 | * listener.setSSDPHandler(new SSDPDefaultHandler(controler));
27 | * t = new Thread(listener);
28 | * t.start();
29 | *
30 | * // using multiples Network Interfaces
31 | *
32 | // You need pass a ISSDPHandler to handle the multicast messages received.
33 | * List networkInterfaceList = new ArrayList();
34 | * networkInterfaceList.add(NetworkInterface.getByName("eth0"));
35 | * SSDPMulticastListener listener = new SSDPMulticastListener(new InetSocketAddress(SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT), networkInterfaceList);
36 | * listener.setSSDPHandler(new SSDPDefaultHandler(controler));
37 | * t = new Thread(listener);
38 | * t.start();
39 | *
40 | *
41 | */
42 | public class SSDPMulticastListener implements Runnable {
43 | private static final Logger logger = Logger.getLogger(SSDPMulticastListener.class.getName());
44 |
45 | protected StateHolder stateHolder = new StateHolder();
46 |
47 | protected int timeout = SSDPContants.DEFAULT_SOCKET_TIMEOUT;
48 | protected String host = null;
49 | protected int port;
50 | protected InetSocketAddress socketAddress = null;
51 | protected List networkInterfaceList = null;
52 | private ISSDPResponseHandler handler = null;
53 | protected boolean blocking = true;
54 |
55 | /**
56 | * Constructor with default delay and listener in blocking mode
57 | * @param host Multicast IP
58 | * @param port Multicast Port
59 | */
60 | public SSDPMulticastListener(String host, int port) {
61 | this(host, port, SSDPContants.DEFAULT_SOCKET_TIMEOUT, true);
62 | }
63 |
64 | /**
65 | * Constructor with listener in blocking mode
66 | * @param host Multicast IP
67 | * @param port Multicast Port
68 | * @param timeout timeout for the non blocking mode
69 | */
70 | public SSDPMulticastListener(String host, int port, int timeout) {
71 | this(host, port, timeout, true);
72 | }
73 |
74 | /**
75 | * Constructor with custom values
76 | * @param host Multicast IP
77 | * @param port Multicast Port
78 | * @param timeout timeout for the non blocking mode
79 | * @param blocking is it in blocking mode
80 | */
81 | public SSDPMulticastListener(String host, int port, int timeout, boolean blocking) {
82 | this.host = host;
83 | this.port = port;
84 | this.timeout = timeout;
85 | this.blocking = blocking;
86 |
87 | setState(State.STOPPED);
88 | }
89 |
90 | /**
91 | * Constructor with default delay and listener in blocking mode
92 | * @param host Multicast IP
93 | * @param port Multicast Port
94 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
95 | */
96 | public SSDPMulticastListener(String host, int port, List networkInterfaceList) {
97 | this(host, port, networkInterfaceList, SSDPContants.DEFAULT_SOCKET_TIMEOUT, true);
98 | }
99 |
100 | /**
101 | * Constructor with listener in blocking mode
102 | * @param host Multicast IP
103 | * @param port Multicast Port
104 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
105 | * @param timeout timeout for the non blocking mode
106 | */
107 | public SSDPMulticastListener(String host, int port, List networkInterfaceList, int timeout) {
108 | this(host, port, networkInterfaceList, timeout, true);
109 | }
110 |
111 | /**
112 | * Constructor with custom values
113 | * @param host Multicast IP
114 | * @param port Multicast Port
115 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
116 | * @param timeout timeout for the non blocking mode
117 | * @param blocking is it in blocking mode
118 | */
119 | public SSDPMulticastListener(String host, int port, List networkInterfaceList, int timeout, boolean blocking) {
120 | this.host = host;
121 | this.port = port;
122 | this.networkInterfaceList = networkInterfaceList;
123 | this.timeout = timeout;
124 | this.blocking = blocking;
125 |
126 | socketAddress = new InetSocketAddress(host, port);
127 |
128 | setState(State.STOPPED);
129 | }
130 |
131 | /**
132 | * Constructor with default delay and listener in blocking mode
133 | * @param socketAddress Multicast IP and port
134 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
135 | */
136 | public SSDPMulticastListener(InetSocketAddress socketAddress, List networkInterfaceList) {
137 | this(socketAddress, networkInterfaceList, SSDPContants.DEFAULT_SOCKET_TIMEOUT, true);
138 | }
139 |
140 | /**
141 | * Constructor with default delay and listener in blocking mode
142 | * @param socketAddress Multicast IP and port
143 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
144 | * * @param timeout timeout for the non blocking mode
145 | */
146 | public SSDPMulticastListener(InetSocketAddress socketAddress, List networkInterfaceList, int timeout) {
147 | this(socketAddress, networkInterfaceList, timeout, true);
148 | }
149 |
150 | /**
151 | * Constructor with default delay and listener in blocking mode
152 | * @param socketAddress Multicast IP and port
153 | * @param networkInterfaceList NetworkInterfaces that will be used to listen
154 | * @param timeout timeout for the non blocking mode
155 | * @param blocking is it in blocking mode
156 | */
157 | public SSDPMulticastListener(InetSocketAddress socketAddress, List networkInterfaceList, int timeout, boolean blocking) {
158 | this.socketAddress = socketAddress;
159 | this.networkInterfaceList = networkInterfaceList;
160 | this.timeout = timeout;
161 | this.blocking = blocking;
162 |
163 | setState(State.STOPPED);
164 | }
165 |
166 | /**
167 | * Returns the ISSDPHandler that handle the multicast messages received
168 | * @return the handler
169 | */
170 | public ISSDPResponseHandler getSSDPResponseHandler() {
171 | return handler;
172 | }
173 |
174 | /**
175 | * Sets the ISSDPHandler that will handle the multicast messages received
176 | * @param handler
177 | */
178 | public void setSSDPResponseHandler(ISSDPResponseHandler handler) {
179 | this.handler = handler;
180 | }
181 |
182 | /**
183 | * Returns the current state of this listener
184 | * @return the current state
185 | */
186 | public State getState() {
187 | return stateHolder.getState();
188 | }
189 |
190 | /**
191 | * Sets a new state for this listener
192 | * @param state new State
193 | */
194 | public void setState(State state) {
195 | this.stateHolder.setState(state);
196 | }
197 |
198 | /**
199 | * Returns the timeout of the non blocking mode
200 | * @return timeout in ms.
201 | */
202 | public int getTimeout() {
203 | return timeout;
204 | }
205 |
206 | /**
207 | * Sets the timeout for the non blocking mode
208 | * @param timeout value in ms.
209 | */
210 | public void setTimeout(int timeout) {
211 | this.timeout = timeout;
212 | }
213 |
214 | /**
215 | * Returns the Multicast Address on which this listener listen
216 | * @return the IP.
217 | */
218 | public String getHost() {
219 | return host;
220 | }
221 |
222 | /**
223 | * Sets the Multicast Address on which this listener will listen
224 | * @param host the IP
225 | */
226 | public void setHost(String host) {
227 | this.host = host;
228 | }
229 |
230 | /**
231 | * Returns the Multicast Port on which this listener listen
232 | * @return the port.
233 | */
234 | public int getPort() {
235 | return port;
236 | }
237 |
238 | /**
239 | * Sets the Multicast Port on which this listener will listen
240 | * @param port the port
241 | */
242 | public void setPort(int port) {
243 | this.port = port;
244 | }
245 |
246 | /**
247 | * Sets this listener in blocking mode or non blocking.
248 | *
249 | * In blocking mode this listener will block until a message is received.
250 | * In non blocking mode this listener will wait until the timeout value and loop back again.
251 | * In non blocking mode this listener can be stopped when the timeout expired, and in blocking mode,
252 | * the listener need to receive a message before changing state.
253 | *
254 | * @param blocking is blocking mode enabled
255 | */
256 | public void setBlocking(boolean blocking){
257 | this.blocking = blocking;
258 | }
259 |
260 | /**
261 | * Returns the blocking mode of this listener
262 | *
263 | * In blocking mode this listener will block until a message is received.
264 | * In non blocking mode this listener will wait until the timeout value and loop back again.
265 | * In non blocking mode this listener can be stopped when the timeout expired, and in blocking mode,
266 | * the listener need to receive a message before changing state.
267 | *
268 | * @return is it blocking mode enabled
269 | */
270 | public boolean getBlocking(){
271 | return blocking;
272 | }
273 |
274 | @Override
275 | public void run() {
276 |
277 | stateHolder.setState(State.STARTED);
278 |
279 | IMulticastListener listener = null;
280 | InetAddress group = null;
281 |
282 | try {
283 |
284 | // if NetworkInterface are used, we can join on multiple groups
285 | if(networkInterfaceList!=null && !networkInterfaceList.isEmpty()){
286 | //listener = SSDPNetworkFactory.getInstance().createMulticastListener(socketAddress, handler);
287 | listener = SSDPNetworkFactory.getInstance().createMulticastListener(socketAddress.getPort(), handler);
288 | for (NetworkInterface ni : networkInterfaceList) {
289 | listener.joinGroup(socketAddress, ni);
290 | }
291 | } else {
292 | group = InetAddress.getByName(host);
293 | listener = SSDPNetworkFactory.getInstance().createMulticastListener(port, handler);
294 | listener.joinGroup(group);
295 | }
296 |
297 | listener.setTimeout(timeout);
298 |
299 | while (!Thread.interrupted() && stateHolder.getState() != State.STOPPED) {
300 | try {
301 | listener.receive(blocking);
302 | } catch (SocketTimeoutException e) {
303 | // does nothing
304 | }
305 | }
306 | } catch(Exception e){
307 | logger.log(Level.WARNING, e.getMessage(), e);
308 | } finally {
309 | stateHolder.setState(State.STOPPED);
310 | if(listener!=null){
311 | if(group!=null){
312 | try {
313 | listener.leaveGroup(group);
314 | } catch (Exception e) {
315 | }
316 | } else if(networkInterfaceList!=null && !networkInterfaceList.isEmpty()){
317 | for (NetworkInterface ni : networkInterfaceList) {
318 | try {
319 | listener.leaveGroup(socketAddress, ni);
320 | } catch (Exception e) {
321 | }
322 | }
323 | }
324 | }
325 | }
326 |
327 |
328 | }
329 |
330 | }
331 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/message/AbstractSSDPNotifyMessage.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.message;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Contains the commons fields for notification {@link ISSDPMessage}.
7 | * A parent class will extends this class and add the required fields that are missing.
8 | *
9 | * @author Sebastien Dionne
10 | *
11 | */
12 | public abstract class AbstractSSDPNotifyMessage implements ISSDPMessage {
13 | protected String message;
14 | protected String notify;
15 | protected String host;
16 | protected String port;
17 | protected String nt;
18 | protected String nts;
19 | protected String usn;
20 | protected List attributes = null;
21 |
22 | /**
23 | * Returns the raw message if parsed with {@link com.jerabi.ssdp.message.helper.SSDPMessageHelper}
24 | * @return message not parsed
25 | */
26 | public String getMessage() {
27 | return message;
28 | }
29 |
30 | /**
31 | * Sets the raw message if parsed with {@link com.jerabi.ssdp.message.helper.SSDPMessageHelper}
32 | * or for debugging
33 | * @param message original message not parsed
34 | */
35 | public void setMessage(String message) {
36 | this.message = message;
37 | }
38 | /**
39 | * Returns the (USN)
40 | * @see com.jerabi.ssdp.message.USNInfo
41 | * @return (USN) Unique Service Name
42 | */
43 | public String getUsn() {
44 | return usn;
45 | }
46 |
47 | /**
48 | * Sets the (USN)
49 | * @see com.jerabi.ssdp.message.USNInfo
50 | * @param usn Unique Service Name
51 | */
52 | public void setUsn(String usn) {
53 | this.usn = usn;
54 | }
55 |
56 | /**
57 | * Returns the host
58 | * @return host
59 | */
60 | public String getHost() {
61 | return host;
62 | }
63 |
64 | /**
65 | * Sets the host
66 | * @param host
67 | */
68 | public void setHost(String host) {
69 | this.host = host;
70 | }
71 |
72 | /**
73 | * Returns Notification Type (NT)
74 | * @return Notification Type
75 | */
76 | public String getNt() {
77 | return nt;
78 | }
79 |
80 | /**
81 | * Sets Notification Type (NT)
82 | * @param nt
83 | */
84 | public void setNt(String nt) {
85 | this.nt = nt;
86 | }
87 |
88 | /**
89 | * Sets Notification Sub Type (NTS). It's the message type
90 | * @see AliveMessage
91 | * @see ByeByeMessage
92 | * @see UpdateMessage
93 | * @param nts
94 | */
95 | public void setNts(String nts) {
96 | this.nts = nts;
97 | }
98 |
99 | /**
100 | * Returns the Notify : the first line of the message
101 | * @return notify
102 | */
103 | public String getNotify() {
104 | return notify;
105 | }
106 |
107 | /**
108 | * Sets the notify
109 | * @param notify
110 | */
111 | public void setNotify(String notify) {
112 | this.notify = notify;
113 | }
114 |
115 | /**
116 | * Returns port
117 | * @return port
118 | */
119 | public String getPort() {
120 | return port;
121 | }
122 |
123 | /**
124 | * Sets port
125 | * @param port
126 | */
127 | public void setPort(String port) {
128 | this.port = port;
129 | }
130 |
131 | /**
132 | * Returns the extra attributes for the message
133 | * @return extra attributes
134 | */
135 | public List getAttributes() {
136 | return attributes;
137 | }
138 |
139 | /**
140 | * Sets extra attributes for the message
141 | * @param attributes
142 | */
143 | public void setAttributes(List attributes) {
144 | this.attributes = attributes;
145 | }
146 |
147 | /**
148 | * Return this message formatted
149 | * @return message formatted
150 | */
151 | public abstract String toString();
152 |
153 | /**
154 | * Returns Notification Sub Type (NTS)
155 | * @return nts
156 | */
157 | public abstract String getNts();
158 |
159 | }
160 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/message/AliveMessage.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.message;
2 |
3 | import com.jerabi.ssdp.util.SSDPContants;
4 |
5 | /**
6 | *
7 | * Represents a ssdp:alive message. This message is sent periodically as a keep-alive like and for broadcasting
8 | * the service that the device offers. The server must sent this message for advertising his services.
9 | *
10 | * @author Sebastien Dionne
11 | * @example.
12 | *
16 | * @see com.jerabi.ssdp.message.helper.SSDPMessageHelper
17 | */
18 | public class ServiceInfo implements Comparable {
19 |
20 | private String host;
21 | private int port;
22 | private String nt;
23 | private String location;
24 | private USNInfo usn;
25 |
26 | /**
27 | * Default constructor
28 | */
29 | public ServiceInfo(){
30 |
31 | }
32 |
33 | /**
34 | * Constructor with custom values
35 | * @param host multicast IP
36 | * @param port multicast Port
37 | * @param nt Notification Type (NT)
38 | * @param location URL on which the device will publish more information
39 | * @param usn Unique Service Name (USN)
40 | */
41 | public ServiceInfo(String host, int port, String nt, String location, USNInfo usn){
42 | this.host = host;
43 | this.port = port;
44 | this.nt = nt;
45 | this.location = location;
46 | this.usn = usn;
47 | }
48 |
49 | /**
50 | * Returns Notification Type (NT)
51 | * @return Notification Type
52 | */
53 | public String getNt() {
54 | return nt;
55 | }
56 |
57 | /**
58 | * Sets Notification Type (NT)
59 | * @param nt
60 | */
61 | public void setNt(String nt) {
62 | this.nt = nt;
63 | }
64 |
65 | /**
66 | * Returns the URL for retrieving more informations about the device.
67 | * The device most respond to this URL.
68 | *
69 | * @return device location
70 | */
71 | public String getLocation() {
72 | return location;
73 | }
74 |
75 | /**
76 | * Sets the URL on which the device will publish more informations
77 | * @param location
78 | */
79 | public void setLocation(String location) {
80 | this.location = location;
81 | }
82 | /**
83 | * Returns the (USN)
84 | * @return (USN) Unique Service Name
85 | */
86 | public USNInfo getUsn() {
87 | return usn;
88 | }
89 |
90 | /**
91 | * Sets the (USN)
92 | * @param usn Unique Service Name
93 | */
94 | public void setUsn(USNInfo usn) {
95 | this.usn = usn;
96 | }
97 |
98 | /**
99 | * Returns the host
100 | * @return host
101 | */
102 | public String getHost() {
103 | return host;
104 | }
105 |
106 | /**
107 | * Sets the host
108 | * @param host
109 | */
110 | public void setHost(String host) {
111 | this.host = host;
112 | }
113 |
114 | /**
115 | * Returns the listen port
116 | * @return port
117 | */
118 | public int getPort() {
119 | return port;
120 | }
121 |
122 | /**
123 | * Sets the listen port
124 | * @param port
125 | */
126 | public void setPort(int port) {
127 | this.port = port;
128 | }
129 |
130 | /**
131 | * Returns the root path of the location
132 | * @return "http://" + server + port(if present)
133 | */
134 | public String getLocationPath(){
135 | if(location==null){
136 | return null;
137 | }
138 |
139 | String path = null;
140 |
141 | if(location.toLowerCase().startsWith("http://")){
142 | int index = location.toLowerCase().indexOf("/", "http://".length());
143 |
144 | if(index>0){
145 | path = location.substring(index);
146 | } else {
147 | // if there isn't path, use blank
148 | // ex : http://localhost:8080
149 | path = "";
150 | }
151 |
152 | }
153 |
154 | return path;
155 | }
156 |
157 | /**
158 | * {@inheritDoc}
159 | */
160 | @Override
161 | public int hashCode() {
162 | final int prime = 31;
163 | int result = 1;
164 | result = prime * result + ((host == null) ? 0 : host.hashCode());
165 | result = prime * result
166 | + ((location == null) ? 0 : location.hashCode());
167 | result = prime * result + ((nt == null) ? 0 : nt.hashCode());
168 | result = prime * result + port;
169 | result = prime * result + ((usn == null) ? 0 : usn.hashCode());
170 | return result;
171 | }
172 |
173 | /**
174 | * {@inheritDoc}
175 | */
176 | @Override
177 | public boolean equals(Object obj) {
178 | if (this == obj)
179 | return true;
180 | if (obj == null)
181 | return false;
182 | if (getClass() != obj.getClass())
183 | return false;
184 | ServiceInfo other = (ServiceInfo) obj;
185 | if (host == null) {
186 | if (other.host != null)
187 | return false;
188 | } else if (!host.equals(other.host))
189 | return false;
190 | if (location == null) {
191 | if (other.location != null)
192 | return false;
193 | } else if (!location.equals(other.location))
194 | return false;
195 | if (nt == null) {
196 | if (other.nt != null)
197 | return false;
198 | } else if (!nt.equals(other.nt))
199 | return false;
200 | if (port != other.port)
201 | return false;
202 | if (usn == null) {
203 | if (other.usn != null)
204 | return false;
205 | } else if (!usn.equals(other.usn))
206 | return false;
207 | return true;
208 | }
209 |
210 | /**
211 | * @return Returns this ServiceInfo as a String
212 | */
213 | public String toString(){
214 |
215 | StringBuffer sb = new StringBuffer();
216 |
217 | sb.append("host=").append(host).append("\n");
218 | sb.append("port=").append(port).append("\n");
219 | sb.append("nt=").append(nt).append("\n");
220 | sb.append("location=").append(location).append("\n");
221 | sb.append("usn=").append(usn).append("\n");
222 |
223 | return sb.toString();
224 | }
225 |
226 | /**
227 | * {@inheritDoc}
228 | */
229 | @Override
230 | public int compareTo(ServiceInfo o) {
231 | return this.toString().compareToIgnoreCase(o.toString());
232 | }
233 |
234 | }
235 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/message/USNInfo.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.message;
2 |
3 | /**
4 | *
5 | * Unique Service Name (USN) - An identifier that is unique across all
6 | * services for all time. It is used to uniquely identify a particular
7 | * service in order to allow services of identical service type to be
8 | * differentiated.
9 | *
10 | * A USN is formed by two parts : UUID and URN and they are not mandatory.
11 | *
12 | * UUID : Universally Unique Identifier {@link com.jerabi.ssdp.util.UUIDGenerator}
13 | * URN : Uniform Resource Name.
14 | *
15 | * A URN must respect this format :
16 |
17 | * urn:schemas-upnp-org:device:deviceType:ver
18 | * or
19 | * urn:domain-name:device:deviceType:ver
20 | *
23 | *
24 | * @see AbstractSSDPNotifyMessage
25 | */
26 | public class UpdateMessage extends AbstractSSDPNotifyMessage {
27 |
28 | /**
29 | * First line of the message
30 | */
31 | public static final String notify = "NOTIFY * HTTP/1.1";
32 |
33 | /**
34 | * NTS value
35 | */
36 | public static final String nts = SSDPContants.NTS_UPDATE;
37 |
38 | protected String cacheControl;
39 | protected String location;
40 | protected String server;
41 |
42 | /**
43 | * {@inheritDoc}
44 | */
45 | @Override
46 | public String getNts() {
47 | return nts;
48 | }
49 |
50 | /**
51 | * Returns a duration for which the advertisement is valid
52 | * @return cache-control value
53 | */
54 | public String getCacheControl() {
55 | return cacheControl;
56 | }
57 |
58 | /**
59 | * Sets the duration for which the advertisement is valid
60 | * @param cacheControl
61 | */
62 | public void setCacheControl(String cacheControl) {
63 | this.cacheControl = cacheControl;
64 | }
65 |
66 | /**
67 | * Returns the URL for retrieving more information about the device.
68 | * The device most respond to this URL.
69 | *
70 | * @return device location
71 | */
72 | public String getLocation() {
73 | return location;
74 | }
75 |
76 | /**
77 | * Sets the URL on which the device will publish more information
78 | * @param location
79 | */
80 | public void setLocation(String location) {
81 | this.location = location;
82 | }
83 |
84 | /**
85 | * Returns the server informations.
86 | * Format is : OS/version, UPnP/version, product/version
87 | * @return server informations
88 | */
89 | public String getServer() {
90 | return server;
91 | }
92 |
93 | /**
94 | * Sets the server informations.
95 | * Format must be : OS/version, UPnP/version, product/version
96 | * @param server informations
97 | */
98 | public void setServer(String server) {
99 | this.server = server;
100 | }
101 |
102 | /**
103 | * {@inheritDoc}
104 | */
105 | @Override
106 | public String toString() {
107 | StringBuffer sb = new StringBuffer();
108 |
109 | sb.append(getNotify()).append("\r\n");
110 | sb.append(SSDPContants.HOST + " " + getHost()).append("\r\n");
111 | sb.append(SSDPContants.NT + " " + getNt()).append("\r\n");
112 | sb.append(SSDPContants.NTS + " " + getNts()).append("\r\n");
113 | sb.append(SSDPContants.LOCATION + " " + getLocation()).append("\r\n");
114 | sb.append(SSDPContants.USN + " " + getUsn()).append("\r\n");
115 | sb.append(SSDPContants.CACHECONTROL + " " + getCacheControl()).append("\r\n");
116 | sb.append(SSDPContants.SERVER + " " + getServer()).append("\r\n");
117 | sb.append("\r\n");
118 |
119 | return sb.toString();
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/message/helper/SSDPMessageHelper.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.message.helper;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.logging.Logger;
6 |
7 | import com.jerabi.ssdp.message.AbstractSSDPNotifyMessage;
8 | import com.jerabi.ssdp.message.AliveMessage;
9 | import com.jerabi.ssdp.message.ByeByeMessage;
10 | import com.jerabi.ssdp.message.DiscoverMessage;
11 | import com.jerabi.ssdp.message.DiscoverResponseMessage;
12 | import com.jerabi.ssdp.message.ISSDPMessage;
13 | import com.jerabi.ssdp.message.ServiceInfo;
14 | import com.jerabi.ssdp.message.UpdateMessage;
15 | import com.jerabi.ssdp.util.SSDPContants;
16 |
17 | /**
18 | * This helper provides API to create and parse {@link ISSDPMessage}.
19 | *
20 | * You can create a ISSDPMessage using a {@link ServiceInfo}.
21 | *
22 | * @example.
23 | *
24 | * //You could received a message over the network and want to convert it to ISSDPMessage.
25 | *
26 | * StringBuffer sb = new StringBuffer();
27 | * sb.append("HTTP/1.1 200 OK").append("\n");
28 | * sb.append("CACHE-CONTROL: max-age=1200").append("\n");
29 | * sb.append("DATE: Tue, 05 May 2009 13:31:51 GMT").append("\n");
30 | * sb.append("LOCATION: http://142.225.35.55:5001/description/fetch").append("\n");
31 | * sb.append("SERVER: Windows_XP-x86-5.1, UPnP/1.0, PMS/1.11").append("\n");
32 | * sb.append("ST: upnp:rootdevice").append("\n");
33 | * sb.append("EXT: ").append("\n");
34 | * sb.append("USN: uuid:9dcf6222-fc4b-33eb-bf49-e54643b4f416::upnp:rootdevice").append("\n");
35 | * sb.append("Content-Length: 0").append("\n");
36 | *
37 | * ISSDPMessage message = SSDPMessageHelper.getSSDPMessage(sb.toString());
38 | *
39 | * @author Sebastien Dionne
40 | *
41 | * @see AliveMessage
42 | * @see ByeByeMessage
43 | * @see DiscoverMessage
44 | * @see DiscoverResponseMessage
45 | * @see UpdateMessage
46 | */
47 | public class SSDPMessageHelper {
48 |
49 | private static final Logger logger = Logger.getLogger(SSDPMessageHelper.class.getName());
50 |
51 |
52 | /**
53 | * Parse the message and returns a ISSDPMessage if the message is supported.
54 | * If the message is not recognized a null value will be return.
55 | *
56 | * Some extra attributes could be received within the message. Even if there are not
57 | * part of the SSDP specs, and they be parsed and kept into the property : Attributes.
58 | *
59 | * @param message message to parse
60 | * @return ISSDPMessage if a valid message is received or null if it's a unknown format
61 | */
62 | public static ISSDPMessage getSSDPMessage(String message){
63 |
64 | if(message==null || message.trim().length()==0){
65 | return null;
66 | }
67 |
68 | String[] split = message.split("\n");
69 |
70 | String notify = null;
71 | String cacheControl = null;
72 | String date = null;
73 | String location = null;
74 | String server = null;
75 | String st = null;
76 | String ext = null;
77 | String usn = null;
78 | String contentLength = null;
79 | String host = null;
80 | String port = null;
81 | String nt = null;
82 | String nts = null;
83 | String mx = null;
84 | @SuppressWarnings("unused")
85 | String man = null;
86 | List othersAttributes = new ArrayList();
87 |
88 | for (int i = 0; i < split.length; i++) {
89 |
90 | String line = split[i];
91 |
92 | if(i==0){
93 | notify = line.trim();
94 | } else if(line.toUpperCase().startsWith(SSDPContants.CACHECONTROL)){
95 | cacheControl = line.substring(SSDPContants.CACHECONTROL.length()).trim();
96 | } else if(line.toUpperCase().startsWith(SSDPContants.DATE)){
97 | date = line.substring(SSDPContants.DATE.length()).trim();
98 | } else if(line.toUpperCase().startsWith(SSDPContants.LOCATION)){
99 | location = line.substring(SSDPContants.LOCATION.length()).trim();
100 | } else if(line.toUpperCase().startsWith(SSDPContants.SERVER)){
101 | server = line.substring(SSDPContants.SERVER.length()).trim();
102 | } else if(line.toUpperCase().startsWith(SSDPContants.ST)){
103 | st = line.substring(SSDPContants.ST.length()).trim();
104 | } else if(line.toUpperCase().startsWith(SSDPContants.EXT)){
105 | ext = line.substring(SSDPContants.EXT.length()).trim();
106 | } else if(line.toUpperCase().startsWith(SSDPContants.USN)){
107 | usn = line.substring(SSDPContants.USN.length()).trim();
108 | } else if(line.toUpperCase().startsWith(SSDPContants.CONTENTLENGTH)){
109 | contentLength = line.substring(SSDPContants.CONTENTLENGTH.length()).trim();
110 | } else if(line.toUpperCase().startsWith(SSDPContants.HOST)){
111 | host = line.substring(SSDPContants.HOST.length()).trim();
112 |
113 | // extract port if found
114 | int portIndex = host.indexOf(":");
115 | if(portIndex>0){
116 | port = host.substring(portIndex+1);
117 | host = host.substring(0,portIndex);
118 | } else {
119 | // use default port
120 | port = Integer.toString(SSDPContants.DEFAULT_PORT);
121 | }
122 |
123 | } else if(line.toUpperCase().startsWith(SSDPContants.NT)){
124 | nt = line.substring(SSDPContants.NT.length()).trim();
125 | } else if(line.toUpperCase().startsWith(SSDPContants.NTS)){
126 | nts = line.substring(SSDPContants.NTS.length()).trim();
127 | } else if(line.toUpperCase().startsWith(SSDPContants.MX)){
128 | mx = line.substring(SSDPContants.MX.length()).trim();
129 | } else if(line.toUpperCase().startsWith(SSDPContants.MAN)){
130 | man = line.substring(SSDPContants.MAN.length()).trim();
131 | } else {
132 | othersAttributes.add(line);
133 | }
134 |
135 | }
136 |
137 | // is it a M-SEARCH ?
138 | if(notify!=null && notify.toUpperCase().startsWith("M-SEARCH")){
139 |
140 | DiscoverMessage ssdpMessage = new DiscoverMessage();
141 |
142 | ssdpMessage.setMessage(message);
143 | ssdpMessage.setHost(host);
144 | ssdpMessage.setPort(port);
145 | ssdpMessage.setMx(mx);
146 | ssdpMessage.setSt(st);
147 | ssdpMessage.setAttributes(othersAttributes);
148 |
149 | return ssdpMessage;
150 |
151 | } else if(notify!=null && notify.equalsIgnoreCase("HTTP/1.1 200 OK")){
152 | // probably a M-SEARCH response
153 | DiscoverResponseMessage ssdpMessage = new DiscoverResponseMessage();
154 |
155 | ssdpMessage.setMessage(message);
156 | //ssdpMessage.setNotify(notify);
157 | ssdpMessage.setCacheControl(cacheControl);
158 | ssdpMessage.setDate(date);
159 | ssdpMessage.setLocation(location);
160 | ssdpMessage.setServer(server);
161 | ssdpMessage.setSt(st);
162 | ssdpMessage.setExt(ext);
163 | ssdpMessage.setUsn(usn);
164 | ssdpMessage.setContentLength(contentLength);
165 | ssdpMessage.setAttributes(othersAttributes);
166 |
167 | return ssdpMessage;
168 | } else if(nts!=null && nts.trim().length()>0){
169 | // assign values now
170 |
171 | AbstractSSDPNotifyMessage ssdpMessage = null;
172 |
173 | if(SSDPContants.NTS_ALIVE.equals(nts)){
174 | ssdpMessage = new AliveMessage();
175 |
176 | ((AliveMessage)ssdpMessage ).setCacheControl(cacheControl);
177 | ((AliveMessage)ssdpMessage ).setLocation(location);
178 | ((AliveMessage)ssdpMessage ).setServer(server);
179 |
180 | } else if(SSDPContants.NTS_UPDATE.equals(nts)){
181 | ssdpMessage = new UpdateMessage();
182 |
183 | ((UpdateMessage)ssdpMessage ).setCacheControl(cacheControl);
184 | ((UpdateMessage)ssdpMessage ).setLocation(location);
185 | ((UpdateMessage)ssdpMessage ).setServer(server);
186 |
187 | } else if(SSDPContants.NTS_BYEBYE.equals(nts)){
188 | ssdpMessage = new ByeByeMessage();
189 |
190 | ((ByeByeMessage)ssdpMessage ).setContentLength(contentLength);
191 |
192 | } else {
193 | logger.info("SSDPNotifyMessage not reconized : \n" + message);
194 | return null;
195 | }
196 | // commons fields
197 |
198 | ssdpMessage.setMessage(message);
199 | ssdpMessage.setNotify(notify);
200 | ssdpMessage.setHost(host);
201 | ssdpMessage.setPort(port);
202 | ssdpMessage.setNt(nt);
203 | ssdpMessage.setNts(nts);
204 | ssdpMessage.setUsn(usn);
205 | ssdpMessage.setAttributes(othersAttributes);
206 |
207 | return ssdpMessage;
208 | } else {
209 | logger.finest("Message not recognized : \n" + message);
210 | }
211 |
212 | return null;
213 | }
214 |
215 | /**
216 | * Creates a {@link AliveMessage} from a {@link ServiceInfo}.
217 | *
218 | * @param deviceInfo info on your device
219 | * @return AliveMessage
220 | */
221 | public static AliveMessage createSSDPAliveMessage(ServiceInfo deviceInfo) {
222 | AliveMessage message = new AliveMessage();
223 |
224 | message.setNotify(AliveMessage.notify);
225 | message.setHost(deviceInfo.getHost() + ":" + deviceInfo.getPort());
226 | message.setNts(AliveMessage.nts);
227 | message.setNt(deviceInfo.getNt());
228 | message.setLocation(deviceInfo.getLocation());
229 | message.setUsn(deviceInfo.getUsn().toString());
230 |
231 | return message;
232 | }
233 |
234 | /**
235 | * Creates a {@link UpdateMessage} from a {@link ServiceInfo}.
236 | *
237 | * @param deviceInfo info on your device
238 | * @return UpdateMessage
239 | */
240 | public static UpdateMessage createSSDPUpdateMessage(ServiceInfo deviceInfo) {
241 | UpdateMessage message = new UpdateMessage();
242 |
243 | message.setNotify(UpdateMessage.notify);
244 | message.setHost(deviceInfo.getHost() + ":" + deviceInfo.getPort());
245 | message.setNts(UpdateMessage.nts);
246 | message.setNt(deviceInfo.getNt());
247 | message.setUsn(deviceInfo.getUsn().toString());
248 |
249 | return message;
250 | }
251 |
252 | /**
253 | * Creates a {@link ByeByeMessage} from a {@link ServiceInfo}.
254 | *
255 | * @param deviceInfo info on your device
256 | * @return ByeByeMessage
257 | */
258 | public static ByeByeMessage createSSDPByeByeMessage(ServiceInfo deviceInfo) {
259 | ByeByeMessage message = new ByeByeMessage();
260 |
261 | message.setNotify(ByeByeMessage.notify);
262 | message.setHost(deviceInfo.getHost() + ":" + deviceInfo.getPort());
263 | message.setNts(ByeByeMessage.nts);
264 | message.setNt(deviceInfo.getNt());
265 | message.setUsn(deviceInfo.getUsn().toString());
266 |
267 | return message;
268 | }
269 |
270 | /**
271 | * Creates a {@link DiscoverMessage} from the info on your device.
272 | *
273 | * @param host on which host the device is located
274 | * @param port on which port the device is listening
275 | * @param ttl the time to live value
276 | * @param device device URN ex : urn:schemas-upnp-org:device:MediaServer:1
277 | * @param attributes add extra attributes on the message
278 | * @return DiscoverMessage
279 | */
280 | public static DiscoverMessage createSSDPDiscoverMessage(String host, int port, int ttl, String device, List attributes) {
281 | DiscoverMessage message = new DiscoverMessage(host, port, ttl, device, attributes);
282 |
283 | return message;
284 | }
285 |
286 | }
287 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/network/IMulticastListener.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.network;
2 |
3 | import java.net.InetAddress;
4 | import java.net.NetworkInterface;
5 | import java.net.SocketAddress;
6 |
7 | /**
8 | * Provides API to listen for incoming multicast UDP, with additional capabilities for
9 | * joining "groups" of other multicast hosts on the Internet.
10 | *
11 | * A multicast group is specified by a class D IP address
12 | * and by a standard UDP port number. Class D IP addresses
13 | * are in the range 224.0.0.0 to 239.255.255.255,
14 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
15 | *
16 | * To join a multicast group you need to invoke joinGroup(InetAddress groupAddr).
17 | * To leave a multicast group you need to invoke leaveGroup(InetAddress groupAddr).
18 | *
19 | * When a multicast message is sent, all the subscribers will receive the message (within the ttl range).
20 | *
21 | * It's possible to send a multicast message without the needs to join a group.
22 | *
23 | * @author Sebastien Dionne
24 | *
25 | * @example.
26 | *
27 | *
28 | */
29 | public interface IMulticastListener {
30 |
31 | /**
32 | * Reads for incoming message. This method use the default timeout.
33 | * If you need a blocking reader look {@link #receive(boolean)}
34 | * @throws Exception
35 | */
36 | void receive() throws Exception;
37 |
38 |
39 | /**
40 | * Reads for incoming message. This method is blocking until a message is received.
41 | * If you need a non blocking reader look {@link #receive()}
42 | *
43 | * @param blocking in blocking mode is set to true
44 | * @throws Exception
45 | */
46 | void receive(boolean blocking) throws Exception;
47 |
48 | /**
49 | * Joins a multicast group
50 | * @param group the new to join
51 | * @throws Exception
52 | */
53 | void joinGroup(InetAddress group) throws Exception;
54 |
55 | /**
56 | * Leaves a multicast group
57 | * @param group group to leave
58 | * @throws Exception
59 | */
60 | void leaveGroup(InetAddress group) throws Exception;
61 |
62 | /**
63 | * Joins a multicast group
64 | * @param socketAddress the new to join
65 | * @param ni NetworkInterface that will be used.
66 | * @throws Exception
67 | */
68 | void joinGroup(SocketAddress socketAddress, NetworkInterface ni) throws Exception;
69 |
70 | /**
71 | * Leaves a multicast group
72 | * @param socketAddress the new to join
73 | * @param ni NetworkInterface that will be used.
74 | * @throws Exception
75 | */
76 | void leaveGroup(SocketAddress socketAddress, NetworkInterface ni) throws Exception;
77 |
78 | /**
79 | * Sets the timeout for non blocking socket
80 | * @param timeout value in ms.
81 | */
82 | void setTimeout(int timeout);
83 |
84 | /**
85 | * Returns the timeout for non blocking socket
86 | * @return timeout value in ms.
87 | */
88 | int getTimeout();
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/network/ISSDPNetwork.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.network;
2 |
3 | import java.net.InetAddress;
4 | import java.net.NetworkInterface;
5 | import java.net.SocketAddress;
6 |
7 | import com.jerabi.ssdp.handler.ISSDPResponseHandler;
8 |
9 | /**
10 | *
11 | * Provides API for sending and receiving messages over network.
12 | *
13 | * @author Sebastien Dionne
14 | */
15 | public interface ISSDPNetwork {
16 |
17 |
18 | // SSDPPeriodicMessageSender ->
19 | /**
20 | * Sends a multicast UDP message without the needs to join a group.
21 | *
22 | * The multicast addresses are in the range 224.0.0.0 to 239.255.255.255,
23 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
24 | *
25 | * @param message message to send
26 | * @param address destination address
27 | * @throws Exception
28 | */
29 | void sendMulticastMessage(String message, SocketAddress address) throws Exception;
30 |
31 | /**
32 | * Sends a multicast UDP message without the needs to join a group.
33 | *
34 | * The multicast addresses are in the range 224.0.0.0 to 239.255.255.255,
35 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
36 | *
37 | * @param message message to send
38 | * @param address destination address
39 | * @param ni NetworkInterface that will be used.
40 | * @throws Exception
41 | */
42 | void sendMulticastMessage(String message, SocketAddress address, NetworkInterface ni) throws Exception;
43 |
44 | /**
45 | *
46 | * Sends a multicast UDP message
47 | *
48 | * The multicast addresses are in the range 224.0.0.0 to 239.255.255.255,
49 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
50 | *
51 | * @param message message to send
52 | * @param address destination address
53 | * @param port destination port
54 | * @throws Exception
55 | */
56 | void sendMulticastMessage(String message, InetAddress address, int port) throws Exception;
57 |
58 | /**
59 | *
60 | * Sends a multicast UDP message and wait for a response. TTL defines the timeout for the response.
61 | * If a response is received, it will be forward to the callback {@link ISSDPResponseHandler}.
62 | *
63 | * The multicast addresses are in the range 224.0.0.0 to 239.255.255.255,
64 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
65 | *
66 | * @param message message to send
67 | * @param address destination address
68 | * @param callbackHandler handle the response
69 | * @param ttl Time to live (timeout)
70 | * @throws Exception
71 | */
72 | void sendMulticastMessage(String message, SocketAddress address, ISSDPResponseHandler callbackHandler, int ttl) throws Exception;
73 |
74 | /**
75 | *
76 | * Sends a multicast UDP message and wait for a response. TTL defines the timeout for the response.
77 | * If a response is received, it will be forward to the callback {@link ISSDPResponseHandler}.
78 | *
79 | * The multicast addresses are in the range 224.0.0.0 to 239.255.255.255,
80 | * inclusive. The address 224.0.0.0 is reserved and should not be used.
81 | *
82 | * @param message message to send
83 | * @param address destination address
84 | * @param port destination port
85 | * @param callbackHandler handle the response
86 | * @param ttl Time to live (timeout)
87 | * @throws Exception
88 | */
89 | void sendMulticastMessage(String message, InetAddress address, int port, ISSDPResponseHandler callbackHandler, int ttl) throws Exception;
90 |
91 | // SSDPDiscoverSender -> <-
92 | /**
93 | * Creates a {@link IUDPSender} instance.
94 | * @return IUDPSender
95 | * @throws Exception
96 | */
97 | IUDPSender createUDPSender() throws Exception;
98 |
99 | /**
100 | * Creates a {@link IUDPSender} instance.
101 | *
102 | * @param port port that will be used
103 | * @return IUDPSender
104 | * @throws Exception
105 | */
106 | IUDPSender createUDPSender(int port) throws Exception;
107 |
108 | // SSDPMulticastListener <-
109 | /**
110 | * Creates a {@link IMulticastListener} instance.
111 | *
112 | * @param port listening port
113 | * @param callbackHandler handle the response
114 | * @return IMulticastListener
115 | * @throws Exception
116 | */
117 | IMulticastListener createMulticastListener(int port, ISSDPResponseHandler callbackHandler) throws Exception;
118 |
119 | /**
120 | * Creates a {@link IMulticastListener} instance.
121 | *
122 | * @param bindAddress listening address
123 | * @param callbackHandler handle the response
124 | * @return IMulticastListener
125 | * @throws Exception
126 | */
127 | IMulticastListener createMulticastListener(SocketAddress bindAddress, ISSDPResponseHandler callbackHandler) throws Exception;
128 |
129 | /**
130 | * Creates a {@link IMulticastListener} instance.
131 | *
132 | * @param bindAddress listening address
133 | * @param callbackHandler handle the response
134 | * @param ni NetworkInterface that will be used.
135 | * @return IMulticastListener
136 | * @throws Exception
137 | */
138 | IMulticastListener createMulticastListener(SocketAddress bindAddress, ISSDPResponseHandler callbackHandler, NetworkInterface ni) throws Exception;
139 |
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/network/IUDPSender.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.network;
2 |
3 | import java.net.InetAddress;
4 | import java.net.SocketAddress;
5 |
6 | import com.jerabi.ssdp.handler.ISSDPResponseHandler;
7 |
8 | /**
9 | * Provides API for sending and receiving UDP messages over network.
10 | *
11 | * This sender will not send multicast UDP. If you need multicast UDP look {@link ISSDPNetwork}.
12 | *
13 | * @author Sebastien Dionne
14 | */
15 | public interface IUDPSender {
16 |
17 | /**
18 | * Sends a UDP message and wait for a response. TTL defines the timeout for the response.
19 | * If a response is received, it will be forward to the callback {@link ISSDPResponseHandler}.
20 | *
21 | * @param message message to send
22 | * @param address destination address
23 | * @param callbackHandler handle the response
24 | * @param ttl Time to live (timeout)
25 | * @throws Exception
26 | */
27 | void sendMessage(String message, SocketAddress address, ISSDPResponseHandler callbackHandler, int ttl) throws Exception;
28 |
29 | /**
30 | * Sends a UDP message and wait for a response. TTL defines the timeout for the response.
31 | * If a response is received, it will be forward to the callback {@link ISSDPResponseHandler}.
32 | *
33 | * @param message message to send
34 | * @param address destination address
35 | * @param port destination port
36 | * @param callbackHandler handle the response
37 | * @param ttl Time to live (timeout)
38 | * @throws Exception
39 | */
40 | void sendMessage(String message, InetAddress address, int port, ISSDPResponseHandler callbackHandler, int ttl) throws Exception;
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/network/SSDPNetworkFactory.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.network;
2 |
3 | import java.lang.reflect.InvocationTargetException;
4 |
5 |
6 | /**
7 | *
8 | * Provides API for sending and receiving messages over network.
9 | *
10 | * This class is a dummy that doesn't implements any methods.
11 | * It used for compilation purpose. An implementation must be
12 | * available in another package.
13 | *
14 | * @author Sebastien Dionne
15 | *
16 | */
17 | public class SSDPNetworkFactory {
18 |
19 | private static final String DEFAULT_IMPL = "com.jerabi.ssdp.network.impl.SSDPNetworkImpl";
20 | private static ISSDPNetwork instance = null;
21 |
22 | /**
23 | * Private Constructor. You need to use getInstance()
24 | * @see #getInstance()
25 | */
26 | private SSDPNetworkFactory(){}
27 |
28 | /**
29 | * Returns a ISSDPNetwork instance.
30 | *
31 | * @return ISSDPNetwork
32 | * @throws ClassNotFoundException
33 | * @throws IllegalAccessException
34 | * @throws InstantiationException
35 | * @throws InvocationTargetException
36 | * @throws IllegalArgumentException
37 | * @throws SecurityException
38 | * @throws NoSuchMethodException
39 | */
40 | public static ISSDPNetwork getInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
41 |
42 | if(instance==null){
43 | instance = (ISSDPNetwork) Class.forName(DEFAULT_IMPL).newInstance();
44 | }
45 |
46 | return instance;
47 |
48 | }
49 |
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/sender/AliveMessageSender.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.sender;
2 |
3 | import java.net.NetworkInterface;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import com.jerabi.ssdp.ISSDPControler;
8 | import com.jerabi.ssdp.message.AliveMessage;
9 | import com.jerabi.ssdp.message.ISSDPMessage;
10 | import com.jerabi.ssdp.message.ServiceInfo;
11 | import com.jerabi.ssdp.message.helper.SSDPMessageHelper;
12 |
13 | /**
14 | * This class is a Sender that sends periodically {@link AliveMessage} and doesn't handle responses. If
15 | * a response is required, you will have to override {@link #sendMessage(String)}.
16 | *
17 | * This class is a implementation of {@link SSDPDefaultPeriodicMessageSender}.
18 | *
19 | * Once this sender is stopped it can't be restarted. You need to create a new instance.
20 | *
21 | * This sender will send the message and enter in sleep mode for the delay used and return to started mode until
22 | * the sender is stopped by the controller.
23 | *
24 | *
25 | * @author Sebastien Dionne
26 | * @example.
27 | *
28 | *
29 | * // a simple example that will send 5 times the same message each time.
30 | * ...
31 | * sender = new AliveMessageSender(controler, SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT, SSDPContants.DEFAULT_DELAY, "max-age=1800", "Demo Server", 5);
32 | *
33 | * ...
34 | *
35 | *
36 | *
37 | */
38 | public class AliveMessageSender extends SSDPDefaultPeriodicMessageSender {
39 |
40 | protected String cacheControl = "";
41 | protected String serverName = "";
42 | protected int multipleTimeToSend = 1;
43 |
44 | /**
45 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
46 | * @param controler ISSDPControler
47 | * @param ssdpHost multicast IP
48 | * @param ssdpPort multicast port
49 | * @param cacheControl cache-control value
50 | * @param serverName the name or description of the server
51 | */
52 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, String cacheControl, String serverName) {
53 | super(controler, ssdpHost, ssdpPort);
54 | this.cacheControl = cacheControl;
55 | this.serverName = serverName;
56 | }
57 |
58 | /**
59 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
60 | * @param controler ISSDPControler
61 | * @param ssdpHost multicast IP
62 | * @param ssdpPort multicast port
63 | * @param cacheControl cache-control value
64 | * @param serverName the name or description of the server
65 | * @param multipleTimeToSend number time each messages will be sent each time
66 | */
67 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, String cacheControl, String serverName, int multipleTimeToSend) {
68 | super(controler, ssdpHost, ssdpPort);
69 | this.cacheControl = cacheControl;
70 | this.serverName = serverName;
71 | this.multipleTimeToSend = multipleTimeToSend;
72 | }
73 |
74 | /**
75 | * Constructor with a custom default delay in ms.
76 | * @param controler ISSDPControler
77 | * @param ssdpHost multicast IP
78 | * @param ssdpPort multicast port
79 | * @param delay delay before the next batch of messages are sent
80 | * @param cacheControl cache-control value
81 | * @param serverName the name or description of the server
82 | */
83 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay, String cacheControl, String serverName) {
84 | super(controler, ssdpHost, ssdpPort, delay);
85 | this.cacheControl = cacheControl;
86 | this.serverName = serverName;
87 | }
88 |
89 | /**
90 | * Constructor with a custom default delay in ms.
91 | * @param controler ISSDPControler
92 | * @param ssdpHost multicast IP
93 | * @param ssdpPort multicast port
94 | * @param delay delay before the next batch of messages are sent
95 | * @param cacheControl cache-control value
96 | * @param serverName the name or description of the server
97 | * @param multipleTimeToSend number time each messages will be sent each time
98 | */
99 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay, String cacheControl, String serverName, int multipleTimeToSend) {
100 | super(controler, ssdpHost, ssdpPort, delay);
101 | this.cacheControl = cacheControl;
102 | this.serverName = serverName;
103 | this.multipleTimeToSend = multipleTimeToSend;
104 | }
105 |
106 | /**
107 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
108 | * @param controler ISSDPControler
109 | * @param ssdpHost multicast IP
110 | * @param ssdpPort multicast port
111 | * @param cacheControl cache-control value
112 | * @param serverName the name or description of the server
113 | * @param networkInterfaceList NetworkInterfaces that will be used
114 | */
115 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, String cacheControl, String serverName, List networkInterfaceList) {
116 | super(controler, ssdpHost, ssdpPort, networkInterfaceList);
117 | this.cacheControl = cacheControl;
118 | this.serverName = serverName;
119 | }
120 |
121 | /**
122 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
123 | * @param controler ISSDPControler
124 | * @param ssdpHost multicast IP
125 | * @param ssdpPort multicast port
126 | * @param cacheControl cache-control value
127 | * @param serverName the name or description of the server
128 | * @param networkInterfaceList NetworkInterfaces that will be used
129 | * @param multipleTimeToSend number time each messages will be sent each time
130 | */
131 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, String cacheControl, String serverName, List networkInterfaceList, int multipleTimeToSend) {
132 | super(controler, ssdpHost, ssdpPort, networkInterfaceList);
133 | this.cacheControl = cacheControl;
134 | this.serverName = serverName;
135 | this.multipleTimeToSend = multipleTimeToSend;
136 | }
137 |
138 | /**
139 | * Constructor with a custom default delay in ms.
140 | * @param controler ISSDPControler
141 | * @param ssdpHost multicast IP
142 | * @param ssdpPort multicast port
143 | * @param delay delay before the next batch of messages are sent
144 | * @param cacheControl cache-control value
145 | * @param serverName the name or description of the server
146 | * @param networkInterfaceList NetworkInterfaces that will be used
147 | */
148 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay, String cacheControl, String serverName, List networkInterfaceList) {
149 | super(controler, ssdpHost, ssdpPort, networkInterfaceList, delay);
150 | this.cacheControl = cacheControl;
151 | this.serverName = serverName;
152 | }
153 |
154 | /**
155 | * Constructor with a custom default delay in ms.
156 | * @param controler ISSDPControler
157 | * @param ssdpHost multicast IP
158 | * @param ssdpPort multicast port
159 | * @param delay delay before the next batch of messages are sent
160 | * @param cacheControl cache-control value
161 | * @param serverName the name or description of the server
162 | * @param networkInterfaceList NetworkInterfaces that will be used
163 | * @param multipleTimeToSend number time each messages will be sent each time
164 | */
165 | public AliveMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay, String cacheControl, String serverName, List networkInterfaceList, int multipleTimeToSend) {
166 | super(controler, ssdpHost, ssdpPort, networkInterfaceList, delay);
167 | this.cacheControl = cacheControl;
168 | this.serverName = serverName;
169 | this.multipleTimeToSend = multipleTimeToSend;
170 | }
171 |
172 | /**
173 | * {@inheritDoc}
174 | */
175 | @Override
176 | public List getSSDPMessagesToSend() {
177 | List list = new ArrayList();
178 |
179 | for (ServiceInfo deviceInfo : controler.getServiceInfoList()) {
180 |
181 | AliveMessage message = SSDPMessageHelper.createSSDPAliveMessage(deviceInfo);
182 |
183 | message.setCacheControl(cacheControl);
184 | message.setServer(serverName);
185 |
186 | for(int i=0;i
25 | *
26 | * // a simple example that will send 5 times the same message each time.
27 | * ...
28 | * sender = new SSDPDefaultPeriodicMessageSender(controler, SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT, SSDPContants.DEFAULT_DELAY) {
29 | * @Override
30 | * public List<ISSDPMessage> getSSDPMessagesToSend() {
31 | * List<ISSDPMessage> list = new ArrayList<ISSDPMessage>();
32 | *
33 | * // add 5 times the same message to the list
34 | * for(int i=0;i<5;i++){
35 | * list.add(new ISSDPMessage(){
36 | * public String toString() {
37 | * return "messagetosend";
38 | * }});
39 | * }
40 | *
41 | * return list;
42 | * }
43 | * };
44 | *
45 | * ...
46 | *
47 | *
48 | *
49 | */
50 | public class SSDPDefaultPeriodicMessageSender extends SSDPPeriodicMessageSender {
51 |
52 | /**
53 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
54 | * @param controler ISSDPControler
55 | * @param ssdpHost multicast IP
56 | * @param ssdpPort multicast port
57 | */
58 | public SSDPDefaultPeriodicMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort) {
59 | super(controler, ssdpHost, ssdpPort);
60 | }
61 |
62 | /**
63 | * Constructor with a custom default delay in ms.
64 | * @param controler ISSDPControler
65 | * @param ssdpHost multicast IP
66 | * @param ssdpPort multicast port
67 | * @param delay delay before the next batch of messages are sent
68 | */
69 | public SSDPDefaultPeriodicMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay) {
70 | super(controler, ssdpHost, ssdpPort, delay);
71 | }
72 |
73 | /**
74 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
75 | * @param controler ISSDPControler
76 | * @param ssdpHost multicast IP
77 | * @param ssdpPort multicast port
78 | * @param networkInterfaceList NetworkInterfaces that will be used
79 | */
80 | public SSDPDefaultPeriodicMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, List networkInterfaceList) {
81 | super(controler, ssdpHost, ssdpPort, networkInterfaceList);
82 | }
83 |
84 | /**
85 | * Constructor with a custom default delay in ms.
86 | * @param controler ISSDPControler
87 | * @param ssdpHost multicast IP
88 | * @param ssdpPort multicast port
89 | * @param networkInterfaceList NetworkInterfaces that will be used
90 | * @param delay delay before the next batch of messages are sent
91 | */
92 | public SSDPDefaultPeriodicMessageSender(ISSDPControler controler, String ssdpHost, int ssdpPort, List networkInterfaceList, int delay) {
93 | super(controler, ssdpHost, ssdpPort, networkInterfaceList, delay);
94 | }
95 |
96 | /**
97 | * {@inheritDoc}
98 | */
99 | @Override
100 | public List getSSDPMessagesToSend() {
101 | return null;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/sender/SSDPDiscoverSender.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.sender;
2 |
3 | import java.net.InetAddress;
4 | import java.net.NetworkInterface;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.concurrent.Callable;
8 | import java.util.logging.Logger;
9 |
10 | import com.jerabi.ssdp.ISSDPControler;
11 | import com.jerabi.ssdp.handler.ISSDPResponseHandler;
12 | import com.jerabi.ssdp.message.DiscoverMessage;
13 | import com.jerabi.ssdp.message.ISSDPMessage;
14 | import com.jerabi.ssdp.network.IUDPSender;
15 | import com.jerabi.ssdp.network.SSDPNetworkFactory;
16 | import com.jerabi.ssdp.util.SSDPContants;
17 |
18 | /**
19 | * This class in a {@link SSDPPeriodicMessageSender} that send DiscoverMessage and handle responses for the messages sent.
20 | *
21 | * The sender is a {@link IUDPSender} and it sends UDP instead of Multicast UDP. The responses will be handle by a {@link ISSDPResponseHandler}, if the handler is null,
22 | * the responses will be ignored.
23 | *
24 | * When you change the port, the {@link IUDPSender} will be set to null and recreated when you send a message.
25 | *
26 | * @author Sebastien Dionne
27 | * @example.
28 | *
29 | * ...
30 | * // you need a ISSDPControler to process the responses.
31 | * SSDPDiscoverSender discoverSender = new SSDPDiscoverSender(controler, SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT);
32 | * discoverSender.setSSDPResponseHandler(new SSDPDiscoverResponseHandler(controler));
33 | * Thread t = new Thread(discoverSender);
34 | * t.start();
35 | *
36 | * @see DiscoverMessage
37 | * @see IUDPSender
38 | */
39 | public class SSDPDiscoverSender extends SSDPPeriodicMessageSender {
40 | private Logger logger = Logger.getLogger(SSDPDiscoverSender.class.getName());
41 |
42 | private IUDPSender udpSender = null;
43 | private ISSDPResponseHandler handler = null;
44 | private int TTL = 3; // MX
45 |
46 | /**
47 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
48 | * and creates a IUDPSender using ssdpPort
49 | *
50 | * @param controler ISSDPControler
51 | * @param ssdpHost multicast IP
52 | * @param ssdpPort multicast port
53 | */
54 | public SSDPDiscoverSender(ISSDPControler controler, String ssdpHost, int ssdpPort) {
55 | super(controler, ssdpHost, ssdpPort);
56 | }
57 |
58 | /**
59 | * Constructor with a custom default delay in ms.
60 | * and creates a IUDPSender using ssdpPort
61 | *
62 | * @param controler ISSDPControler
63 | * @param ssdpHost multicast IP
64 | * @param ssdpPort multicast port
65 | * @param delay delay before the next batch of messages are sent
66 | */
67 | public SSDPDiscoverSender(ISSDPControler controler, String ssdpHost, int ssdpPort, int delay) {
68 | super(controler, ssdpHost, ssdpPort, delay);
69 | }
70 |
71 | /**
72 | * Constructor that will use the default delay see com.jerabi.ssdp.util.SSDPContants.DEFAULT_DELAY value
73 | * and creates a IUDPSender using ssdpPort
74 | *
75 | * @param controler ISSDPControler
76 | * @param ssdpHost multicast IP
77 | * @param ssdpPort multicast port
78 | * @param networkInterfaceList NetworkInterfaces that will be used
79 | */
80 | public SSDPDiscoverSender(ISSDPControler controler, String ssdpHost, int ssdpPort, List networkInterfaceList) {
81 | super(controler, ssdpHost, ssdpPort, networkInterfaceList);
82 | }
83 |
84 | /**
85 | * Constructor with a custom default delay in ms.
86 | * and creates a IUDPSender using ssdpPort
87 | *
88 | * @param controler ISSDPControler
89 | * @param ssdpHost multicast IP
90 | * @param ssdpPort multicast port
91 | * @param networkInterfaceList NetworkInterfaces that will be used
92 | * @param delay delay before the next batch of messages are sent
93 | */
94 | public SSDPDiscoverSender(ISSDPControler controler, String ssdpHost, int ssdpPort, List networkInterfaceList, int delay) {
95 | super(controler, ssdpHost, ssdpPort, networkInterfaceList, delay);
96 | }
97 |
98 | /**
99 | * Return a ISSDPHandler that will handle the discover responses.
100 | * @return handler
101 | */
102 | public ISSDPResponseHandler getSSDPResponseHandler() {
103 | return handler;
104 | }
105 |
106 | /**
107 | * Sets a ISSDPHandler that will handle the discover responses.
108 | * @param handler
109 | */
110 | public void setSSDPResponseHandler(ISSDPResponseHandler handler) {
111 | this.handler = handler;
112 | }
113 |
114 | /**
115 | * {@inheritDoc}
116 | * Sets IUDPSender to null. If will be recreate when a message is sent.
117 | */
118 | @Override
119 | public void setSSDPPort(int port) {
120 | super.setSSDPPort(port);
121 | udpSender=null;
122 | }
123 |
124 | /**
125 | * {@inheritDoc}
126 | * Creates a {@link DiscoverMessage} and add it twice to the list.
127 | * It's strongly suggested to send DiscoverMessage twice.
128 | */
129 | @Override
130 | public List getSSDPMessagesToSend() {
131 |
132 | List list = new ArrayList();
133 | DiscoverMessage discoverMessage = new DiscoverMessage(SSDPContants.DEFAULT_IP, SSDPContants.DEFAULT_PORT, TTL, "upnp:rootdevice", null);
134 |
135 | list.add(discoverMessage);
136 | list.add(discoverMessage);
137 |
138 | return list;
139 | }
140 |
141 | /**
142 | * Sends the messages using {@link IUDPSender} and wait for a response until a timeout (Time-to-live).
143 | * When a response is received, a {@link ISSDPResponseHandler} will handle it. If the port changed since the
144 | * last time you sent a message, a new IUDPSender will be created.
145 | */
146 | @Override
147 | public void sendMessage(String message) throws Exception {
148 |
149 | if(message==null){
150 | return;
151 | }
152 |
153 | logger.info("sending M-SEARCH \n" + message);
154 |
155 | if(udpSender==null){
156 | udpSender = SSDPNetworkFactory.getInstance().createUDPSender();
157 | }
158 |
159 | final String msg = message;
160 | threadPool.submit(new Callable() {
161 | @Override
162 | public Boolean call() throws Exception {
163 | udpSender.sendMessage(msg, InetAddress.getByName(host), port, handler, TTL);
164 | return Boolean.TRUE;
165 | }
166 | });
167 |
168 | }
169 |
170 | }
171 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/sender/SSDPPeriodicMessageSender.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jerabi/jerabi-ssdp/30e89a68451173f490a1b138751ab81608497b3c/ssdp-core/src/main/java/com/jerabi/ssdp/sender/SSDPPeriodicMessageSender.java
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/util/IStateListener.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.util;
2 |
3 | /**
4 | * Provides the notification mechanism for state changes.
5 | *
6 | * @author Sebastien Dionne
7 | *
8 | * @param State
9 | */
10 | public interface IStateListener {
11 |
12 | /**
13 | * Notify the listener that the state changed.
14 | *
15 | * @param state the new current state
16 | */
17 | void notifyStateChange(E state);
18 | }
19 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/util/SSDPContants.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.util;
2 |
3 | /**
4 | *
5 | * Defines all SSDP Constants.
6 | *
7 | * @author Sebastien Dionne
8 | *
9 | */
10 | public class SSDPContants {
11 |
12 | /**
13 | * Method for sending notifications and events. First line of the message.
14 | */
15 | public static final String NOTIFY = "NOTIFY:";
16 |
17 | /**
18 | * Field value MUST have the max-age directive ("max-age=") followed by an integer that specifies the number of
19 | * seconds the advertisement is valid
20 | */
21 | public static final String CACHECONTROL = "CACHE-CONTROL:";
22 | /**
23 | * Field value contains when response was generated
24 | */
25 | public static final String DATE = "DATE:";
26 | /**
27 | * Field value contains a URL to the UPnP description of the root device
28 | */
29 | public static final String LOCATION = "LOCATION:";
30 | /**
31 | * Server informations. The format is : OS/version, UPnP/version, product/version
32 | */
33 | public static final String SERVER = "SERVER:";
34 | /**
35 | * Field value contains Search Target.
36 | */
37 | public static final String ST = "ST:";
38 | /**
39 | * Backwards compatibility with UPnP 1.0. (Header field name only; no field value.)
40 | */
41 | public static final String EXT = "EXT:";
42 | /**
43 | * Field value contains Unique Service Name. Identifies a unique instance of a device or service
44 | */
45 | public static final String USN = "USN:";
46 | /**
47 | * Field value contains the byte count in the body
48 | */
49 | public static final String CONTENTLENGTH = "CONTENT-LENGTH:";
50 |
51 | /**
52 | * Field value contains multicast address and port reserved for SSDP by Internet Assigned Numbers Authority (IANA).
53 | * MUST be 239.255.255.250:1900. If the port number (":1900") is omitted, the receiver MUST assume the default SSDP port
54 | * number of 1900.
55 | */
56 | public static final String HOST = "HOST:";
57 | /**
58 | * Field value contains Notification Type.
59 | */
60 | public static final String NT = "NT:";
61 | /**
62 | * Field value contains Notification Sub Type
63 | */
64 | public static final String NTS = "NTS:";
65 | /**
66 | * HTTP Extension Framework. Unlike the NTS and ST field values, the field value of the MAN header field is
67 | * enclosed in double quotes; it defines the scope (namespace) of the extension. MUST be "ssdp:discover".
68 | */
69 | public static final String MAN = "MAN:";
70 | /**
71 | * Field value contains maximum wait time in seconds. MUST be greater than or equal to 1 and SHOULD be less than
72 | * 5 inclusive. Device responses SHOULD be delayed a random duration between 0 and this many seconds to balance load for
73 | * the control point when it processes responses
74 | */
75 | public static final String MX = "MX:";
76 |
77 | /**
78 | * Default SSDP port
79 | */
80 | public static final int DEFAULT_PORT = 1900;
81 |
82 | /**
83 | * Default SSDP IP
84 | */
85 | public static final String DEFAULT_IP = "239.255.255.250";
86 |
87 | /**
88 | * Default sleep value for periodically messages in ms.
89 | */
90 | public static final int DEFAULT_DELAY = 5000;
91 |
92 | /**
93 | * Default value for non blocking socket timeout
94 | */
95 | public static final int DEFAULT_SOCKET_TIMEOUT = 3000;
96 |
97 | /**
98 | * NTS value for {@link com.jerabi.ssdp.message.AliveMessage}
99 | */
100 | public static final String NTS_ALIVE = "ssdp:alive";
101 | /**
102 | * NTS value for {@link com.jerabi.ssdp.message.DiscoverMessage}
103 | */
104 | public static final String NTS_DISCOVER = "\"ssdp:discover\"";
105 | /**
106 | * NTS value for {@link com.jerabi.ssdp.message.ByeByeMessage}
107 | */
108 | public static final String NTS_BYEBYE = "ssdp:byebye";
109 | /**
110 | * NTS value for {@link com.jerabi.ssdp.message.UpdateMessage}
111 | */
112 | public static final String NTS_UPDATE = "ssdp:update";
113 | /**
114 | * NTS value for discover all devices and services @see com.jerabi.ssdp.message.DiscoverMessage
115 | */
116 | public static final String NTS_DISCOVER_ALL = "ssdp:all";
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/util/State.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.util;
2 |
3 | /**
4 | * Defines available SSDP states.
5 | *
6 | * @author Sebastien Dionne
7 | *
8 | */
9 | public enum State {
10 | /**
11 | * Used when the process is stopped
12 | */
13 | STOPPED,
14 | /**
15 | * Used when the process is started
16 | */
17 | STARTED,
18 | /**
19 | * Used when the process is sleeping
20 | */
21 | SLEEP,
22 | /**
23 | * Used when the process is supended
24 | */
25 | SUSPENDED
26 | }
27 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/util/StateHolder.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.util;
2 |
3 | import java.util.LinkedList;
4 | import java.util.List;
5 | import java.util.concurrent.atomic.AtomicReference;
6 | import java.util.concurrent.locks.ReentrantReadWriteLock;
7 |
8 | /**
9 | * Class that will hold a State {@link State}.
10 | *
11 | * Uses {@link AtomicReference} with {@link ReentrantReadWriteLock}.
12 | *
13 | * Notify listener when the state changes.
14 | *
15 | * @see State
16 | *
17 | * @author Sebastien Dionne
18 | * @param State
19 | */
20 | public class StateHolder {
21 | private AtomicReference state;
22 |
23 | private ReentrantReadWriteLock readWriteLock;
24 | private List> stateListenerList = null;
25 |
26 | /**
27 | * Instantiates a new state holder.
28 | */
29 | public StateHolder(){
30 | state = new AtomicReference();
31 | readWriteLock = new ReentrantReadWriteLock();
32 | stateListenerList = new LinkedList>();
33 | }
34 |
35 | /**
36 | * Adds the state listener.
37 | *
38 | * @param listener the listener
39 | */
40 | public void addStateListener(IStateListener listener){
41 | if(listener!=null){
42 | stateListenerList.add(listener);
43 | }
44 | }
45 |
46 | /**
47 | * Removes the state listener.
48 | *
49 | * @param listener the listener
50 | */
51 | public void removeStateListener(IStateListener listener){
52 | if(listener!=null){
53 | stateListenerList.remove(listener);
54 | }
55 | }
56 |
57 | /**
58 | * Gets the state.
59 | * If the state is not setted, null value will be return
60 | *
61 | * @return the state
62 | * @see State
63 | */
64 | public E getState() {
65 | readWriteLock.readLock().lock();
66 |
67 | E currentState = state.get();
68 |
69 | readWriteLock.readLock().unlock();
70 |
71 | return currentState;
72 | }
73 |
74 | /**
75 | * Sets the state and notify all registered listeners.
76 | * Used a {@link ReentrantReadWriteLock}
77 | *
78 | * @param state the new state
79 | * @see State
80 | */
81 | public void setState(E state) {
82 | readWriteLock.writeLock().lock();
83 |
84 | this.state.set(state);
85 |
86 | // downgrading lock to read
87 | readWriteLock.readLock().lock();
88 | readWriteLock.writeLock().unlock();
89 |
90 | // notifyListener
91 | notifyListeners(state);
92 |
93 | // release lock
94 | readWriteLock.readLock().unlock();
95 | }
96 |
97 | /**
98 | * Notify listeners.
99 | *
100 | * @param state the state
101 | */
102 | protected void notifyListeners(E state){
103 | for (IStateListener listener : stateListenerList) {
104 | listener.notifyStateChange(state);
105 | }
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/ssdp-core/src/main/java/com/jerabi/ssdp/util/UUIDGenerator.java:
--------------------------------------------------------------------------------
1 | package com.jerabi.ssdp.util;
2 |
3 | import java.net.NetworkInterface;
4 | import java.net.SocketException;
5 | import java.util.UUID;
6 |
7 | /**
8 | *
9 | * Provide API to generate {@link java.util.UUID}.
10 | *
11 | * A UUID is an acronym for : Universally Unique Identifier
12 | *
13 | *
14 | * UUID = <time_low> - <time_mid> - <time_high_and_version> - <clock_seq_and_reserved> <clock_seq_low> - <node>
15 | *
16 | * time_low = 4*<hexOctet>
17 | * time_mid = 2*<hexOctet>
18 | * time_high_and_version = 2*<hexOctet>
19 | * clock_seq_and_reserved = <hexOctet>
20 | * clock_seq_low = <hexOctet>
21 | * node = 6*<hexOctet
22 | * hexOctet = <hexDigit> <hexDigit>
23 | *
24 | * hexDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | A | B | C | D | E | F
25 | *
26 | * The following is an example of the string representation of a UUID:
27 | *
28 | * f81d4fae-7dec-11d0-a765-00a0c91e6bf6
29 | *