Code cleanup for modem plugin, better locking in ModemImpl.

This commit is contained in:
akwizgran
2012-12-10 16:15:50 +00:00
parent 15ab5be476
commit cd3bacc8cf
5 changed files with 60 additions and 44 deletions

View File

@@ -15,10 +15,9 @@ class Crc32 {
} }
} }
static long update(long c, byte[] b, int off, int len) { private static long update(long c, byte[] b, int off, int len) {
for(int i = off; i < off + len; i++) { for(int i = off; i < off + len; i++)
c = TABLE[(int) ((c ^ b[i]) & 0xff)] ^ (c >> 8); c = TABLE[(int) ((c ^ b[i]) & 0xff)] ^ (c >> 8);
}
return c; return c;
} }

View File

@@ -8,7 +8,7 @@ abstract class Frame {
protected final byte[] buf; protected final byte[] buf;
Frame(byte[] buf) { protected Frame(byte[] buf) {
this.buf = buf; this.buf = buf;
} }
@@ -49,8 +49,8 @@ abstract class Frame {
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof Frame) { if(o instanceof Frame) {
Frame f = (Frame) o; Frame f = (Frame) o;
if(buf[0] != f.buf[0]) return false; return buf[0] == f.buf[0] &&
return getSequenceNumber() == f.getSequenceNumber(); getSequenceNumber() == f.getSequenceNumber();
} }
return false; return false;
} }

View File

