/* * Copyright 2009 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.console; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolEncoder; import org.apache.mina.filter.codec.ProtocolEncoderOutput; import org.krakenapps.ansicode.AnsiEscapeCode; import org.krakenapps.api.TelnetCommand; class TelnetEncoder implements ProtocolEncoder { private final byte INTERPRET_AS_CONTROL = (byte) 255; public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { if (message instanceof TelnetOptionControl) { encodeOptionControl(message, out); } else if (message instanceof TelnetCommand) { encodeCommand(message, out); } else if (message instanceof String) { encodeString(session, message, out); } else if (message instanceof AnsiEscapeCode) { encodeAnsiEscapeCode(message, out); } else if (message instanceof byte[]) { encodeBytes(message, out); } } private void encodeAnsiEscapeCode(Object message, ProtocolEncoderOutput out) { AnsiEscapeCode ansiEscapeCode = (AnsiEscapeCode) message; IoBuffer buffer = getEscapedData(ansiEscapeCode.toByteArray()); buffer.flip(); out.write(buffer); } private void encodeBytes(Object message, ProtocolEncoderOutput out) { IoBuffer buffer = getEscapedData((byte[]) message); buffer.flip(); out.write(buffer); } private void encodeCommand(Object message, ProtocolEncoderOutput out) { TelnetCommand command = (TelnetCommand) message; byte[] commandBytes = command.toByteArray(); IoBuffer buffer = IoBuffer.allocate(1 + commandBytes.length); buffer.put(INTERPRET_AS_CONTROL); buffer.put(commandBytes); buffer.flip(); out.write(buffer); } private void encodeString(IoSession session, Object message, ProtocolEncoderOutput out) throws CharacterCodingException { String m = (String) message; if (m.length() == 0) return; byte[] string = m.getBytes(Charset.forName("utf-8")); IoBuffer buffer = getEscapedData(string); buffer.flip(); out.write(buffer); } private IoBuffer getEscapedData(byte[] data) { IoBuffer buffer = IoBuffer.allocate(data.length * 2); for (int i = 0; i < data.length; i++) { // escape IAC in data stream if (data[i] == INTERPRET_AS_CONTROL) { buffer.put(data[i]); buffer.put(data[i]); } else { buffer.put(data[i]); } } return buffer; } private void encodeOptionControl(Object message, ProtocolEncoderOutput out) { final int AVERAGE_OPTION_COMMAND_LENGTH = 3; TelnetOptionControl optionControl = (TelnetOptionControl) message; IoBuffer buffer = IoBuffer.allocate(AVERAGE_OPTION_COMMAND_LENGTH).setAutoExpand(true); // e.g. IAC (255), WILL (251), ECHO (1) buffer.put(INTERPRET_AS_CONTROL); buffer.put(optionControl.getTypeCode()); buffer.put(optionControl.getOptionCode()); buffer.flip(); out.write(buffer); } public void dispose(IoSession session) throws Exception { } }