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 }