package jxm.JWS.FR;
import jxm.CHRF;
import jxm.JWS.EX.InvalidDataException;
import jxm.JWS.EX.InvalidFrameException;
import java.nio.ByteBuffer;
public class CloseFrameBuilder extends FramedataImpl1 implements CloseFrame {
static final ByteBuffer emptybytebuffer = ByteBuffer.allocate(0);
private int code;
private String reason;
public CloseFrameBuilder() {
super(Opcode.CLOSING);
setFin(true);
}
public CloseFrameBuilder(int code) throws InvalidDataException {
super(Opcode.CLOSING);
setFin(true);
setCodeAndMessage(code, "");
}
public CloseFrameBuilder(int code, String m) throws InvalidDataException {
super(Opcode.CLOSING);
setFin(true);
setCodeAndMessage(code, m);
}
private void setCodeAndMessage(int code, String m) throws InvalidDataException {
if (m == null) {
m = "";
}
// CloseFrame.TLS_ERROR is not allowed to be transfered over the wire
if (code == TLS_ERROR) {
code = NOCODE;
m = "";
}
if (code == NOCODE) {
if (0 < m.length()) {
throw new InvalidDataException(PROTOCOL_ERROR, "A close frame must have a closecode if it has a reason");
}
return;// empty payload
}
byte[] by = CHRF.utf8Bytes(m);
ByteBuffer buf = ByteBuffer.allocate(4);
buf.putInt(code);
buf.position(2);
ByteBuffer pay = ByteBuffer.allocate(2 + by.length);
pay.put(buf);
pay.put(by);
pay.rewind();
setPayload(pay);
}
private void initCloseCode() throws InvalidFrameException {
code = NOCODE;
ByteBuffer payload = super.getPayloadData();
payload.mark();
if (payload.remaining() >= 2) {
ByteBuffer bb = ByteBuffer.allocate(4);
bb.position(2);
bb.putShort(payload.getShort());
bb.position(0);
code = bb.getInt();
if (code == ABNORMAL_CLOSE || code == TLS_ERROR || code == NOCODE || code > 4999 || code < 1000 || code == 1004) {
throw new InvalidFrameException("closecode must not be sent over the wire: " + code);
}
}
payload.reset();
}
@Override
public int getCloseCode() {
return code;
}
private void initMessage() throws InvalidDataException {
if (code == NOCODE) {
reason = CHRF.stringUtf8(super.getPayloadData());
} else {
ByteBuffer b = super.getPayloadData();
int mark = b.position();// because stringUtf8 also creates a mark
try {
b.position(b.position() + 2);
reason = CHRF.stringUtf8(b);
} catch (IllegalArgumentException e) {
throw new InvalidFrameException(e);
} finally {
b.position(mark);
}
}
}
@Override
public String getMessage() {
return reason;
}
@Override
public String toString() {
return super.toString() + "code: " + code;
}
@Override
public void setPayload(ByteBuffer payload) throws InvalidDataException {
super.setPayload(payload);
initCloseCode();
initMessage();
}
@Override
public ByteBuffer getPayloadData() {
if (code == NOCODE)
return emptybytebuffer;
return super.getPayloadData();
}
}