@@ -28,10 +28,10 @@ interface Modem {
boolean dial(String number) throws IOException; boolean dial(String number) throws IOException;
/** Returns a stream for reading from the currently connected call. */ /** Returns a stream for reading from the currently connected call. */
InputStream getInputStream(); InputStream getInputStream() throws IOException;
/** Returns a stream for writing to the currently connected call. */ /** Returns a stream for writing to the currently connected call. */
OutputStream getOutputStream(); OutputStream getOutputStream() throws IOException;
/** Hangs up the modem, ending the currently connected call. */ /** Hangs up the modem, ending the currently connected call. */
void hangUp() throws IOException; void hangUp() throws IOException;

View File

@@ -9,7 +9,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -32,20 +31,20 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
private final Executor executor; private final Executor executor;
private final Callback callback; private final Callback callback;
private final SerialPort port; private final SerialPort port;
private final AtomicBoolean initialised, connected; private final AtomicBoolean initialised; // Locking: self
private final Semaphore offHook; private final AtomicBoolean connected; // Locking: self
private final byte[] line; private final byte[] line;
private int lineLen = 0; private int lineLen = 0;
private volatile ReliabilityLayer reliabilityLayer = null; private ReliabilityLayer reliabilityLayer = null; // Locking: this
private boolean offHook = false; // Locking: this;
ModemImpl(Executor executor, Callback callback, String portName) { ModemImpl(Executor executor, Callback callback, String portName) {
this.executor = executor; this.executor = executor;
this.callback = callback; this.callback = callback;
port = new SerialPort(portName); port = new SerialPort(portName);
initialised = new AtomicBoolean(false); initialised = new AtomicBoolean(false);
offHook = new Semaphore(1);
connected = new AtomicBoolean(false); connected = new AtomicBoolean(false);
line = new byte[MAX_LINE_LENGTH]; line = new byte[MAX_LINE_LENGTH];
} }
@@ -79,19 +78,19 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try { try {
synchronized(initialised) { synchronized(initialised) {
if(!initialised.get()) initialised.wait(OK_TIMEOUT); if(!initialised.get()) initialised.wait(OK_TIMEOUT);
if(initialised.get()) return;
} }
} catch(InterruptedException e) { } catch(InterruptedException e) {
tryToClose(port); tryToClose(port);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new IOException("Interrupted while initialising modem"); throw new IOException("Interrupted while initialising modem");
} }
if(!initialised.get()) tryToClose(port);
throw new IOException("Modem did not respond"); throw new IOException("Modem did not respond");
} }
public void stop() throws IOException { public void stop() throws IOException {
if(offHook.tryAcquire()) offHook.release(); hangUp();
else hangUp();
try { try {
port.closePort(); port.closePort();
} catch(SerialPortException e) { } catch(SerialPortException e) {
@@ -100,13 +99,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
} }
public boolean dial(String number) throws IOException { public boolean dial(String number) throws IOException {
if(!offHook.tryAcquire()) { synchronized(this) {
if(LOG.isLoggable(INFO)) if(offHook) {
LOG.info("Not dialling - call in progress"); if(LOG.isLoggable(INFO))
return false; LOG.info("Not dialling - call in progress");
return false;
}
reliabilityLayer = new ReliabilityLayer(this);
reliabilityLayer.start();
offHook = true;
} }
reliabilityLayer = new ReliabilityLayer(this);
reliabilityLayer.start();
if(LOG.isLoggable(INFO)) LOG.info("Dialling"); if(LOG.isLoggable(INFO)) LOG.info("Dialling");
try { try {
port.writeBytes(("ATDT" + number + "\r\n").getBytes("US-ASCII")); port.writeBytes(("ATDT" + number + "\r\n").getBytes("US-ASCII"));
@@ -117,36 +119,46 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
try { try {
synchronized(connected) { synchronized(connected) {
if(!connected.get()) connected.wait(CONNECT_TIMEOUT); if(!connected.get()) connected.wait(CONNECT_TIMEOUT);
if(connected.get()) return true;
} }
} catch(InterruptedException e) { } catch(InterruptedException e) {
tryToClose(port); tryToClose(port);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new IOException("Interrupted while connecting outgoing call"); throw new IOException("Interrupted while connecting outgoing call");
} }
if(connected.get()) return true;
hangUp(); hangUp();
return false; return false;
} }
public InputStream getInputStream() { public synchronized InputStream getInputStream() throws IOException {
return reliabilityLayer.getInputStream(); if(offHook) return reliabilityLayer.getInputStream();
throw new IOException("Not connected");
} }
public OutputStream getOutputStream() { public synchronized OutputStream getOutputStream() throws IOException {
return reliabilityLayer.getOutputStream(); if(offHook) return reliabilityLayer.getOutputStream();
throw new IOException("Not connected");
} }
public void hangUp() throws IOException { public void hangUp() throws IOException {
synchronized(this) {
if(!offHook) {
if(LOG.isLoggable(INFO))
LOG.info("Not hanging up - already on the hook");
return;
}
reliabilityLayer.stop();
reliabilityLayer = null;
offHook = false;
}
if(LOG.isLoggable(INFO)) LOG.info("Hanging up"); if(LOG.isLoggable(INFO)) LOG.info("Hanging up");
connected.set(false);
try { try {
port.setDTR(false); port.setDTR(false);
} catch(SerialPortException e) { } catch(SerialPortException e) {
tryToClose(port); tryToClose(port);
throw new IOException(e.toString()); throw new IOException(e.toString());
} }
reliabilityLayer.stop();
connected.set(false);
offHook.release();
} }
public void handleWrite(byte[] b) throws IOException { public void handleWrite(byte[] b) throws IOException {
@@ -193,8 +205,8 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
if(LOG.isLoggable(INFO)) LOG.info("Modem status: " + s); if(LOG.isLoggable(INFO)) LOG.info("Modem status: " + s);
if(s.startsWith("CONNECT")) { if(s.startsWith("CONNECT")) {
synchronized(connected) { synchronized(connected) {
if(!connected.getAndSet(true)) connected.set(true);
connected.notifyAll(); connected.notifyAll();
} }
// There might be data in the buffer as well as text // There might be data in the buffer as well as text
int off = i + 1; int off = i + 1;
@@ -211,8 +223,8 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
} }
} else if(s.equals("OK")) { } else if(s.equals("OK")) {
synchronized(initialised) { synchronized(initialised) {
if(!initialised.getAndSet(true)) initialised.set(true);
initialised.notifyAll(); initialised.notifyAll();
} }
} else if(s.equals("RING")) { } else if(s.equals("RING")) {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@@ -233,13 +245,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
} }
private void answer() throws IOException { private void answer() throws IOException {
if(!offHook.tryAcquire()) { synchronized(this) {
if(LOG.isLoggable(INFO)) if(offHook) {
LOG.info("Not answering - call in progress"); if(LOG.isLoggable(INFO))
return; LOG.info("Not answering - call in progress");
return;
}
reliabilityLayer = new ReliabilityLayer(this);
reliabilityLayer.start();
offHook = true;
} }
reliabilityLayer = new ReliabilityLayer(this);
reliabilityLayer.start();
if(LOG.isLoggable(INFO)) LOG.info("Answering"); if(LOG.isLoggable(INFO)) LOG.info("Answering");
try { try {
port.writeBytes("ATA\r\n".getBytes("US-ASCII")); port.writeBytes("ATA\r\n".getBytes("US-ASCII"));
@@ -247,16 +262,18 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
tryToClose(port); tryToClose(port);
throw new IOException(e.toString()); throw new IOException(e.toString());
} }
boolean success = false;
try { try {
synchronized(connected) { synchronized(connected) {
if(!connected.get()) connected.wait(CONNECT_TIMEOUT); if(!connected.get()) connected.wait(CONNECT_TIMEOUT);
success = connected.get();
} }
} catch(InterruptedException e) { } catch(InterruptedException e) {
tryToClose(port); tryToClose(port);
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new IOException("Interrupted while connecting incoming call"); throw new IOException("Interrupted while connecting incoming call");
} }
if(connected.get()) callback.incomingCallConnected(); if(success) callback.incomingCallConnected();
else hangUp(); else hangUp();
} }

View File

@@ -208,11 +208,11 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private final CountDownLatch finished = new CountDownLatch(1); private final CountDownLatch finished = new CountDownLatch(1);
public InputStream getInputStream() { public InputStream getInputStream() throws IOException {
return modem.getInputStream(); return modem.getInputStream();
} }
public OutputStream getOutputStream() { public OutputStream getOutputStream() throws IOException {
return modem.getOutputStream(); return modem.getOutputStream();
} }