/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2009 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package erjang.driver;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SelectableChannel;
import kilim.Pausable;
import erjang.EBinary;
import erjang.EHandle;
import erjang.EObject;
import erjang.EPID;
import erjang.ERT;
import erjang.ERef;
import erjang.EString;
import erjang.NotImplemented;
/**
*
*/
public class FDDriverInstance extends EDriverInstance {
public static final int CTRL_OP_GET_WINSIZE = 100;
private final int in;
private final int out;
InputStream ins;
OutputStream outs;
/**
* @param in
* @param out
*/
public FDDriverInstance(int in, int out) {
super (new FDDriver());
this.in = in;
this.out = out;
if (in == 0) {
ins = ERT.getInputStream();
}
if (out == 1) {
outs = ERT.getOutputStream();
}
if (out == 2) {
outs = ERT.getErrorStream();
}
// that's it.
}
@Override
protected void readyAsync(EAsync data) throws Pausable {
data.ready();
}
public void setup() {
if (ins != null) {
new Thread() {
{ setDaemon(true); start(); setName("FD in="+in); }
void finish(final int howmany, final byte[] buffer) {
final EDriverTask dt = FDDriverInstance.this.task;
final byte[] ob = new byte[howmany];
System.arraycopy(buffer, 0, ob, 0, howmany);
ERT.run_async(new EAsync() {
@Override
public void ready() throws Pausable {
if (task.send_binary_data) {
EBinary out = new EBinary(ob);
task.output_from_driver(out);
} else {
EString str = EString.make(ob);
task.output_from_driver(str);
}
}
@Override
public void async() {
// do nothing //
}
}, dt);
}
@Override
public void run() {
byte[] buffer = new byte[1024];
while (true) {
try {
int howmany;
howmany = ins.read(buffer);
if (howmany < 0) {
if (task.send_eof) {
task.eof_from_driver_b();
}
return;
}
finish(howmany, buffer);
} catch (IOException e) {
if (e.getMessage().equals("Interrupted system call")) {
// ignore //
} else {
// TODO: we should really just ignore this; maybe log?
e.printStackTrace();
}
}
}
}
};
}
}
@Override
protected ByteBuffer control(EPID caller, int command, ByteBuffer out) throws Pausable {
if (command == CTRL_OP_GET_WINSIZE) {
// TODO: hmm, how do we do that?
// for now, we always respond 80x25.
ByteBuffer bb = ByteBuffer.allocate(8);
bb.order(ByteOrder.nativeOrder());
bb.putInt(80);
bb.putInt(25);
return bb;
} else {
throw ERT.badarg();
}
}
@Override
protected EObject call(EPID caller, int command, EObject data) throws Pausable {
// allways return null
return null;
}
@Override
protected void flush() throws Pausable {
}
@Override
protected void output(EHandle caller, ByteBuffer data) throws IOException, Pausable {
if (outs != null) {
if (data.hasArray()) {
outs.write(data.array(), data.arrayOffset() + data.position(), data.remaining());
} else {
throw new NotImplemented();
}
}
}
@Override
public void processExit(ERef monitor) throws Pausable {
// TODO Auto-generated method stub
}
@Override
protected void readyInput(SelectableChannel ch) throws Pausable {
}
@Override
protected void readyOutput(SelectableChannel evt) throws Pausable {
}
@Override
protected void timeout() throws Pausable {
}
}