Skip to content

Commit

Permalink
Propagate errors from RtpSocket to CallManagers:
Browse files Browse the repository at this point in the history
- Ensure audio system shutdown
- Propagate IOException from RtpSocket send() failure
- Wrap when re-throwing IOExceptions
- If IOException bubbles to CallManager, treat as disconnect
  rather than failure
- ZRTPSocket ignores IOExceptions from RtpSocket, since it
  has its own retry logic.
- When we can't construct the RtpSocket, fail with
  a disconnected call, rather than a clientFailure().
  • Loading branch information
emblem committed Nov 13, 2012
1 parent 0796b9d commit 5a860c6
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 39 deletions.
13 changes: 11 additions & 2 deletions src/org/thoughtcrime/redphone/audio/CallAudioManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.thoughtcrime.redphone.profiling.TimeProfiler;
import org.thoughtcrime.redphone.ui.ApplicationPreferencesActivity;

import java.io.IOException;
import java.util.LinkedList;
import java.util.NoSuchElementException;

Expand Down Expand Up @@ -77,7 +78,16 @@ public CallAudioManager( SecureRtpSocket socket, String codecID, Context context
simDrops = ApplicationPreferencesActivity.isSimulateDroppedPackets(context);
}

public void run() throws AudioException {
public void run() throws AudioException, IOException {
try {
doRun();
} finally {
doTerminate();
}
}

//TODO(Stuart Anderson): Split this up
private void doRun() throws AudioException, IOException {
synchronized(this) {
if( callDone ) return;
runStarted = true;
Expand Down Expand Up @@ -180,7 +190,6 @@ public void run() throws AudioException {
}

}
doTerminate();
}

private void doTerminate() {
Expand Down
6 changes: 5 additions & 1 deletion src/org/thoughtcrime/redphone/call/CallManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.thoughtcrime.redphone.signaling.SignalingSocket;
import org.thoughtcrime.redphone.ui.ApplicationPreferencesActivity;

import java.io.IOException;
import java.util.Date;

/**
Expand Down Expand Up @@ -116,6 +117,9 @@ public void run() {
} catch (AudioException e) {
Log.w("CallManager", e);
callStateListener.notifyClientError(e.getClientMessage());
} catch (IOException e) {
Log.w("CallManager", e);
callStateListener.notifyCallDisconnected();
}
}

Expand Down Expand Up @@ -178,7 +182,7 @@ private void printInitDebug() {
}

//For loopback operation
public void doLoopback() throws AudioException {
public void doLoopback() throws AudioException, IOException {
callAudioManager = new CallAudioManager( null, "SPEEX", context );
callAudioManager.run();
}
Expand Down
7 changes: 5 additions & 2 deletions src/org/thoughtcrime/redphone/call/InitiatingCallManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import android.content.Context;
import android.util.Log;

import org.thoughtcrime.redphone.Release;
import org.thoughtcrime.redphone.crypto.SecureRtpSocket;
import org.thoughtcrime.redphone.crypto.zrtp.MasterSecret;
Expand All @@ -36,6 +35,7 @@
import org.thoughtcrime.redphone.ui.ApplicationPreferencesActivity;

import java.net.InetSocketAddress;
import java.net.SocketException;

/**
* Call Manager for the coordination of outgoing calls. It initiates
Expand Down Expand Up @@ -85,7 +85,7 @@ public void run() {
InetSocketAddress remoteAddress = new InetSocketAddress(sessionDescriptor.getFullServerName(),
sessionDescriptor.relayPort);

secureSocket = new SecureRtpSocket(new RtpSocket(callStateListener, localPort, remoteAddress));
secureSocket = new SecureRtpSocket(new RtpSocket(localPort, remoteAddress));

zrtpSocket = new ZRTPInitiatorSocket(secureSocket, zid);

Expand All @@ -106,6 +106,9 @@ public void run() {
} catch (SignalingException se) {
Log.w("InitiatingCallManager", se);
callStateListener.notifyServerFailure();
} catch (SocketException e) {
Log.w("InitiatingCallManager", e);
callStateListener.notifyCallDisconnected();
} catch( RuntimeException e ) {
Log.e( "InitiatingCallManager", "Died with unhandled exception!");
Log.w( "InitiatingCallManager", e );
Expand Down
6 changes: 5 additions & 1 deletion src/org/thoughtcrime/redphone/call/ResponderCallManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.thoughtcrime.redphone.signaling.SignalingSocket;

import java.net.InetSocketAddress;
import java.net.SocketException;

/**
* CallManager responsible for coordinating incoming calls.
Expand Down Expand Up @@ -87,7 +88,7 @@ public void run() {
InetSocketAddress remoteAddress = new InetSocketAddress(sessionDescriptor.getFullServerName(),
sessionDescriptor.relayPort);

secureSocket = new SecureRtpSocket(new RtpSocket(callStateListener, localPort, remoteAddress));
secureSocket = new SecureRtpSocket(new RtpSocket(localPort, remoteAddress));
zrtpSocket = new ZRTPResponderSocket(secureSocket, zid);

callStateListener.notifyConnectingtoInitiator();
Expand All @@ -105,6 +106,9 @@ public void run() {
} catch (LoginFailedException lfe) {
Log.w("ResponderCallManager", lfe);
callStateListener.notifyLoginFailed();
} catch (SocketException e) {
Log.w("ResponderCallManager", e);
callStateListener.notifyCallDisconnected();
} catch( RuntimeException e ) {
Log.e( "ResponderCallManager", "Died unhandled with exception!");
Log.w( "ResponderCallManager", e );
Expand Down
6 changes: 3 additions & 3 deletions src/org/thoughtcrime/redphone/crypto/SecureRtpSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ private void initializeStreamContexts() {
this.outgoingContext = new SecureStream(outgoingCipherKey, outgoingMacKey, outgoingSalt);
}

public void send(HandshakePacket packet) {
public void send(HandshakePacket packet) throws IOException {
packet.setCRC();
socket.send(packet);
}
Expand All @@ -93,7 +93,7 @@ public void setTimeout(int timeoutMillis) {
socket.setTimeout(timeoutMillis);
}

public void send(SecureRtpPacket packet) {
public void send(SecureRtpPacket packet) throws IOException {
TimeProfiler.startBlock("SRPS:send:updateSeq" );
outgoingContext.updateSequence(packet);
TimeProfiler.stopBlock("SRPS:send:updateSeq" );
Expand All @@ -108,7 +108,7 @@ public void send(SecureRtpPacket packet) {
TimeProfiler.stopBlock("SRPS:send:send" );
}

public SecureRtpPacket receive() {
public SecureRtpPacket receive() throws IOException {
TimeProfiler.startBlock( "SecureRedphoneSocket::receive" );
RtpPacket barePacket;
barePacket = socket.receive();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.thoughtcrime.redphone.Release;
import org.thoughtcrime.redphone.crypto.SecureRtpSocket;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

Expand Down
6 changes: 5 additions & 1 deletion src/org/thoughtcrime/redphone/crypto/zrtp/ZRTPSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,11 @@ private void sendPacket(HandshakePacket packet) {

if (packet != null) {
packet.setSequenceNumber(this.sequence++);
socket.send(packet);
try {
socket.send(packet);
} catch (IOException e) {
Log.w("ZRTPSocket", e);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/org/thoughtcrime/redphone/network/RtpAudioReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.thoughtcrime.redphone.profiling.PeriodicTimer;
import org.thoughtcrime.redphone.profiling.TimeProfiler;

import java.io.IOException;
import java.util.List;
/**
* RtpAudioReader listens to a {@link SecureRtpSocket} and writes the incoming {@link EncodedAudioData} to
Expand All @@ -51,7 +52,7 @@ public RtpAudioReader(List<EncodedAudioData> incomingAudio,

private int consecutiveReads = 0;
private int totalReads = 0;
public void go() {
public void go() throws IOException {
//if( !recvTimer.periodically()) return;

SecureRtpPacket inPacket = socket.receive();
Expand Down
3 changes: 2 additions & 1 deletion src/org/thoughtcrime/redphone/network/RtpAudioSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.thoughtcrime.redphone.profiling.PacketLogger;
import org.thoughtcrime.redphone.profiling.StatisticsWatcher;

import java.io.IOException;
import java.util.LinkedList;

/**
Expand Down Expand Up @@ -61,7 +62,7 @@ public RtpAudioSender(LinkedList<EncodedAudioData> outgoingAudio,



public void go() {
public void go() throws IOException {

if( audioQueue.size() < audioChunksPerPacket ) {
consecutiveSends = 0;
Expand Down
42 changes: 15 additions & 27 deletions src/org/thoughtcrime/redphone/network/RtpSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,14 @@
* @author Stuart O. Anderson
*/
public class RtpSocket {

private final CallStateListener callStateListener;

private final byte [] buf = new byte[4096];
protected DatagramSocket socket;

public RtpSocket(CallStateListener callStateListener, int localPort, InetSocketAddress remoteAddress) {
this.callStateListener = callStateListener;
private DatagramSocket socket;

try {
socket = new DatagramSocket(localPort);
socket.setSoTimeout(1);
socket.connect(new InetSocketAddress(remoteAddress.getAddress().getHostAddress(), remoteAddress.getPort()));
Log.d( "RtpSocket", "Connected to: " + remoteAddress.getAddress().getHostAddress() );
} catch (SocketException e) {
e.printStackTrace();
// XXX-S It seems like this should do something?
}
public RtpSocket(int localPort, InetSocketAddress remoteAddress) throws SocketException {
socket = new DatagramSocket(localPort);
socket.setSoTimeout(1);
socket.connect(new InetSocketAddress(remoteAddress.getAddress().getHostAddress(), remoteAddress.getPort()));
Log.d( "RtpSocket", "Connected to: " + remoteAddress.getAddress().getHostAddress() );
}

public void setTimeout(int timeoutMillis) {
Expand All @@ -67,12 +57,14 @@ public void setTimeout(int timeoutMillis) {
private long totalSendTime = 0;
private PeriodicTimer pt = new PeriodicTimer(10000);

public void send(RtpPacket outPacket) {
public void send(RtpPacket outPacket) throws IOException {
long start = SystemClock.uptimeMillis();
try {
socket.send(new DatagramPacket(outPacket.getPacket(), outPacket.getPacketLength()));
} catch (IOException e) {
Log.w("RtpSocket", e);
if (!socket.isClosed()) {
throw new IOException(e);
}
}
long stop = SystemClock.uptimeMillis();
totalSendTime += stop - start;
Expand All @@ -82,23 +74,19 @@ public void send(RtpPacket outPacket) {
}
}

public RtpPacket receive() {
public RtpPacket receive() throws IOException {
try {
DatagramPacket dataPack = new DatagramPacket(buf, buf.length);
socket.setSoTimeout(1);
socket.receive(dataPack);
RtpPacket inPacket = new RtpPacket(dataPack.getData(), dataPack.getLength());
return inPacket;
} catch( SocketTimeoutException e ) {
return null;
} catch (SocketException e) {
// XXX-S I don't think this should be reaching back up the stack from this level.
// Instead, it seems like this should be throwing IOException/SocketException up
// the stack to CallAudioManager or wherever, which should handle reaching back up
// from that point in the stack.
callStateListener.notifyCallDisconnected();
//Do Nothing.
} catch (IOException e) {
callStateListener.notifyCallDisconnected();
if (!socket.isClosed()) {
throw new IOException(e);
}
}
return null;
}
Expand Down

0 comments on commit 5a860c6

Please sign in to comment.