1 package org.apache.jcs.auxiliary.lateral.socket.tcp.discovery;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.ObjectOutputStream;
25 import java.net.DatagramPacket;
26 import java.net.InetAddress;
27 import java.net.MulticastSocket;
28 import java.util.ArrayList;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.jcs.auxiliary.lateral.LateralCacheInfo;
33
34 /***
35 * This is a generic sender for the UDPDiscovery process.
36 *
37 * @author Aaron Smuts
38 *
39 */
40 public class UDPDiscoverySender
41 {
42 private final static Log log = LogFactory.getLog( UDPDiscoverySender.class );
43
44 private MulticastSocket m_localSocket;
45
46 private InetAddress m_multicastAddress;
47
48 private int m_multicastPort;
49
50 /***
51 * Constructor for the UDPDiscoverySender object
52 * <p>
53 * This sender can be used to send multiple messages.
54 * <p>
55 * When you are done sending, you should destroy the socket sender.
56 *
57 * @param host
58 * @param port
59 *
60 * @exception IOException
61 */
62 public UDPDiscoverySender( String host, int port )
63 throws IOException
64 {
65 try
66 {
67 m_localSocket = new MulticastSocket();
68
69
70 m_multicastAddress = InetAddress.getByName( host );
71 }
72 catch ( IOException e )
73 {
74 log.error( "Could not bind to multicast address [" + host + "]", e );
75
76 throw e;
77 }
78
79 m_multicastPort = port;
80 }
81
82 /***
83 * Closes the socket connection.
84 *
85 */
86 public void destroy()
87 {
88 try
89 {
90
91 if ( this.m_localSocket != null )
92
93 {
94 this.m_localSocket.close();
95 }
96 }
97 catch ( Exception e )
98 {
99 log.error( "Problem destrying sender", e );
100 }
101 }
102
103 /***
104 * Just being careful about closing the socket.
105 *
106 * @throws Throwable
107 */
108 public void finalize()
109 throws Throwable
110 {
111 super.finalize();
112 destroy();
113 }
114
115 /***
116 * Send messages.
117 *
118 * @param message
119 * @throws IOException
120 */
121 public void send( UDPDiscoveryMessage message )
122 throws IOException
123 {
124 if ( this.m_localSocket == null )
125 {
126 throw new IOException( "Socket is null, cannot send message." );
127 }
128
129
130
131
132
133
134
135 if ( log.isDebugEnabled() )
136 {
137 log.debug( "sending UDPDiscoveryMessage, message = " + message );
138 }
139
140 try
141 {
142
143 final MyByteArrayOutputStream byteStream = new MyByteArrayOutputStream();
144 final ObjectOutputStream objectStream = new ObjectOutputStream( byteStream );
145 objectStream.writeObject( message );
146 objectStream.flush();
147 final byte[] bytes = byteStream.getBytes();
148
149
150 final DatagramPacket packet = new DatagramPacket( bytes, bytes.length, m_multicastAddress, m_multicastPort );
151
152 m_localSocket.send( packet );
153 }
154 catch ( IOException e )
155 {
156 log.error( "Error sending message", e );
157 throw e;
158 }
159 }
160
161 /***
162 * Ask other to broadcast their info the the multicast address. If a lateral
163 * is non receiving it can use this. This is also called on startup so we
164 * can get info.
165 *
166 * @throws IOException
167 */
168 public void requestBroadcast()
169 throws IOException
170 {
171 if ( log.isDebugEnabled() )
172 {
173 log.debug( "sending requestBroadcast " );
174 }
175
176 UDPDiscoveryMessage message = new UDPDiscoveryMessage();
177 message.setRequesterId( LateralCacheInfo.listenerId );
178 message.setMessageType( UDPDiscoveryMessage.REQUEST_BROADCAST );
179 send( message );
180 }
181
182 /***
183 * This sends a message braodcasting our that the host and port is available
184 * for connections.
185 * <p>
186 * It uses the vmid as the requesterDI
187 *
188 * @param host
189 * @param port
190 * @param cacheNames
191 * @throws IOException
192 */
193 public void passiveBroadcast( String host, int port, ArrayList cacheNames )
194 throws IOException
195 {
196 passiveBroadcast( host, port, cacheNames, LateralCacheInfo.listenerId );
197 }
198
199 /***
200 * This allows you to set the sender id. This is mainly for testing.
201 *
202 * @param host
203 * @param port
204 * @param cacheNames
205 * @param listenerId
206 * @throws IOException
207 */
208 protected void passiveBroadcast( String host, int port, ArrayList cacheNames, long listenerId )
209 throws IOException
210 {
211 if ( log.isDebugEnabled() )
212 {
213 log.debug( "sending passiveBroadcast " );
214 }
215
216 UDPDiscoveryMessage message = new UDPDiscoveryMessage();
217 message.setHost( host );
218 message.setPort( port );
219 message.setCacheNames( cacheNames );
220 message.setRequesterId( listenerId );
221 message.setMessageType( UDPDiscoveryMessage.PASSIVE_BROADCAST );
222 send( message );
223 }
224 }
225
226 /***
227 * This allows us to get the byte array from an output stream.
228 *
229 * @author asmuts
230 * @created January 15, 2002
231 */
232
233 class MyByteArrayOutputStream
234 extends ByteArrayOutputStream
235 {
236 /***
237 * Gets the bytes attribute of the MyByteArrayOutputStream object
238 *
239 * @return The bytes value
240 */
241 public byte[] getBytes()
242 {
243 return buf;
244 }
245 }
246