Package com.subgraph.orchid.circuits.cells

Source Code of com.subgraph.orchid.circuits.cells.RelayCellImpl

package com.subgraph.orchid.circuits.cells;

import java.nio.ByteBuffer;

import com.subgraph.orchid.Cell;
import com.subgraph.orchid.CircuitNode;
import com.subgraph.orchid.RelayCell;
import com.subgraph.orchid.TorException;

public class RelayCellImpl extends CellImpl implements RelayCell {

  public static RelayCell createFromCell(CircuitNode node, Cell cell) {
    if(cell.getCommand() != Cell.RELAY)
      throw new TorException("Attempted to create RelayCell from Cell type: "+ cell.getCommand());
    return new RelayCellImpl(node, cell.getCellBytes());
  }

  private final int streamId;
  private final int relayCommand;
  private final CircuitNode circuitNode;
  private final boolean isOutgoing;

  /*
   * The payload of each unencrypted RELAY cell consists of:
     *     Relay command           [1 byte]
     *     'Recognized'            [2 bytes]
     *     StreamID                [2 bytes]
     *     Digest                  [4 bytes]
     *     Length                  [2 bytes]
     *     Data                    [CELL_LEN-14 bytes]
     */
 
   public RelayCellImpl(CircuitNode node, int circuit, int stream, int relayCommand) {
     this(node, circuit, stream, relayCommand, false);
   }
  
   public RelayCellImpl(CircuitNode node, int circuit, int stream, int relayCommand, boolean isRelayEarly) {
    super(circuit, (isRelayEarly) ? (Cell.RELAY_EARLY) : (Cell.RELAY));
    this.circuitNode = node;
    this.relayCommand = relayCommand;
    this.streamId = stream;
    this.isOutgoing = true;
    putByte(relayCommand)// Command
    putShort(0);      // 'Recognized'
    putShort(stream);    // Stream
    putInt(0);        // Digest
    putShort(0);      // Length 
  }

  private RelayCellImpl(CircuitNode node, byte[] rawCell) {
    super(rawCell);
    this.circuitNode = node;
    this.relayCommand = getByte();
    getShort();
    this.streamId = getShort();
    this.isOutgoing = false;
    getInt();
    int payloadLength = getShort();
    cellBuffer.mark(); // End of header
    if(RelayCell.HEADER_SIZE + payloadLength > rawCell.length)
      throw new TorException("Header length field exceeds total size of cell");
    cellBuffer.limit(RelayCell.HEADER_SIZE + payloadLength);
  }

  public int getStreamId() {
    return streamId;
  }

  public int getRelayCommand() {
    return relayCommand;
  }

  public void setLength() {
    putShortAt(LENGTH_OFFSET, (short) (cellBytesConsumed() - HEADER_SIZE));
  }

  public void setDigest(byte[] digest) {
    for(int i = 0; i < 4; i++)
      putByteAt(DIGEST_OFFSET + i, digest[i]);
  }

  public ByteBuffer getPayloadBuffer() {
    final ByteBuffer dup = cellBuffer.duplicate();
    dup.reset();
    return dup.slice();
  }

  public CircuitNode getCircuitNode() {
    return circuitNode;
  }

  public String toString() {
    if(isOutgoing)
      return "["+ commandToDescription(relayCommand) +" stream="+ streamId +" payload_len="+ (cellBytesConsumed() - HEADER_SIZE) +" dest="+ circuitNode +"]";
    else
      return "["+ commandToString() + " stream="+ streamId + " payload_len="+ cellBuffer.remaining() +" source="+ circuitNode + "]";
  }

  public String commandToString() {
    if(relayCommand == RELAY_TRUNCATED) {
      final int code = getByteAt(HEADER_SIZE);
      return commandToDescription(relayCommand) + " ("+ CellImpl.errorToDescription(code) +")";
    } else if(relayCommand == RELAY_END) {
      final int code = getByteAt(HEADER_SIZE);
      return commandToDescription(relayCommand) +" ("+ reasonToDescription(code) +")";
    }
    else
      return commandToDescription(relayCommand);
  }

  public static String reasonToDescription(int reasonCode) {
    switch(reasonCode) {
    case REASON_MISC:
      return "Unlisted reason";
    case REASON_RESOLVEFAILED:
      return "Couldn't look up hostname";
    case REASON_CONNECTREFUSED:
      return "Remote host refused connection";
    case REASON_EXITPOLICY:
      return "OR refuses to connect to host or port";
    case REASON_DESTROY:
      return "Circuit is being destroyed";
    case REASON_DONE:
      return "Anonymized TCP connection was closed";
    case REASON_TIMEOUT:
      return "Connection timed out, or OR timed out while connecting";
    case REASON_HIBERNATING:
      return "OR is temporarily hibernating";
    case REASON_INTERNAL:
      return "Internal error at the OR";
    case REASON_RESOURCELIMIT:
      return "OR has no resources to fulfill request";
    case REASON_CONNRESET:
      return "Connection was unexpectedly reset";
    case REASON_TORPROTOCOL:
      return "Tor protocol violation";
    case REASON_NOTDIRECTORY:
      return "Client sent RELAY_BEGIN_DIR to a non-directory server.";
    default:
      return "Reason code "+ reasonCode;
    }
  }

  public static String commandToDescription(int command) {
    switch(command) {
    case RELAY_BEGIN:
      return "RELAY_BEGIN";
    case RELAY_DATA:
      return "RELAY_DATA";
    case RELAY_END:
      return "RELAY_END";
    case RELAY_CONNECTED:
      return "RELAY_CONNECTED";
    case RELAY_SENDME:
      return "RELAY_SENDME";
    case RELAY_EXTEND:
      return "RELAY_EXTEND";
    case RELAY_EXTENDED:
      return "RELAY_EXTENDED";
    case RELAY_TRUNCATE:
      return "RELAY_TRUNCATE";
    case RELAY_TRUNCATED:
      return "RELAY_TRUNCATED";
    case RELAY_DROP:
      return "RELAY_DROP";
    case RELAY_RESOLVE:
      return "RELAY_RESOLVE";
    case RELAY_RESOLVED:
      return "RELAY_RESOLVED";
    case RELAY_BEGIN_DIR:
      return "RELAY_BEGIN_DIR";
    case RELAY_EXTEND2:
      return "RELAY_EXTEND2";
    case RELAY_EXTENDED2:
      return "RELAY_EXTENDED2";
    default:
      return "Relay command = "+ command;
    }
  }
}
TOP

Related Classes of com.subgraph.orchid.circuits.cells.RelayCellImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.