001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.replication.protocol;
028
029 import java.io.Serializable;
030 import java.io.UnsupportedEncodingException;
031 import java.net.InetAddress;
032 import java.net.UnknownHostException;
033 import java.util.zip.DataFormatException;
034
035 import org.opends.server.replication.common.ServerState;
036 import org.opends.server.types.DN;
037 import org.opends.server.types.DirectoryException;
038
039 /**
040 * This message is used by LDAP server when they first connect.
041 * to a replication server to let them know who they are and what is their state
042 * (their RUV)
043 */
044 public class ServerStartMessage extends StartMessage implements
045 Serializable
046 {
047 private static final long serialVersionUID = 8649393307038290287L;
048
049 private short serverId; // Id of the LDAP server that sent this message
050 private String serverURL;
051 private String baseDn;
052 private int maxReceiveQueue;
053 private int maxSendQueue;
054 private int maxReceiveDelay;
055 private int maxSendDelay;
056 private int windowSize;
057 private boolean handshakeOnly;
058 private ServerState serverState = null;
059
060 /**
061 * The time in milliseconds between heartbeats from the replication
062 * server. Zero means heartbeats are off.
063 */
064 private long heartbeatInterval = 0;
065
066 /**
067 * Whether to continue using SSL to encrypt messages after the start
068 * messages have been exchanged.
069 */
070 private boolean sslEncryption;
071
072 /**
073 * Creates a new ServerStartMessage. This message is to be sent by an LDAP
074 * Server after being connected to a replication server for a given
075 * replication domain.
076 *
077 * @param serverId The serverId of the server for which the ServerStartMessage
078 * is created.
079 * @param baseDn The base DN.
080 * @param maxReceiveDelay The max receive delay for this server.
081 * @param maxReceiveQueue The max receive Queue for this server.
082 * @param maxSendDelay The max Send Delay from this server.
083 * @param maxSendQueue The max send Queue from this server.
084 * @param windowSize The window size used by this server.
085 * @param heartbeatInterval The requested heartbeat interval.
086 * @param serverState The state of this server.
087 * @param protocolVersion The replication protocol version of the creator.
088 * @param generationId The generationId for this server.
089 * @param sslEncryption Whether to continue using SSL to encrypt messages
090 * after the start messages have been exchanged.
091 * @param handshakeOnly Whether this message is only to get an handshake
092 * with the server or not.
093 */
094 public ServerStartMessage(short serverId, DN baseDn, int maxReceiveDelay,
095 int maxReceiveQueue, int maxSendDelay,
096 int maxSendQueue, int windowSize,
097 long heartbeatInterval,
098 ServerState serverState,
099 short protocolVersion,
100 long generationId,
101 boolean sslEncryption,
102 boolean handshakeOnly)
103 {
104 super(protocolVersion, generationId);
105
106 this.serverId = serverId;
107 this.baseDn = baseDn.toString();
108 this.maxReceiveDelay = maxReceiveDelay;
109 this.maxReceiveQueue = maxReceiveQueue;
110 this.maxSendDelay = maxSendDelay;
111 this.maxSendQueue = maxSendQueue;
112 this.windowSize = windowSize;
113 this.heartbeatInterval = heartbeatInterval;
114 this.sslEncryption = sslEncryption;
115 this.serverState = serverState;
116 this.handshakeOnly = handshakeOnly;
117
118 try
119 {
120 /* TODO : find a better way to get the server URL */
121 this.serverURL = InetAddress.getLocalHost().getHostName();
122 } catch (UnknownHostException e)
123 {
124 this.serverURL = "Unknown host";
125 }
126 }
127
128 /**
129 * Creates a new ServerStartMessage from its encoded form.
130 *
131 * @param in The byte array containing the encoded form of the
132 * ServerStartMessage.
133 * @throws DataFormatException If the byte array does not contain a valid
134 * encoded form of the ServerStartMessage.
135 */
136 public ServerStartMessage(byte[] in) throws DataFormatException
137 {
138 super(MSG_TYPE_SERVER_START, in);
139
140 try
141 {
142 /* first bytes are the header */
143 int pos = headerLength;
144
145 /*
146 * read the dn
147 * first calculate the length then construct the string
148 */
149 int length = getNextLength(in, pos);
150 baseDn = new String(in, pos, length, "UTF-8");
151 pos += length +1;
152
153 /*
154 * read the ServerId
155 */
156 length = getNextLength(in, pos);
157 String serverIdString = new String(in, pos, length, "UTF-8");
158 serverId = Short.valueOf(serverIdString);
159 pos += length +1;
160
161 /*
162 * read the ServerURL
163 */
164 length = getNextLength(in, pos);
165 serverURL = new String(in, pos, length, "UTF-8");
166 pos += length +1;
167
168 /*
169 * read the maxReceiveDelay
170 */
171 length = getNextLength(in, pos);
172 maxReceiveDelay = Integer.valueOf(new String(in, pos, length, "UTF-8"));
173 pos += length +1;
174
175 /*
176 * read the maxReceiveQueue
177 */
178 length = getNextLength(in, pos);
179 maxReceiveQueue = Integer.valueOf(new String(in, pos, length, "UTF-8"));
180 pos += length +1;
181
182 /*
183 * read the maxSendDelay
184 */
185 length = getNextLength(in, pos);
186 maxSendDelay = Integer.valueOf(new String(in, pos, length, "UTF-8"));
187 pos += length +1;
188
189 /*
190 * read the maxSendQueue
191 */
192 length = getNextLength(in, pos);
193 maxSendQueue = Integer.valueOf(new String(in, pos, length, "UTF-8"));
194 pos += length +1;
195
196 /*
197 * read the windowSize
198 */
199 length = getNextLength(in, pos);
200 windowSize = Integer.valueOf(new String(in, pos, length, "UTF-8"));
201 pos += length +1;
202
203 /*
204 * read the heartbeatInterval
205 */
206 length = getNextLength(in, pos);
207 heartbeatInterval = Integer.valueOf(new String(in, pos, length, "UTF-8"));
208 pos += length +1;
209
210 /*
211 * read the sslEncryption setting
212 */
213 length = getNextLength(in, pos);
214 sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
215 pos += length +1;
216
217
218 /*
219 * read the handshakeOnly flag
220 */
221 length = getNextLength(in, pos);
222 handshakeOnly = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
223 pos += length +1;
224
225 /*
226 * read the ServerState
227 */
228 serverState = new ServerState(in, pos, in.length-1);
229
230 } catch (UnsupportedEncodingException e)
231 {
232 throw new DataFormatException("UTF-8 is not supported by this jvm.");
233 }
234 }
235
236 /**
237 * Get the ServerID from the message.
238 * @return the server ID
239 */
240 public short getServerId()
241 {
242 return serverId;
243 }
244
245 /**
246 * get the Server URL from the message.
247 * @return the server URL
248 */
249 public String getServerURL()
250 {
251 return serverURL;
252 }
253
254 /**
255 * Get the baseDn.
256 * @return Returns the baseDn.
257 */
258 public DN getBaseDn()
259 {
260 try
261 {
262 return DN.decode(baseDn);
263 } catch (DirectoryException e)
264 {
265 return null;
266 }
267 }
268
269 /**
270 * Get the maxReceiveDelay.
271 * @return Returns the maxReceiveDelay.
272 */
273 public int getMaxReceiveDelay()
274 {
275 return maxReceiveDelay;
276 }
277
278 /**
279 * Get the maxReceiveQueue.
280 * @return Returns the maxReceiveQueue.
281 */
282 public int getMaxReceiveQueue()
283 {
284 return maxReceiveQueue;
285 }
286
287 /**
288 * Get the maxSendDelay.
289 * @return Returns the maxSendDelay.
290 */
291 public int getMaxSendDelay()
292 {
293 return maxSendDelay;
294 }
295
296 /**
297 * Get the maxSendQueue.
298 * @return Returns the maxSendQueue.
299 */
300 public int getMaxSendQueue()
301 {
302 return maxSendQueue;
303 }
304
305 /**
306 * Get the ServerState.
307 * @return The ServerState.
308 */
309 public ServerState getServerState()
310 {
311 return serverState;
312 }
313
314 /**
315 * {@inheritDoc}
316 */
317 @Override
318 public byte[] getBytes()
319 {
320 try {
321 byte[] byteDn = baseDn.getBytes("UTF-8");
322 byte[] byteServerId = String.valueOf(serverId).getBytes("UTF-8");
323 byte[] byteServerUrl = serverURL.getBytes("UTF-8");
324 byte[] byteMaxRecvDelay =
325 String.valueOf(maxReceiveDelay).getBytes("UTF-8");
326 byte[] byteMaxRecvQueue =
327 String.valueOf(maxReceiveQueue).getBytes("UTF-8");
328 byte[] byteMaxSendDelay =
329 String.valueOf(maxSendDelay).getBytes("UTF-8");
330 byte[] byteMaxSendQueue =
331 String.valueOf(maxSendQueue).getBytes("UTF-8");
332 byte[] byteWindowSize =
333 String.valueOf(windowSize).getBytes("UTF-8");
334 byte[] byteHeartbeatInterval =
335 String.valueOf(heartbeatInterval).getBytes("UTF-8");
336 byte[] byteSSLEncryption =
337 String.valueOf(sslEncryption).getBytes("UTF-8");
338 byte[] byteServerState = serverState.getBytes();
339 byte[] byteHandshakeOnly =
340 String.valueOf(handshakeOnly).getBytes("UTF-8");
341
342 int length = byteDn.length + 1 + byteServerId.length + 1 +
343 byteServerUrl.length + 1 +
344 byteMaxRecvDelay.length + 1 +
345 byteMaxRecvQueue.length + 1 +
346 byteMaxSendDelay.length + 1 +
347 byteMaxSendQueue.length + 1 +
348 byteWindowSize.length + 1 +
349 byteHeartbeatInterval.length + 1 +
350 byteSSLEncryption.length + 1 +
351 byteHandshakeOnly.length + 1 +
352 byteServerState.length + 1;
353
354 /* encode the header in a byte[] large enough to also contain the mods */
355 byte resultByteArray[] = encodeHeader(MSG_TYPE_SERVER_START, length);
356 int pos = headerLength;
357
358 pos = addByteArray(byteDn, resultByteArray, pos);
359
360 pos = addByteArray(byteServerId, resultByteArray, pos);
361
362 pos = addByteArray(byteServerUrl, resultByteArray, pos);
363
364 pos = addByteArray(byteMaxRecvDelay, resultByteArray, pos);
365
366 pos = addByteArray(byteMaxRecvQueue, resultByteArray, pos);
367
368 pos = addByteArray(byteMaxSendDelay, resultByteArray, pos);
369
370 pos = addByteArray(byteMaxSendQueue, resultByteArray, pos);
371
372 pos = addByteArray(byteWindowSize, resultByteArray, pos);
373
374 pos = addByteArray(byteHeartbeatInterval, resultByteArray, pos);
375
376 pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
377
378 pos = addByteArray(byteHandshakeOnly, resultByteArray, pos);
379
380 pos = addByteArray(byteServerState, resultByteArray, pos);
381
382 return resultByteArray;
383 }
384 catch (UnsupportedEncodingException e)
385 {
386 return null;
387 }
388 }
389
390 /**
391 * Get the window size for the ldap server that created the message.
392 *
393 * @return The window size for the ldap server that created the message.
394 */
395 public int getWindowSize()
396 {
397 return windowSize;
398 }
399
400 /**
401 * Get the heartbeat interval requested by the ldap server that created the
402 * message.
403 *
404 * @return The heartbeat interval requested by the ldap server that created
405 * the message.
406 */
407 public long getHeartbeatInterval()
408 {
409 return heartbeatInterval;
410 }
411
412 /**
413 * Get the SSL encryption value for the ldap server that created the
414 * message.
415 *
416 * @return The SSL encryption value for the ldap server that created the
417 * message.
418 */
419 public boolean getSSLEncryption()
420 {
421 return sslEncryption;
422 }
423
424 /**
425 * Get the SSL encryption value for the ldap server that created the
426 * message.
427 *
428 * @return The SSL encryption value for the ldap server that created the
429 * message.
430 */
431 public boolean isHandshakeOnly()
432 {
433 return handshakeOnly;
434 }
435 }