more error handling for jingle connections

This commit is contained in:
iNPUTmice 2014-06-29 13:44:59 +02:00
parent 8eedc1a57f
commit d58d428874
10 changed files with 90 additions and 57 deletions

View file

@ -248,4 +248,5 @@
<string name="edit_conference_details">Touch to edit conference details</string> <string name="edit_conference_details">Touch to edit conference details</string>
<string name="openpgp_messages_found">OpenPGP encrypted messages found</string> <string name="openpgp_messages_found">OpenPGP encrypted messages found</string>
<string name="openpgp_click_to_decrypt">Click here to enter passphrase and decrypt messages</string> <string name="openpgp_click_to_decrypt">Click here to enter passphrase and decrypt messages</string>
<string name="reception_failed">Reception failed</string>
</resources> </resources>

View file

@ -12,6 +12,7 @@ public class Message extends AbstractEntity {
public static final String TABLENAME = "messages"; public static final String TABLENAME = "messages";
public static final int STATUS_RECEPTION_FAILED = -3;
public static final int STATUS_RECEIVED_OFFER = -2; public static final int STATUS_RECEIVED_OFFER = -2;
public static final int STATUS_RECIEVING = -1; public static final int STATUS_RECIEVING = -1;
public static final int STATUS_RECIEVED = 0; public static final int STATUS_RECIEVED = 0;

View file

@ -232,6 +232,7 @@ public class XmppConnectionService extends Service {
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
mJingleConnectionManager.cancelInTransmission();
List<Conversation> conversations = getConversations(); List<Conversation> conversations = getConversations();
for (int i = 0; i < conversations.size(); ++i) { for (int i = 0; i < conversations.size(); ++i) {
if (conversations.get(i).getAccount() == account) { if (conversations.get(i).getAccount() == account) {

View file

@ -252,6 +252,9 @@ public class ConversationFragment extends Fragment {
info = getString(R.string.send_rejected); info = getString(R.string.send_rejected);
error = true; error = true;
break; break;
case Message.STATUS_RECEPTION_FAILED:
info = getString(R.string.reception_failed);
error = true;
default: default:
if (multiReceived) { if (multiReceived) {
info = message.getCounterpart(); info = message.getCounterpart();

View file

@ -75,7 +75,7 @@ public class JingleConnection {
} }
}; };
final OnFileTransmitted onFileTransmitted = new OnFileTransmitted() { final OnFileTransmissionStatusChanged onFileTransmissionSatusChanged = new OnFileTransmissionStatusChanged() {
@Override @Override
public void onFileTransmitted(JingleFile file) { public void onFileTransmitted(JingleFile file) {
@ -96,6 +96,11 @@ public class JingleConnection {
} }
Log.d("xmppService","sucessfully transmitted file:"+file.getAbsolutePath()); Log.d("xmppService","sucessfully transmitted file:"+file.getAbsolutePath());
} }
@Override
public void onFileTransferAborted() {
JingleConnection.this.cancel();
}
}; };
private OnProxyActivated onProxyActivated = new OnProxyActivated() { private OnProxyActivated onProxyActivated = new OnProxyActivated() {
@ -104,9 +109,9 @@ public class JingleConnection {
public void success() { public void success() {
if (initiator.equals(account.getFullJid())) { if (initiator.equals(account.getFullJid())) {
Log.d("xmppService","we were initiating. sending file"); Log.d("xmppService","we were initiating. sending file");
transport.send(file,onFileTransmitted); transport.send(file,onFileTransmissionSatusChanged);
} else { } else {
transport.receive(file,onFileTransmitted); transport.receive(file,onFileTransmissionSatusChanged);
Log.d("xmppService","we were responding. receiving file"); Log.d("xmppService","we were responding. receiving file");
} }
} }
@ -140,14 +145,14 @@ public class JingleConnection {
Reason reason = packet.getReason(); Reason reason = packet.getReason();
if (reason!=null) { if (reason!=null) {
if (reason.hasChild("cancel")) { if (reason.hasChild("cancel")) {
this.receiveCancel(); this.cancel();
} else if (reason.hasChild("success")) { } else if (reason.hasChild("success")) {
this.receiveSuccess(); this.receiveSuccess();
} else { } else {
this.receiveCancel(); this.cancel();
} }
} else { } else {
this.receiveCancel(); this.cancel();
} }
} else if (packet.isAction("session-accept")) { } else if (packet.isAction("session-accept")) {
returnResult = receiveAccept(packet); returnResult = receiveAccept(packet);
@ -279,13 +284,13 @@ public class JingleConnection {
} }
this.file.setExpectedSize(size); this.file.setExpectedSize(size);
} else { } else {
this.sendCancel(); this.cancel();
} }
} else { } else {
this.sendCancel(); this.cancel();
} }
} else { } else {
this.sendCancel(); this.cancel();
} }
} }
@ -405,7 +410,7 @@ public class JingleConnection {
connection.setActivated(true); connection.setActivated(true);
} else { } else {
Log.d("xmppService","activated connection not found"); Log.d("xmppService","activated connection not found");
this.sendCancel(); this.cancel();
} }
} }
return true; return true;
@ -479,10 +484,10 @@ public class JingleConnection {
} else { } else {
if (initiator.equals(account.getFullJid())) { if (initiator.equals(account.getFullJid())) {
Log.d("xmppService","we were initiating. sending file"); Log.d("xmppService","we were initiating. sending file");
connection.send(file,onFileTransmitted); connection.send(file,onFileTransmissionSatusChanged);
} else { } else {
Log.d("xmppService","we were responding. receiving file"); Log.d("xmppService","we were responding. receiving file");
connection.receive(file,onFileTransmitted); connection.receive(file,onFileTransmissionSatusChanged);
} }
} }
} }
@ -553,7 +558,7 @@ public class JingleConnection {
} }
this.transportId = packet.getJingleContent().getTransportId(); this.transportId = packet.getJingleContent().getTransportId();
this.transport = new JingleInbandTransport(this.account,this.responder,this.transportId,this.ibbBlockSize); this.transport = new JingleInbandTransport(this.account,this.responder,this.transportId,this.ibbBlockSize);
this.transport.receive(file, onFileTransmitted); this.transport.receive(file, onFileTransmissionSatusChanged);
JinglePacket answer = bootstrapPacket("transport-accept"); JinglePacket answer = bootstrapPacket("transport-accept");
Content content = new Content("initiator", "a-file-offer"); Content content = new Content("initiator", "a-file-offer");
content.setTransportId(this.transportId); content.setTransportId(this.transportId);
@ -582,7 +587,7 @@ public class JingleConnection {
@Override @Override
public void established() { public void established() {
JingleConnection.this.transport.send(file, onFileTransmitted); JingleConnection.this.transport.send(file, onFileTransmissionSatusChanged);
} }
}); });
return true; return true;
@ -598,10 +603,21 @@ public class JingleConnection {
this.mJingleConnectionManager.finishConnection(this); this.mJingleConnectionManager.finishConnection(this);
} }
private void receiveCancel() { void cancel() {
this.sendCancel();
this.disconnect(); this.disconnect();
this.status = STATUS_CANCELED; if (this.message!=null) {
if (this.responder.equals(account.getFullJid())) {
this.mXmppConnectionService.markMessage(this.message, Message.STATUS_RECEPTION_FAILED);
} else {
if (this.status == STATUS_INITIATED) {
this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED); this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED);
} else {
this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_FAILED);
}
}
}
this.status = STATUS_CANCELED;
this.mJingleConnectionManager.finishConnection(this); this.mJingleConnectionManager.finishConnection(this);
} }

