From cd3bacc8cf247dcefe3daa7cf22b932adc8a4b2c Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Mon, 10 Dec 2012 16:15:50 +0000 Subject: [PATCH] Code cleanup for modem plugin, better locking in ModemImpl. --- .../src/net/sf/briar/plugins/modem/Crc32.java | 5 +- .../src/net/sf/briar/plugins/modem/Frame.java | 6 +- .../src/net/sf/briar/plugins/modem/Modem.java | 4 +- .../net/sf/briar/plugins/modem/ModemImpl.java | 85 +++++++++++-------- .../sf/briar/plugins/modem/ModemPlugin.java | 4 +- 5 files changed, 60 insertions(+), 44 deletions(-) diff --git a/briar-core/src/net/sf/briar/plugins/modem/Crc32.java b/briar-core/src/net/sf/briar/plugins/modem/Crc32.java index 9cd9d2d81c..8279d3c971 100644 --- a/briar-core/src/net/sf/briar/plugins/modem/Crc32.java +++ b/briar-core/src/net/sf/briar/plugins/modem/Crc32.java @@ -15,10 +15,9 @@ class Crc32 { } } - static long update(long c, byte[] b, int off, int len) { - for(int i = off; i < off + len; i++) { + private static long update(long c, byte[] b, int off, int len) { + for(int i = off; i < off + len; i++) c = TABLE[(int) ((c ^ b[i]) & 0xff)] ^ (c >> 8); - } return c; } diff --git a/briar-core/src/net/sf/briar/plugins/modem/Frame.java b/briar-core/src/net/sf/briar/plugins/modem/Frame.java index 3feb0e47e6..fc80bd6b88 100644 --- a/briar-core/src/net/sf/briar/plugins/modem/Frame.java +++ b/briar-core/src/net/sf/briar/plugins/modem/Frame.java @@ -8,7 +8,7 @@ abstract class Frame { protected final byte[] buf; - Frame(byte[] buf) { + protected Frame(byte[] buf) { this.buf = buf; } @@ -49,8 +49,8 @@ abstract class Frame { public boolean equals(Object o) { if(o instanceof Frame) { Frame f = (Frame) o; - if(buf[0] != f.buf[0]) return false; - return getSequenceNumber() == f.getSequenceNumber(); + return buf[0] == f.buf[0] && + getSequenceNumber() == f.getSequenceNumber(); } return false; } diff --git a/briar-core/src/net/sf/briar/plugins/modem/Modem.java b/briar-core/src/net/sf/briar/plugins/modem/Modem.java index ffb372f983..004f7f18be 100644 --- a/briar-core/src/net/sf/briar/plugins/modem/Modem.java +++ b/briar-core/src/net/sf/briar/plugins/modem/Modem.java @@ -28,10 +28,10 @@ interface Modem { boolean dial(String number) throws IOException; /** 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. */ - OutputStream getOutputStream(); + OutputStream getOutputStream() throws IOException; /** Hangs up the modem, ending the currently connected call. */ void hangUp() throws IOException; diff --git a/briar-core/src/net/sf/briar/plugins/modem/ModemImpl.java b/briar-core/src/net/sf/briar/plugins/modem/ModemImpl.java index 0fc79fdd2a..ea26b698a3 100644 --- a/briar-core/src/net/sf/briar/plugins/modem/ModemImpl.java +++ b/briar-core/src/net/sf/briar/plugins/modem/ModemImpl.java @@ -9,7 +9,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.concurrent.Executor; -import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; @@ -32,20 +31,20 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { private final Executor executor; private final Callback callback; private final SerialPort port; - private final AtomicBoolean initialised, connected; - private final Semaphore offHook; + private final AtomicBoolean initialised; // Locking: self + private final AtomicBoolean connected; // Locking: self private final byte[] line; 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) { this.executor = executor; this.callback = callback; port = new SerialPort(portName); initialised = new AtomicBoolean(false); - offHook = new Semaphore(1); connected = new AtomicBoolean(false); line = new byte[MAX_LINE_LENGTH]; } @@ -79,19 +78,19 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { try { synchronized(initialised) { if(!initialised.get()) initialised.wait(OK_TIMEOUT); + if(initialised.get()) return; } } catch(InterruptedException e) { tryToClose(port); Thread.currentThread().interrupt(); throw new IOException("Interrupted while initialising modem"); } - if(!initialised.get()) - throw new IOException("Modem did not respond"); + tryToClose(port); + throw new IOException("Modem did not respond"); } public void stop() throws IOException { - if(offHook.tryAcquire()) offHook.release(); - else hangUp(); + hangUp(); try { port.closePort(); } catch(SerialPortException e) { @@ -100,13 +99,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { } public boolean dial(String number) throws IOException { - if(!offHook.tryAcquire()) { - if(LOG.isLoggable(INFO)) - LOG.info("Not dialling - call in progress"); - return false; + synchronized(this) { + if(offHook) { + if(LOG.isLoggable(INFO)) + 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"); try { port.writeBytes(("ATDT" + number + "\r\n").getBytes("US-ASCII")); @@ -117,36 +119,46 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { try { synchronized(connected) { if(!connected.get()) connected.wait(CONNECT_TIMEOUT); + if(connected.get()) return true; } } catch(InterruptedException e) { tryToClose(port); Thread.currentThread().interrupt(); throw new IOException("Interrupted while connecting outgoing call"); } - if(connected.get()) return true; hangUp(); return false; } - public InputStream getInputStream() { - return reliabilityLayer.getInputStream(); + public synchronized InputStream getInputStream() throws IOException { + if(offHook) return reliabilityLayer.getInputStream(); + throw new IOException("Not connected"); } - public OutputStream getOutputStream() { - return reliabilityLayer.getOutputStream(); + public synchronized OutputStream getOutputStream() throws IOException { + if(offHook) return reliabilityLayer.getOutputStream(); + throw new IOException("Not connected"); } 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"); + connected.set(false); try { port.setDTR(false); } catch(SerialPortException e) { tryToClose(port); throw new IOException(e.toString()); } - reliabilityLayer.stop(); - connected.set(false); - offHook.release(); } 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(s.startsWith("CONNECT")) { synchronized(connected) { - if(!connected.getAndSet(true)) - connected.notifyAll(); + connected.set(true); + connected.notifyAll(); } // There might be data in the buffer as well as text int off = i + 1; @@ -211,8 +223,8 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { } } else if(s.equals("OK")) { synchronized(initialised) { - if(!initialised.getAndSet(true)) - initialised.notifyAll(); + initialised.set(true); + initialised.notifyAll(); } } else if(s.equals("RING")) { executor.execute(new Runnable() { @@ -233,13 +245,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { } private void answer() throws IOException { - if(!offHook.tryAcquire()) { - if(LOG.isLoggable(INFO)) - LOG.info("Not answering - call in progress"); - return; + synchronized(this) { + if(offHook) { + if(LOG.isLoggable(INFO)) + 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"); try { port.writeBytes("ATA\r\n".getBytes("US-ASCII")); @@ -247,16 +262,18 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener { tryToClose(port); throw new IOException(e.toString()); } + boolean success = false; try { synchronized(connected) { if(!connected.get()) connected.wait(CONNECT_TIMEOUT); + success = connected.get(); } } catch(InterruptedException e) { tryToClose(port); Thread.currentThread().interrupt(); throw new IOException("Interrupted while connecting incoming call"); } - if(connected.get()) callback.incomingCallConnected(); + if(success) callback.incomingCallConnected(); else hangUp(); } diff --git a/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java b/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java index eaa8536bdd..e77444d027 100644 --- a/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java +++ b/briar-core/src/net/sf/briar/plugins/modem/ModemPlugin.java @@ -208,11 +208,11 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { private final CountDownLatch finished = new CountDownLatch(1); - public InputStream getInputStream() { + public InputStream getInputStream() throws IOException { return modem.getInputStream(); } - public OutputStream getOutputStream() { + public OutputStream getOutputStream() throws IOException { return modem.getOutputStream(); } -- GitLab