/*
* Copyright (c) 2003 University of Murcia. All rights reserved.
* --------------------------------------------------------------
* For more information, please see .
*/
package org.umu.cops.stack;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* COPS Sync State Message (RFC 2748 pag. 26 and pag. 29
*
* The format of the Synchronize State Query message is as follows:
*
* ::=
* []
* []
*
* This message indicates that the remote PDP wishes the client (which
* appears in the common header) to re-send its state. If the optional
* Client Handle is present, only the state associated with this handle
* is synchronized. If the PEP does not recognize the requested handle,
* it MUST immediately send a DRQ message to the PDP for the handle that
* was specified in the SSQ message. If no handle is specified in the
* SSQ message, all the active client state MUST be synchronized with
* the PDP.
*
* The client performs state synchronization by re-issuing request
* queries of the specified client-type for the existing state in the
* PEP. When synchronization is complete, the PEP MUST issue a
* synchronize state complete message to the PDP.
*
* ::=
* []
* []
*
* The Client Handle object only needs to be included if the corresponding
* Synchronize State Message originally referenced a specific handle.
*
* @version COPSSyncStateMsg.java, v 1.00 2003
*
*/
public class COPSSyncStateMsg extends COPSMsg {
/* COPSHeader coming from base class */
private COPSHandle _clientHandle;
private COPSIntegrity _integrity;
public COPSSyncStateMsg() {
_clientHandle = null;
_integrity = null;
}
/**
Parse data and create COPSSyncStateMsg object
*/
protected COPSSyncStateMsg(byte[] data) throws COPSException {
_clientHandle = null;
_integrity = null;
parse(data);
}
/**
* Checks the sanity of COPS message and throw an
* COPSException when data is bad.
*/
public void checkSanity() throws COPSException {
if (_hdr == null) {
throw new COPSException("Bad message format");
}
}
/**
* Add message header
*
* @param hdr a COPSHeader
*
* @throws COPSException
*
*/
public void add (COPSHeader hdr) throws COPSException {
if (hdr == null)
throw new COPSException ("Null Header");
if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&
(hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))
throw new COPSException ("Error Header (no COPS_OP_SSX)");
_hdr = hdr;
setMsgLength();
}
/**
* Add client handle to the message
*
* @param handle a COPSHandle
*
* @throws COPSException
*
*/
public void add (COPSHandle handle) throws COPSException {
if (handle == null)
throw new COPSException ("Null Handle");
//Message integrity object should be the very last one
//If it is already added
if (_integrity != null)
throw new COPSException ("No null Handle");
_clientHandle = handle;
setMsgLength();
}
/**
* Add integrity object
*
* @param integrity a COPSIntegrity
*
* @throws COPSException
*
*/
public void add (COPSIntegrity integrity) throws COPSException {
if (integrity == null)
throw new COPSException ("Null Integrity");
if (!integrity.isMessageIntegrity())
throw new COPSException ("Error Integrity");
_integrity = integrity;
setMsgLength();
}
/**
* If the optional Client Handle is present, only the state associated
* with this handle is synchronized. If no handle is specified in the
* SSQ message, all the active client state MUST be synchronized with
* the PDP.
*
* @return a boolean
*
*/
public boolean hasClientHandle() {
return (_clientHandle != null);
}
/**
* Get client Handle
*
* @return a COPSHandle
*
*/
public COPSHandle getClientHandle() {
return _clientHandle;
}
/**
* Returns true if it has integrity object
*
* @return a boolean
*
*/
public boolean hasIntegrity() {
return (_integrity != null);
}
/**
* Get Integrity. Should check hasIntegrity() before calling
*
* @return a COPSIntegrity
*
*/
public COPSIntegrity getIntegrity() {
return (_integrity);
}
/**
* Writes data to given socket
*
* @param id a Socket
*
* @throws IOException
*
*/
public void writeData(Socket id) throws IOException {
// checkSanity();
if (_hdr != null) _hdr.writeData(id);
if (_clientHandle != null) _clientHandle.writeData(id);
if (_integrity != null) _integrity.writeData(id);
}
/**
* Parse data
*
* @param data a byte[]
*
* @throws COPSException
*
*/
protected void parse(byte[] data) throws COPSException {
super.parseHeader(data);
while (_dataStart < _dataLength) {
byte[] buf = new byte[data.length - _dataStart];
System.arraycopy(data,_dataStart,buf,0,data.length - _dataStart);
COPSObjHeader objHdr = COPSObjHeader.parse(buf);
switch (objHdr.getCNum()) {
case HANDLE:
_clientHandle = new COPSHandle(buf);
_dataStart += _clientHandle.getDataLength();
break;
case MSG_INTEGRITY:
_integrity = new COPSIntegrity(buf);
_dataStart += _integrity.getDataLength();
break;
default:
throw new COPSException("Bad Message format, unknown object type");
}
}
checkSanity();
}
/**
* Parse data
*
* @param hdr a COPSHeader
* @param data a byte[]
*
* @throws COPSException
*
*/
protected void parse(COPSHeader hdr, byte[] data) throws COPSException {
if ((hdr.getOpCode() != COPSHeader.COPS_OP_SSC) &&
(hdr.getOpCode() != COPSHeader.COPS_OP_SSQ))
throw new COPSException ("Error Header (no COPS_OP_SSX)");
_hdr = hdr;
parse(data);
setMsgLength();
}
/**
* Set the message length, base on the set of objects it contains
*
* @throws COPSException
*
*/
protected void setMsgLength() throws COPSException {
short len = 0;
if (_clientHandle != null) len += _clientHandle.getDataLength();
if (_integrity != null) len += _integrity.getDataLength();
_hdr.setMsgLength(len);
}
/**
* Write an object textual description in the output stream
*
* @param os an OutputStream
*
* @throws IOException
*
*/
public void dump(OutputStream os) throws IOException {
_hdr.dump(os);
if (_clientHandle != null)
_clientHandle.dump(os);
if (_integrity != null) {
_integrity.dump(os);
}
}
}