View file

@ -155,4 +155,12 @@ public class JingleConnectionManager {
Log.d("xmppService","no sid found in incomming ibb packet"); Log.d("xmppService","no sid found in incomming ibb packet");
} }
} }
public void cancelInTransmission() {
for(JingleConnection connection : this.connections) {
if (connection.getStatus() == JingleConnection.STATUS_TRANSMITTING) {
connection.cancel();
}
}
}
} }

View file

@ -33,7 +33,7 @@ public class JingleInbandTransport extends JingleTransport {
private long remainingSize; private long remainingSize;
private MessageDigest digest; private MessageDigest digest;
private OnFileTransmitted onFileTransmitted; private OnFileTransmissionStatusChanged onFileTransmissionStatusChanged;
private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() { private OnIqPacketReceived onAckReceived = new OnIqPacketReceived() {
@Override @Override
@ -77,8 +77,8 @@ public class JingleInbandTransport extends JingleTransport {
} }
@Override @Override
public void receive(JingleFile file, OnFileTransmitted callback) { public void receive(JingleFile file, OnFileTransmissionStatusChanged callback) {
this.onFileTransmitted = callback; this.onFileTransmissionStatusChanged = callback;
this.file = file; this.file = file;
try { try {
this.digest = MessageDigest.getInstance("SHA-1"); this.digest = MessageDigest.getInstance("SHA-1");
@ -86,27 +86,35 @@ public class JingleInbandTransport extends JingleTransport {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
file.createNewFile(); file.createNewFile();
this.fileOutputStream = getOutputStream(file); this.fileOutputStream = getOutputStream(file);
if (this.fileOutputStream==null) {
callback.onFileTransferAborted();
return;
}
this.remainingSize = file.getExpectedSize(); this.remainingSize = file.getExpectedSize();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); callback.onFileTransferAborted();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); callback.onFileTransferAborted();
} }
} }
@Override @Override
public void send(JingleFile file, OnFileTransmitted callback) { public void send(JingleFile file, OnFileTransmissionStatusChanged callback) {
this.onFileTransmitted = callback; this.onFileTransmissionStatusChanged = callback;
this.file = file; this.file = file;
try { try {
this.digest = MessageDigest.getInstance("SHA-1"); this.digest = MessageDigest.getInstance("SHA-1");
this.digest.reset(); this.digest.reset();
fileInputStream = this.getInputStream(file); fileInputStream = this.getInputStream(file);
if (fileInputStream==null) {
callback.onFileTransferAborted();
return;
}
this.sendNextBlock(); this.sendNextBlock();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
e.printStackTrace(); callback.onFileTransferAborted();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
e.printStackTrace(); callback.onFileTransferAborted();
} }
} }
@ -117,7 +125,7 @@ public class JingleInbandTransport extends JingleTransport {
if (count == -1) { if (count == -1) {
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
fileInputStream.close(); fileInputStream.close();
this.onFileTransmitted.onFileTransmitted(file); this.onFileTransmissionStatusChanged.onFileTransmitted(file);
} else { } else {
this.digest.update(buffer); this.digest.update(buffer);
String base64 = Base64.encodeToString(buffer, Base64.NO_WRAP); String base64 = Base64.encodeToString(buffer, Base64.NO_WRAP);
@ -134,8 +142,7 @@ public class JingleInbandTransport extends JingleTransport {
this.seq++; this.seq++;
} }
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block this.onFileTransmissionStatusChanged.onFileTransferAborted();
e.printStackTrace();
} }
} }
@ -154,10 +161,10 @@ public class JingleInbandTransport extends JingleTransport {
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
fileOutputStream.flush(); fileOutputStream.flush();
fileOutputStream.close(); fileOutputStream.close();
this.onFileTransmitted.onFileTransmitted(file); this.onFileTransmissionStatusChanged.onFileTransmitted(file);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); this.onFileTransmissionStatusChanged.onFileTransferAborted();
} }
} }

