io.termd.core.http.HttpTtyConnection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of termd-core Show documentation
Show all versions of termd-core Show documentation
An open source terminal daemon library providing terminal handling in Java,
back ported to Alibaba by core engine team to support running on JDK 6+.
The newest version!
/*
* Copyright 2015 Julien Viet
*
* 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 io.termd.core.http;
import java.nio.charset.Charset;
import java.util.Map;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import io.termd.core.function.BiConsumer;
import io.termd.core.function.Consumer;
import io.termd.core.io.BinaryDecoder;
import io.termd.core.io.BinaryEncoder;
import io.termd.core.tty.TtyConnectionSupport;
import io.termd.core.tty.TtyEvent;
import io.termd.core.tty.TtyEventDecoder;
import io.termd.core.tty.TtyOutputMode;
import io.termd.core.util.Vector;
/**
* A connection to an http client, independant of the protocol, it could be straight Websockets or
* SockJS, etc...
*
* The incoming protocol is based on json messages:
*
* {
* "action": "read",
* "data": "what the user typed"
* }
*
* or
*
* {
* "action": "resize",
* "cols": 30,
* "rows: 50
* }
*
* @author Julien Viet
* @author Matej Lazar
*/
public abstract class HttpTtyConnection extends TtyConnectionSupport {
public static final Vector DEFAULT_SIZE = new Vector(80, 24);
private Charset charset;
private Vector size;
private Consumer sizeHandler;
private final TtyEventDecoder eventDecoder;
private final BinaryDecoder decoder;
private final Consumer stdout;
private Consumer closeHandler;
private Consumer termHandler;
private long lastAccessedTime = System.currentTimeMillis();
public HttpTtyConnection() {
this(Charset.forName("UTF-8"), DEFAULT_SIZE);
}
public HttpTtyConnection(Charset charset, Vector size) {
this.charset = charset;
this.size = size;
this.eventDecoder = new TtyEventDecoder(3, 26, 4);
this.decoder = new BinaryDecoder(512, charset, eventDecoder);
this.stdout = new TtyOutputMode(new BinaryEncoder(charset, new Consumer() {
@Override
public void accept(byte[] bytes) {
write(bytes);
}
}));
}
@Override
public Charset outputCharset() {
return charset;
}
@Override
public Charset inputCharset() {
return charset;
}
@Override
public long lastAccessedTime() {
return lastAccessedTime;
}
@Override
public String terminalType() {
return "vt100";
}
protected abstract void write(byte[] buffer);
/**
* Special case to handle tty events.
*
* @param bytes
*/
public void writeToDecoder(byte[] bytes) {
lastAccessedTime = System.currentTimeMillis();
decoder.write(bytes);
}
public void writeToDecoder(String msg) {
JSONObject obj;
String action;
try {
obj = JSON.parseObject(msg);
action = obj.getString("action");
} catch (Exception e) {
// Log this
return;
}
if ("read".equals(action)) {
lastAccessedTime = System.currentTimeMillis();
String data = obj.getString("data");
decoder.write(data.getBytes()); //write back echo
} else if ("resize".equals(action)) {
try {
int cols = obj.containsKey("cols") ? obj.getIntValue("cols") : size.x();
int rows = obj.containsKey("rows") ? obj.getIntValue("rows") : size.y();
if (cols > 0 && rows > 0) {
Vector newSize = new Vector(cols, rows);
if (!newSize.equals(size())) {
size = newSize;
if (sizeHandler != null) {
sizeHandler.accept(size);
}
}
}
} catch (Exception e) {
// Invalid size
// Log this
}
}
}
private static Object getOrDefault(Map map, String key, Object defaultValue) {
return (map.containsKey(key)) ? map.get(key) : defaultValue;
}
public Consumer getTerminalTypeHandler() {
return termHandler;
}
public void setTerminalTypeHandler(Consumer handler) {
termHandler = handler;
}
@Override
public Vector size() {
return size;
}
public Consumer getSizeHandler() {
return sizeHandler;
}
public void setSizeHandler(Consumer handler) {
this.sizeHandler = handler;
}
@Override
public BiConsumer getEventHandler() {
return eventDecoder.getEventHandler();
}
@Override
public void setEventHandler(BiConsumer handler) {
eventDecoder.setEventHandler(handler);
}
public Consumer getStdinHandler() {
return eventDecoder.getReadHandler();
}
public void setStdinHandler(Consumer handler) {
eventDecoder.setReadHandler(handler);
}
public Consumer stdoutHandler() {
return stdout;
}
@Override
public void setCloseHandler(Consumer closeHandler) {
this.closeHandler = closeHandler;
}
@Override
public Consumer getCloseHandler() {
return closeHandler;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy