/*
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.*;
import java.net.*;
/**
*
* @author Ian Preston
*/
public class RemoteBlockDevice implements BlockDevice
{
static enum Protocol {
READ, WRITE, TOTAL_SECTORS, CYLINDERS, HEADS, SECTORS, TYPE, INSERTED,
LOCKED, READ_ONLY, SET_LOCKED, CLOSE;
}
private DataInputStream in;
private DataOutputStream out;
public void configure(String spec) throws IOException
{
String server = spec;
int port = 6666;
int colon = spec.indexOf(':');
if (colon >= 0) {
port = Integer.parseInt(spec.substring(colon+1));
server = spec.substring(0, colon);
}
Socket sock = new Socket(server, port);
this.in = new DataInputStream(sock.getInputStream());
this.out = new DataOutputStream(sock.getOutputStream());
}
public RemoteBlockDevice()
{
}
public RemoteBlockDevice(InputStream in, OutputStream out)
{
this.in = new DataInputStream(in);
this.out = new DataOutputStream(out);
}
public synchronized void close()
{
try
{
out.write(Protocol.CLOSE.ordinal());
out.flush();
}
catch (Exception e) {e.printStackTrace();}
}
public synchronized int read(long sectorNumber, byte[] buffer, int size)
{
try
{
// System.out.println("trying to read " + sectorNumber);
out.write(Protocol.READ.ordinal());
out.writeLong(sectorNumber);
out.writeInt(size);
out.flush();
if (in.read() != 0)
throw new IOException("Read failed");
int result = in.readInt();
int toRead = in.readInt();
in.read(buffer, 0, toRead);
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized int write(long sectorNumber, byte[] buffer, int size)
{
try
{
// System.out.println("trying to write " + sectorNumber);
out.write(Protocol.WRITE.ordinal());
out.writeLong(sectorNumber);
out.writeInt(size*512);
out.write(buffer,0,size*512);
out.flush();
if (in.read() != 0)
throw new IOException("Write failed");
int result = in.readInt();
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized boolean isInserted()
{
try
{
out.write(Protocol.INSERTED.ordinal());
out.flush();
boolean result = in.readBoolean();
return result;
}
catch (Exception e) {e.printStackTrace();}
return false;
}
public synchronized boolean isLocked()
{
try
{
out.write(Protocol.LOCKED.ordinal());
out.flush();
boolean result = in.readBoolean();
return result;
}
catch (Exception e) {e.printStackTrace();}
return false;
}
public synchronized boolean isReadOnly()
{
try
{
out.write(Protocol.READ_ONLY.ordinal());
out.flush();
boolean result = in.readBoolean();
return result;
}
catch (Exception e) {e.printStackTrace();}
return false;
}
public synchronized void setLock(boolean locked)
{
try
{
out.write(Protocol.SET_LOCKED.ordinal());
out.writeBoolean(locked);
out.flush();
}
catch (Exception e) {e.printStackTrace();}
}
public synchronized long getTotalSectors()
{
try
{
out.write(Protocol.TOTAL_SECTORS.ordinal());
out.flush();
long result = in.readLong();
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized int getCylinders()
{
try
{
out.write(Protocol.CYLINDERS.ordinal());
out.flush();
int result = in.readInt();
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized int getHeads()
{
try
{
out.write(Protocol.HEADS.ordinal());
out.flush();
int result = in.readInt();
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized int getSectors()
{
try
{
out.write(Protocol.SECTORS.ordinal());
out.flush();
int result = in.readInt();
return result;
}
catch (Exception e) {e.printStackTrace();}
return -1;
}
public synchronized Type getType()
{
try
{
out.write(Protocol.TYPE.ordinal());
out.flush();
int result = in.readInt();
return Type.values()[result];
}
catch (Exception e) {e.printStackTrace();}
return null;
}
// public static void main(String[] args) throws Exception
// {
// PipedOutputStream out1 = new PipedOutputStream();
// PipedInputStream in1 = new PipedInputStream(out1);
// PipedOutputStream out2 = new PipedOutputStream();
// PipedInputStream in2 = new PipedInputStream(out2);
// RemoteBlockDevice remote = new RemoteBlockDevice(in1, out2);
// RemoteBlockDeviceImpl remoteImpl = new RemoteBlockDeviceImpl(in2, out1, new TreeBlockDevice(new File(args[0])));
// byte[] buffer = new byte[512];
// for (int i=0;i<5;i++)
// System.out.println(remote.read(63, buffer, 1));
// }
}