/*
JPC: An x86 PC Hardware Emulator for a pure Java Virtual Machine
Release Version 2.4
A project from the Physics Dept, The University of Oxford
Copyright (C) 2007-2010 The University of Oxford
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Details (including contact information) can be found at:
jpc.sourceforge.net
or the developer website
sourceforge.net/projects/jpc/
Conceived and Developed by:
Rhys Newman, Ian Preston, Chris Dennis
End of licence header
*/
package org.jpc.support;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Ian Preston
*/
public class EthernetHub extends EthernetOutput
{
private int errorDelay, port;
private String serverHost;
private volatile DataOutputStream out;
private volatile DataInputStream in;
private int packetSize;
private Queue<byte[]> inQueue = new ConcurrentLinkedQueue<byte[]>();
private Queue<byte[]> outQueue = new ConcurrentLinkedQueue<byte[]>();
public EthernetHub(String host, int port)
{
packetSize = -1;
serverHost = host;
this.port = port;
errorDelay = 10000;
System.out.println("Connecting to remote EthernetHub at: " + host + ":" + port);
new Thread(new Reader()).start();
new Thread(new Writer()).start();
}
private synchronized void reconnect()
{
notifyAll();
if (in != null)
return;
in = null;
out = null;
while (true)
{
try
{
Socket server = new Socket(serverHost, port);
server.setTcpNoDelay(true);
server.setPerformancePreferences(0, 2, 1);
out = new DataOutputStream(server.getOutputStream());
in = new DataInputStream(server.getInputStream());
errorDelay = 1000;
return;
}
catch (Exception e)
{
errorDelay = Math.min(errorDelay+2000, 30000);
System.out.println("Error connecting to ethernet hub: "+e);
try
{
wait(errorDelay);
}
catch (Exception ee) {}
}
}
}
class Reader implements Runnable
{
public void run()
{
while (true)
{
if (inQueue.size() > 100)
{
System.out.println("Clearing ETH0 packet queue");
inQueue.clear();
}
try
{
int size = in.readInt();
System.out.println(">>> "+size);
byte[] packet = new byte[size];
in.readFully(packet);
inQueue.add(packet);
}
catch (Exception ex)
{
in = null;
out = null;
reconnect();
}
}
}
}
class Writer implements Runnable
{
public void run()
{
while (true)
{
try
{
synchronized (outQueue)
{
while (outQueue.size() == 0)
outQueue.wait();
}
byte[] packet = outQueue.poll();
out.writeInt(packet.length);
out.write(packet);
out.flush();
}
catch (Exception ex)
{
in = null;
out = null;
reconnect();
}
}
}
}
public byte[] getPacket()
{
byte[] packet = inQueue.poll();
return packet;
}
public void sendPacket(byte[] data, int offset, int length)
{
byte[] p = new byte[length];
System.arraycopy(data, offset, p, 0, length);
synchronized (outQueue)
{
outQueue.add(p);
outQueue.notify();
}
}
}