// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2008  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.asteroid.server;

import java.io.IOException;
import java.net.*;

/**
 *  A bridge which is sending datagrams to a registered clients, and forwards datagrams from the
 *  client back.
 *
 *  This class is part of a solution for a
 *  <a href="http://www.heise.de/ct/creativ/08/02/details/">competition by the German computer magazine c't</a>
 */
public class Bridge
        implements DatagramListener,
                   Runnable
{
  /** Our socket. */
  private DatagramSocket socket;
  /** The datagram sender. */
  private DatagramSender sender;
  /** The current client. */
  private SocketAddress clientAddress;

  /**
   *  Create a bridge.
   *  @param port port to listen to
   *  @param sender sender for datagrams
   *  @throws SocketException on initialization problems
   */
  public Bridge(int port, DatagramSender sender) throws SocketException
  {
    socket = new DatagramSocket(port);
    this.sender = sender;
  }

  /**
   * Called when an incoming datagram was received.
   *
   * @param packet packet received
   * @param sndr datagram sender used for answers
   */
  public void datagramReceived(DatagramPacket packet, DatagramSender sndr)
  {
    if (clientAddress != null) {
      try {
        packet.setSocketAddress(clientAddress);
        socket.send(packet);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * Called when an outgoing datagram was sent.
   *
   * @param packet sent packet
   */
  public void datagramSent(DatagramPacket packet)
  {
  }

  /**
   * Start receiving telegrams.
   *
   * @see Thread#run()
   */
  public void run()
  {
    long lastErrorTime = 0;
    DatagramPacket packet = new DatagramPacket(new byte[8], 8);
    while (true) {
      try {
        socket.receive(packet);
        clientAddress = packet.getSocketAddress();
        sender.sendDatagram(packet);
      } catch (IOException e) {
        long now = System.currentTimeMillis();
        long delta = now - lastErrorTime;
        if (delta >= 0  &&  delta < 2) {
          // two errors in 2 ms, better stop, seems to be a pending error
          break;
        }
        lastErrorTime = now;
        e.printStackTrace(System.err);
      }
    }
  }
}