View file

@ -10,7 +10,6 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import android.util.Log;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
public class JingleSocks5Transport extends JingleTransport { public class JingleSocks5Transport extends JingleTransport {
@ -84,7 +83,7 @@ public class JingleSocks5Transport extends JingleTransport {
} }
public void send(final JingleFile file, final OnFileTransmitted callback) { public void send(final JingleFile file, final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
@ -94,37 +93,34 @@ public class JingleSocks5Transport extends JingleTransport {
MessageDigest digest = MessageDigest.getInstance("SHA-1"); MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset(); digest.reset();
fileInputStream = getInputStream(file); fileInputStream = getInputStream(file);
if (fileInputStream==null) {
callback.onFileTransferAborted();
return;
}
int count; int count;
long txBytes = 0;
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
while ((count = fileInputStream.read(buffer)) > 0) { while ((count = fileInputStream.read(buffer)) > 0) {
txBytes += count;
outputStream.write(buffer, 0, count); outputStream.write(buffer, 0, count);
digest.update(buffer, 0, count); digest.update(buffer, 0, count);
} }
Log.d("xmppService","txBytes="+txBytes);
outputStream.flush(); outputStream.flush();
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
if (callback!=null) { if (callback!=null) {
callback.onFileTransmitted(file); callback.onFileTransmitted(file);
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} finally { } finally {
try { try {
if (fileInputStream != null) { if (fileInputStream != null) {
fileInputStream.close(); fileInputStream.close();
} }
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} }
} }
} }
@ -132,7 +128,7 @@ public class JingleSocks5Transport extends JingleTransport {
} }
public void receive(final JingleFile file, final OnFileTransmitted callback) { public void receive(final JingleFile file, final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() { new Thread(new Runnable() {
@Override @Override
@ -144,35 +140,34 @@ public class JingleSocks5Transport extends JingleTransport {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
file.createNewFile(); file.createNewFile();
OutputStream fileOutputStream = getOutputStream(file); OutputStream fileOutputStream = getOutputStream(file);
if (fileOutputStream==null) {
callback.onFileTransferAborted();
return;
}
long remainingSize = file.getExpectedSize(); long remainingSize = file.getExpectedSize();
byte[] buffer = new byte[8192]; byte[] buffer = new byte[8192];
int count = buffer.length; int count = buffer.length;
long rxBytes = 0;
while(remainingSize > 0) { while(remainingSize > 0) {
count = inputStream.read(buffer); count = inputStream.read(buffer);
if (count==-1) { if (count==-1) {
Log.d("xmppService","read end"); callback.onFileTransferAborted();
return;
} else { } else {
rxBytes += count;
fileOutputStream.write(buffer, 0, count); fileOutputStream.write(buffer, 0, count);
digest.update(buffer, 0, count); digest.update(buffer, 0, count);
remainingSize-=count; remainingSize-=count;
} }
} }
Log.d("xmppService","rx bytes="+rxBytes);
fileOutputStream.flush(); fileOutputStream.flush();
fileOutputStream.close(); fileOutputStream.close();
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
callback.onFileTransmitted(file); callback.onFileTransmitted(file);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block callback.onFileTransferAborted();
e.printStackTrace();
} }
} }
}).start(); }).start();

View file

@ -19,8 +19,8 @@ import android.util.Log;
public abstract class JingleTransport { public abstract class JingleTransport {
public abstract void connect(final OnTransportConnected callback); public abstract void connect(final OnTransportConnected callback);
public abstract void receive(final JingleFile file, final OnFileTransmitted callback); public abstract void receive(final JingleFile file, final OnFileTransmissionStatusChanged callback);
public abstract void send(final JingleFile file, final OnFileTransmitted callback); public abstract void send(final JingleFile file, final OnFileTransmissionStatusChanged callback);
private byte[] iv = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0xf}; private byte[] iv = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0xf};
protected InputStream getInputStream(JingleFile file) throws FileNotFoundException { protected InputStream getInputStream(JingleFile file) throws FileNotFoundException {

View file

@ -1,5 +1,6 @@
package eu.siacs.conversations.xmpp.jingle; package eu.siacs.conversations.xmpp.jingle;
public interface OnFileTransmitted { public interface OnFileTransmissionStatusChanged {
public void onFileTransmitted(JingleFile file); public void onFileTransmitted(JingleFile file);
public void onFileTransferAborted();
} }