/*
  TCP/IP 越しにデバイス接続を行うクラス
  Satofumi KAMIMURA
  $Id: connectionHub.cpp 286 2008-10-20 09:40:22Z satofumi $
*/

#include "connectionHub.h"
#include "serialDevice.h"
enum { BufferSize = 4096 };


ConnectionHub::ConnectionHub(ConnectionDevice& a, ConnectionDevice& b)
  : state(Connected), server(NULL), port_a(&a), port_b(&b) {
}


ConnectionHub::ConnectionHub(int port, const char* device, long baudrate)
  : state(WaitToConnect),
    server(new TcpipServer()), con_device(device), con_baudrate(baudrate),
    port_a(NULL), port_b(NULL) {
  server->activate(port);
}


ConnectionHub::~ConnectionHub(void) {
  disconnect();
}


void ConnectionHub::disconnect(void) {
  state = Closed;

  delete port_a;
  port_a = NULL;

  delete port_b;
  port_b = NULL;

  delete server;
  server = NULL;
}


bool ConnectionHub::preUpdate(bool& ret_value) {
  if (state == Closed) {
    ret_value = false;
    return true;
  }

  if (state == WaitToConnect) {
    TcpipDevice* con = server->accept(0);
    if (!con) {
      ret_value = true;
      return true;
    }
    port_a = con;
    port_b = new SerialDevice;
    if (port_b->connect(con_device, con_baudrate) < 0) {
      disconnect();
    }
    state = Connected;
    delete server;
    server = NULL;
  }
  return false;
}


bool ConnectionHub::update(void) {
  bool ret_value = false;
  if (preUpdate(ret_value)) {
    return ret_value;
  }

  // データの送受信
  char buffer[BufferSize];
  if (!port_a->isConnected() || port_a->size() > 0) {
    int n = port_a->recv(buffer, BufferSize);
    if (n < 0) {
      disconnect();
      return false;
    }
    port_b->send(buffer, n);
  }

  if (!port_b->isConnected() || port_b->size() > 0) {
    int n = port_b->recv(buffer, BufferSize);
    if (n < 0) {
      disconnect();
      return false;
    }
    port_a->send(buffer, n);
  }
  return true;
}
