All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.termd.core.http.HttpTtyConnection Maven / Gradle / Ivy

Go to download

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