mirror of
https://github.com/moparisthebest/Conversations
synced 2024-11-17 22:35:08 -05:00
Merge branch 'streammanagment'
This commit is contained in:
commit
49efe81644
@ -20,7 +20,7 @@ import android.util.Log;
|
|||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.persistance.DatabaseBackend;
|
import eu.siacs.conversations.persistance.DatabaseBackend;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
|
|
||||||
import net.java.otr4j.OtrEngineHost;
|
import net.java.otr4j.OtrEngineHost;
|
||||||
import net.java.otr4j.OtrException;
|
import net.java.otr4j.OtrException;
|
||||||
|
@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import eu.siacs.conversations.entities.MucOptions.User;
|
import eu.siacs.conversations.entities.MucOptions.User;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.PresencePacket;
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -144,7 +144,11 @@ public class MucOptions {
|
|||||||
if (split.length == 2) {
|
if (split.length == 2) {
|
||||||
return split[1];
|
return split[1];
|
||||||
} else {
|
} else {
|
||||||
|
if (conversation.getAccount()!=null) {
|
||||||
return conversation.getAccount().getUsername();
|
return conversation.getAccount().getUsername();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,10 @@ public class EventReceiver extends BroadcastReceiver {
|
|||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
Intent mIntentForService = new Intent(context,
|
Intent mIntentForService = new Intent(context,
|
||||||
XmppConnectionService.class);
|
XmppConnectionService.class);
|
||||||
mIntentForService.putExtra("ping", intent.getBooleanExtra("ping",false));
|
if (intent.getAction() != null) {
|
||||||
if ((intent.getAction() != null)
|
mIntentForService.setAction(intent.getAction());
|
||||||
&& (intent.getAction()
|
} else {
|
||||||
.equals("android.intent.action.BOOT_COMPLETED"))) {
|
mIntentForService.setAction("other");
|
||||||
|
|
||||||
}
|
}
|
||||||
context.startService(mIntentForService);
|
context.startService(mIntentForService);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import java.util.Hashtable;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.openintents.openpgp.util.OpenPgpApi;
|
import org.openintents.openpgp.util.OpenPgpApi;
|
||||||
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||||
|
|
||||||
@ -35,15 +34,15 @@ import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
|
|||||||
import eu.siacs.conversations.utils.PhoneHelper;
|
import eu.siacs.conversations.utils.PhoneHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.IqPacket;
|
|
||||||
import eu.siacs.conversations.xmpp.MessagePacket;
|
|
||||||
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
|
||||||
import eu.siacs.conversations.xmpp.OnStatusChanged;
|
import eu.siacs.conversations.xmpp.OnStatusChanged;
|
||||||
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
|
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
|
||||||
import eu.siacs.conversations.xmpp.PresencePacket;
|
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
@ -70,7 +69,8 @@ public class XmppConnectionService extends Service {
|
|||||||
|
|
||||||
public long startDate;
|
public long startDate;
|
||||||
|
|
||||||
private static final int PING_INTERVAL = 300;
|
private static final int PING_MAX_INTERVAL = 300;
|
||||||
|
private static final int PING_MIN_INTERVAL = 10;
|
||||||
private static final int PING_TIMEOUT = 2;
|
private static final int PING_TIMEOUT = 2;
|
||||||
|
|
||||||
private List<Account> accounts;
|
private List<Account> accounts;
|
||||||
@ -80,7 +80,8 @@ public class XmppConnectionService extends Service {
|
|||||||
private OnAccountListChangedListener accountChangedListener = null;
|
private OnAccountListChangedListener accountChangedListener = null;
|
||||||
private OnTLSExceptionReceived tlsException = null;
|
private OnTLSExceptionReceived tlsException = null;
|
||||||
|
|
||||||
public void setOnTLSExceptionReceivedListener(OnTLSExceptionReceived listener) {
|
public void setOnTLSExceptionReceivedListener(
|
||||||
|
OnTLSExceptionReceived listener) {
|
||||||
tlsException = listener;
|
tlsException = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +127,9 @@ public class XmppConnectionService extends Service {
|
|||||||
|| (packet.hasChild("sent"))) {
|
|| (packet.hasChild("sent"))) {
|
||||||
message = MessageParser.parseCarbonMessage(packet, account,
|
message = MessageParser.parseCarbonMessage(packet, account,
|
||||||
service);
|
service);
|
||||||
|
if (message != null) {
|
||||||
message.getConversation().markRead();
|
message.getConversation().markRead();
|
||||||
|
}
|
||||||
notify = false;
|
notify = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +172,8 @@ public class XmppConnectionService extends Service {
|
|||||||
if (convChangedListener != null) {
|
if (convChangedListener != null) {
|
||||||
convChangedListener.onConversationListChanged();
|
convChangedListener.onConversationListChanged();
|
||||||
} else {
|
} else {
|
||||||
UIHelper.updateNotification(getApplicationContext(), getConversations(), notify);
|
UIHelper.updateNotification(getApplicationContext(),
|
||||||
|
getConversations(), notify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -195,16 +199,8 @@ public class XmppConnectionService extends Service {
|
|||||||
if (convChangedListener != null) {
|
if (convChangedListener != null) {
|
||||||
convChangedListener.onConversationListChanged();
|
convChangedListener.onConversationListChanged();
|
||||||
}
|
}
|
||||||
if (account.getKeys().has("pgp_signature")) {
|
scheduleWakeupCall(PING_MAX_INTERVAL, true);
|
||||||
try {
|
|
||||||
sendPgpPresence(account, account.getKeys().getString("pgp_signature"));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scheduleWakeupCall(PING_INTERVAL, true);
|
|
||||||
} else if (account.getStatus() == Account.STATUS_OFFLINE) {
|
} else if (account.getStatus() == Account.STATUS_OFFLINE) {
|
||||||
Log.d(LOGTAG,"onStatusChanged offline");
|
|
||||||
databaseBackend.clearPresences(account);
|
databaseBackend.clearPresences(account);
|
||||||
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
|
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
|
||||||
int timeToReconnect = mRandom.nextInt(50) + 10;
|
int timeToReconnect = mRandom.nextInt(50) + 10;
|
||||||
@ -220,12 +216,16 @@ public class XmppConnectionService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void onPresencePacketReceived(Account account,
|
public void onPresencePacketReceived(Account account,
|
||||||
PresencePacket packet) {
|
PresencePacket packet) {
|
||||||
if (packet.hasChild("x")&&(packet.findChild("x").getAttribute("xmlns").startsWith("http://jabber.org/protocol/muc"))) {
|
if (packet.hasChild("x")
|
||||||
Conversation muc = findMuc(packet.getAttribute("from").split("/")[0]);
|
&& (packet.findChild("x").getAttribute("xmlns")
|
||||||
|
.startsWith("http://jabber.org/protocol/muc"))) {
|
||||||
|
Conversation muc = findMuc(packet.getAttribute("from").split(
|
||||||
|
"/")[0]);
|
||||||
if (muc != null) {
|
if (muc != null) {
|
||||||
int error = muc.getMucOptions().getError();
|
int error = muc.getMucOptions().getError();
|
||||||
muc.getMucOptions().processPacket(packet);
|
muc.getMucOptions().processPacket(packet);
|
||||||
if ((muc.getMucOptions().getError()!=error)&&(convChangedListener!=null)) {
|
if ((muc.getMucOptions().getError() != error)
|
||||||
|
&& (convChangedListener != null)) {
|
||||||
Log.d(LOGTAG, "muc error status changed");
|
Log.d(LOGTAG, "muc error status changed");
|
||||||
convChangedListener.onConversationListChanged();
|
convChangedListener.onConversationListChanged();
|
||||||
}
|
}
|
||||||
@ -255,10 +255,12 @@ public class XmppConnectionService extends Service {
|
|||||||
if (pgp != null) {
|
if (pgp != null) {
|
||||||
Element x = packet.findChild("x");
|
Element x = packet.findChild("x");
|
||||||
if ((x != null)
|
if ((x != null)
|
||||||
&& (x.getAttribute("xmlns").equals("jabber:x:signed"))) {
|
&& (x.getAttribute("xmlns")
|
||||||
|
.equals("jabber:x:signed"))) {
|
||||||
try {
|
try {
|
||||||
contact.setPgpKeyId(pgp.fetchKeyId(packet.findChild("status")
|
contact.setPgpKeyId(pgp.fetchKeyId(packet
|
||||||
.getContent(), x.getContent()));
|
.findChild("status").getContent(), x
|
||||||
|
.getContent()));
|
||||||
} catch (OpenPgpException e) {
|
} catch (OpenPgpException e) {
|
||||||
Log.d(LOGTAG, "faulty pgp. just ignore");
|
Log.d(LOGTAG, "faulty pgp. just ignore");
|
||||||
}
|
}
|
||||||
@ -290,7 +292,7 @@ public class XmppConnectionService extends Service {
|
|||||||
// TODO: ask user to handle it maybe
|
// TODO: ask user to handle it maybe
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG, packet.toString());
|
//Log.d(LOGTAG, packet.toString());
|
||||||
}
|
}
|
||||||
replaceContactInConversation(contact.getJid(), contact);
|
replaceContactInConversation(contact.getJid(), contact);
|
||||||
}
|
}
|
||||||
@ -314,6 +316,8 @@ public class XmppConnectionService extends Service {
|
|||||||
|
|
||||||
private OpenPgpServiceConnection pgpServiceConnection;
|
private OpenPgpServiceConnection pgpServiceConnection;
|
||||||
private PgpEngine mPgpEngine = null;
|
private PgpEngine mPgpEngine = null;
|
||||||
|
private Intent pingIntent;
|
||||||
|
private PendingIntent pendingPingIntent = null;
|
||||||
|
|
||||||
public PgpEngine getPgpEngine() {
|
public PgpEngine getPgpEngine() {
|
||||||
if (pgpServiceConnection.isBound()) {
|
if (pgpServiceConnection.isBound()) {
|
||||||
@ -391,35 +395,65 @@ public class XmppConnectionService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
Log.d(LOGTAG,"calling start service. caller was:"+intent.getAction());
|
||||||
|
|
||||||
|
// internet and online last_received - list_ping >= max_ping : ping
|
||||||
|
// internet and online last_ping - last_received >= ping_timeout :
|
||||||
|
// reconnect
|
||||||
|
// internet and offline and enabled : connect (Threat start)
|
||||||
|
|
||||||
|
// no internet - set no internet
|
||||||
|
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
|
||||||
|
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
|
||||||
boolean isConnected = activeNetwork != null
|
boolean isConnected = activeNetwork != null
|
||||||
&& activeNetwork.isConnected();
|
&& activeNetwork.isConnected();
|
||||||
|
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
|
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
account.setStatus(Account.STATUS_NO_INTERNET);
|
account.setStatus(Account.STATUS_NO_INTERNET);
|
||||||
|
if (statusListener!=null) {
|
||||||
|
statusListener.onStatusChanged(account);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (account.getStatus() == Account.STATUS_NO_INTERNET) {
|
if (account.getStatus() == Account.STATUS_NO_INTERNET) {
|
||||||
account.setStatus(Account.STATUS_OFFLINE);
|
account.setStatus(Account.STATUS_OFFLINE);
|
||||||
|
if (statusListener!=null) {
|
||||||
|
statusListener.onStatusChanged(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 3 remaining cases
|
||||||
|
if (account.getStatus() == Account.STATUS_ONLINE) {
|
||||||
|
long lastReceived = account.getXmppConnection().lastPaketReceived;
|
||||||
|
long lastSent = account.getXmppConnection().lastPingSent;
|
||||||
|
if (lastSent - lastReceived >= PING_TIMEOUT * 1000) {
|
||||||
|
Log.d(LOGTAG, account.getJid() + ": ping timeout");
|
||||||
|
this.reconnectAccount(account);
|
||||||
|
} else if (SystemClock.elapsedRealtime() - lastReceived >= PING_MIN_INTERVAL * 1000) {
|
||||||
|
account.getXmppConnection().sendPing();
|
||||||
|
account.getXmppConnection().lastPingSent = SystemClock.elapsedRealtime();
|
||||||
|
this.scheduleWakeupCall(2, false);
|
||||||
|
}
|
||||||
|
} else if (account.getStatus() == Account.STATUS_OFFLINE) {
|
||||||
|
if (account.getXmppConnection() == null) {
|
||||||
|
account.setXmppConnection(this
|
||||||
|
.createConnection(account));
|
||||||
|
}
|
||||||
|
account.getXmppConnection().lastPingSent = SystemClock.elapsedRealtime();
|
||||||
|
new Thread(account.getXmppConnection()).start();
|
||||||
|
} else {
|
||||||
|
Log.d(LOGTAG,account.getJid()+": status="+account.getStatus());
|
||||||
|
// TODO notify user of ssl cert problem or auth problem or what ever
|
||||||
|
}
|
||||||
|
//in any case. reschedule wakup call
|
||||||
|
this.scheduleWakeupCall(PING_MAX_INTERVAL, true);
|
||||||
|
}
|
||||||
if (accountChangedListener != null) {
|
if (accountChangedListener != null) {
|
||||||
accountChangedListener.onAccountListChangedListener();
|
accountChangedListener.onAccountListChangedListener();
|
||||||
}
|
}
|
||||||
if ((!account.isOptionSet(Account.OPTION_DISABLED))&&(isConnected)) {
|
|
||||||
if (account.getXmppConnection() == null) {
|
|
||||||
account.setXmppConnection(this.createConnection(account));
|
|
||||||
}
|
|
||||||
if (account.getStatus()==Account.STATUS_OFFLINE) {
|
|
||||||
Thread thread = new Thread(account.getXmppConnection());
|
|
||||||
thread.start();
|
|
||||||
} else {
|
|
||||||
if (intent.getBooleanExtra("ping", false)) {
|
|
||||||
Log.d(LOGTAG,"start service ping");
|
|
||||||
ping(account,PING_TIMEOUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
@ -437,7 +471,6 @@ public class XmppConnectionService extends Service {
|
|||||||
getApplicationContext(), "org.sufficientlysecure.keychain");
|
getApplicationContext(), "org.sufficientlysecure.keychain");
|
||||||
this.pgpServiceConnection.bindToService();
|
this.pgpServiceConnection.bindToService();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -445,24 +478,45 @@ public class XmppConnectionService extends Service {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
if (account.getXmppConnection() != null) {
|
if (account.getXmppConnection() != null) {
|
||||||
disconnect(account);
|
disconnect(account, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void scheduleWakeupCall(int seconds, boolean ping) {
|
protected void scheduleWakeupCall(int seconds, boolean ping) {
|
||||||
|
long timeToWake = SystemClock.elapsedRealtime() + seconds * 1000;
|
||||||
Context context = getApplicationContext();
|
Context context = getApplicationContext();
|
||||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager alarmManager = (AlarmManager) context
|
||||||
Intent intent = new Intent(context, EventReceiver.class);
|
.getSystemService(Context.ALARM_SERVICE);
|
||||||
intent.putExtra("ping", ping);
|
|
||||||
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
|
|
||||||
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
|
||||||
SystemClock.elapsedRealtime() +
|
|
||||||
seconds * 1000, alarmIntent);
|
|
||||||
if (ping) {
|
if (ping) {
|
||||||
Log.d(LOGTAG,"schedule ping in "+seconds+" seconds");
|
if (this.pingIntent==null) {
|
||||||
|
this.pingIntent = new Intent(context, EventReceiver.class);
|
||||||
|
this.pingIntent.setAction("ping");
|
||||||
|
this.pingIntent.putExtra("time", timeToWake);
|
||||||
|
this.pendingPingIntent = PendingIntent.getBroadcast(context, 0,
|
||||||
|
this.pingIntent, 0);
|
||||||
|
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,timeToWake, pendingPingIntent);
|
||||||
|
//Log.d(LOGTAG,"schedule ping in "+seconds+" seconds");
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG,"schedule reconnect in "+seconds+" seconds");
|
long scheduledTime = this.pingIntent.getLongExtra("time", 0);
|
||||||
|
if (scheduledTime<SystemClock.elapsedRealtime() || (scheduledTime > timeToWake)) {
|
||||||
|
this.pingIntent.putExtra("time", timeToWake);
|
||||||
|
alarmManager.cancel(this.pendingPingIntent);
|
||||||
|
this.pendingPingIntent = PendingIntent.getBroadcast(context, 0,
|
||||||
|
this.pingIntent, 0);
|
||||||
|
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,timeToWake, pendingPingIntent);
|
||||||
|
//Log.d(LOGTAG,"reschedule old ping to ping in "+seconds+" seconds");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Intent intent = new Intent(context, EventReceiver.class);
|
||||||
|
intent.setAction("ping_check");
|
||||||
|
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0,
|
||||||
|
intent, 0);
|
||||||
|
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,timeToWake, alarmIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -475,13 +529,16 @@ public class XmppConnectionService extends Service {
|
|||||||
connection.setOnPresencePacketReceivedListener(this.presenceListener);
|
connection.setOnPresencePacketReceivedListener(this.presenceListener);
|
||||||
connection
|
connection
|
||||||
.setOnUnregisteredIqPacketReceivedListener(this.unknownIqListener);
|
.setOnUnregisteredIqPacketReceivedListener(this.unknownIqListener);
|
||||||
connection.setOnTLSExceptionReceivedListener(new OnTLSExceptionReceived() {
|
connection
|
||||||
|
.setOnTLSExceptionReceivedListener(new OnTLSExceptionReceived() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTLSExceptionReceived(String fingerprint, Account account) {
|
public void onTLSExceptionReceived(String fingerprint,
|
||||||
|
Account account) {
|
||||||
Log.d(LOGTAG, "tls exception arrived in service");
|
Log.d(LOGTAG, "tls exception arrived in service");
|
||||||
if (tlsException != null) {
|
if (tlsException != null) {
|
||||||
tlsException.onTLSExceptionReceived(fingerprint,account);
|
tlsException.onTLSExceptionReceived(fingerprint,
|
||||||
|
account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -629,7 +686,8 @@ public class XmppConnectionService extends Service {
|
|||||||
Element query = new Element("query");
|
Element query = new Element("query");
|
||||||
query.setAttribute("xmlns", "jabber:iq:roster");
|
query.setAttribute("xmlns", "jabber:iq:roster");
|
||||||
if (!"".equals(account.getRosterVersion())) {
|
if (!"".equals(account.getRosterVersion())) {
|
||||||
Log.d(LOGTAG,account.getJid()+ ": fetching roster version "+account.getRosterVersion());
|
Log.d(LOGTAG, account.getJid() + ": fetching roster version "
|
||||||
|
+ account.getRosterVersion());
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG, account.getJid() + ": fetching roster");
|
Log.d(LOGTAG, account.getJid() + ": fetching roster");
|
||||||
}
|
}
|
||||||
@ -643,7 +701,8 @@ public class XmppConnectionService extends Service {
|
|||||||
IqPacket packet) {
|
IqPacket packet) {
|
||||||
Element roster = packet.findChild("query");
|
Element roster = packet.findChild("query");
|
||||||
if (roster != null) {
|
if (roster != null) {
|
||||||
Log.d(LOGTAG,account.getJid()+": processing roster");
|
Log.d(LOGTAG, account.getJid()
|
||||||
|
+ ": processing roster");
|
||||||
processRosterItems(account, roster);
|
processRosterItems(account, roster);
|
||||||
StringBuilder mWhere = new StringBuilder();
|
StringBuilder mWhere = new StringBuilder();
|
||||||
mWhere.append("jid NOT IN(");
|
mWhere.append("jid NOT IN(");
|
||||||
@ -668,7 +727,8 @@ public class XmppConnectionService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG,account.getJid()+": empty roster returend");
|
Log.d(LOGTAG, account.getJid()
|
||||||
|
+ ": empty roster returend");
|
||||||
}
|
}
|
||||||
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
|
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
|
||||||
|
|
||||||
@ -864,7 +924,7 @@ public class XmppConnectionService extends Service {
|
|||||||
public void deleteAccount(Account account) {
|
public void deleteAccount(Account account) {
|
||||||
Log.d(LOGTAG, "called delete account");
|
Log.d(LOGTAG, "called delete account");
|
||||||
if (account.getXmppConnection() != null) {
|
if (account.getXmppConnection() != null) {
|
||||||
this.disconnect(account);
|
this.disconnect(account, false);
|
||||||
}
|
}
|
||||||
databaseBackend.deleteAccount(account);
|
databaseBackend.deleteAccount(account);
|
||||||
this.accounts.remove(account);
|
this.accounts.remove(account);
|
||||||
@ -913,8 +973,7 @@ public class XmppConnectionService extends Service {
|
|||||||
nick = conversation.getAccount().getUsername();
|
nick = conversation.getAccount().getUsername();
|
||||||
}
|
}
|
||||||
PresencePacket packet = new PresencePacket();
|
PresencePacket packet = new PresencePacket();
|
||||||
packet.setAttribute("to", muc + "/"
|
packet.setAttribute("to", muc + "/" + nick);
|
||||||
+ nick);
|
|
||||||
Element x = new Element("x");
|
Element x = new Element("x");
|
||||||
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
|
x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
|
||||||
if (conversation.getMessages().size() != 0) {
|
if (conversation.getMessages().size() != 0) {
|
||||||
@ -931,6 +990,7 @@ public class XmppConnectionService extends Service {
|
|||||||
|
|
||||||
private OnRenameListener renameListener = null;
|
private OnRenameListener renameListener = null;
|
||||||
private boolean pongReceived;
|
private boolean pongReceived;
|
||||||
|
|
||||||
public void setOnRenameListener(OnRenameListener listener) {
|
public void setOnRenameListener(OnRenameListener listener) {
|
||||||
this.renameListener = listener;
|
this.renameListener = listener;
|
||||||
}
|
}
|
||||||
@ -951,13 +1011,16 @@ public class XmppConnectionService extends Service {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
PresencePacket packet = new PresencePacket();
|
PresencePacket packet = new PresencePacket();
|
||||||
packet.setAttribute("to", conversation.getContactJid().split("/")[0]+"/"+nick);
|
packet.setAttribute("to",
|
||||||
|
conversation.getContactJid().split("/")[0] + "/" + nick);
|
||||||
packet.setAttribute("from", conversation.getAccount().getFullJid());
|
packet.setAttribute("from", conversation.getAccount().getFullJid());
|
||||||
|
|
||||||
packet = conversation.getAccount().getXmppConnection().sendPresencePacket(packet, new OnPresencePacketReceived() {
|
conversation.getAccount().getXmppConnection()
|
||||||
|
.sendPresencePacket(packet, new OnPresencePacketReceived() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPresencePacketReceived(Account account, PresencePacket packet) {
|
public void onPresencePacketReceived(Account account,
|
||||||
|
PresencePacket packet) {
|
||||||
final boolean changed;
|
final boolean changed;
|
||||||
String type = packet.getAttribute("type");
|
String type = packet.getAttribute("type");
|
||||||
changed = (!"error".equals(type));
|
changed = (!"error".equals(type));
|
||||||
@ -965,8 +1028,10 @@ public class XmppConnectionService extends Service {
|
|||||||
options.getOnRenameListener().onRename(false);
|
options.getOnRenameListener().onRename(false);
|
||||||
} else {
|
} else {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
options.getOnRenameListener().onRename(true);
|
options.getOnRenameListener()
|
||||||
options.setNick(packet.getAttribute("from").split("/")[1]);
|
.onRename(true);
|
||||||
|
options.setNick(packet.getAttribute("from")
|
||||||
|
.split("/")[1]);
|
||||||
} else {
|
} else {
|
||||||
options.processPacket(packet);
|
options.processPacket(packet);
|
||||||
}
|
}
|
||||||
@ -974,7 +1039,8 @@ public class XmppConnectionService extends Service {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
String jid = conversation.getContactJid().split("/")[0]+"/"+nick;
|
String jid = conversation.getContactJid().split("/")[0] + "/"
|
||||||
|
+ nick;
|
||||||
conversation.setContactJid(jid);
|
conversation.setContactJid(jid);
|
||||||
databaseBackend.updateConversation(conversation);
|
databaseBackend.updateConversation(conversation);
|
||||||
if (conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
|
if (conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
|
||||||
@ -988,11 +1054,13 @@ public class XmppConnectionService extends Service {
|
|||||||
packet.setAttribute("to", conversation.getContactJid());
|
packet.setAttribute("to", conversation.getContactJid());
|
||||||
packet.setAttribute("from", conversation.getAccount().getFullJid());
|
packet.setAttribute("from", conversation.getAccount().getFullJid());
|
||||||
packet.setAttribute("type", "unavailable");
|
packet.setAttribute("type", "unavailable");
|
||||||
conversation.getAccount().getXmppConnection().sendPresencePacket(packet);
|
conversation.getAccount().getXmppConnection()
|
||||||
|
.sendPresencePacket(packet);
|
||||||
conversation.getMucOptions().setOffline();
|
conversation.getMucOptions().setOffline();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(Account account) {
|
public void disconnect(final Account account, boolean blocking) {
|
||||||
|
if ((account.getStatus() == Account.STATUS_ONLINE)||(account.getStatus() == Account.STATUS_DISABLED)) {
|
||||||
List<Conversation> conversations = getConversations();
|
List<Conversation> conversations = getConversations();
|
||||||
for (int i = 0; i < conversations.size(); i++) {
|
for (int i = 0; i < conversations.size(); i++) {
|
||||||
Conversation conversation = conversations.get(i);
|
Conversation conversation = conversations.get(i);
|
||||||
@ -1009,9 +1077,22 @@ public class XmppConnectionService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
account.getXmppConnection().disconnect();
|
if (!blocking) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
account.getXmppConnection().disconnect(false);
|
||||||
Log.d(LOGTAG, "disconnected account: " + account.getJid());
|
Log.d(LOGTAG, "disconnected account: " + account.getJid());
|
||||||
account.setXmppConnection(null);
|
//account.setXmppConnection(null);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} else {
|
||||||
|
account.getXmppConnection().disconnect(false);
|
||||||
|
Log.d(LOGTAG, "disconnected account: " + account.getJid());
|
||||||
|
//account.setXmppConnection(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1134,57 +1215,23 @@ public class XmppConnectionService extends Service {
|
|||||||
this.tlsException = null;
|
this.tlsException = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reconnectAccount(Account account) {
|
//TODO dont let thread sleep but schedule wake up
|
||||||
|
public void reconnectAccount(final Account account) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
if (account.getXmppConnection() != null) {
|
if (account.getXmppConnection() != null) {
|
||||||
disconnect(account);
|
disconnect(account, true);
|
||||||
}
|
}
|
||||||
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
|
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
|
||||||
if (account.getXmppConnection() == null) {
|
if (account.getXmppConnection() == null) {
|
||||||
account.setXmppConnection(this.createConnection(account));
|
account.setXmppConnection(createConnection(account));
|
||||||
}
|
}
|
||||||
Thread thread = new Thread(account.getXmppConnection());
|
Thread thread = new Thread(account.getXmppConnection());
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ping(final Account account,final int timeout) {
|
|
||||||
Log.d(LOGTAG,account.getJid()+": sending ping");
|
|
||||||
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
|
||||||
Element ping = new Element("ping");
|
|
||||||
iq.setAttribute("from",account.getFullJid());
|
|
||||||
ping.setAttribute("xmlns", "urn:xmpp:ping");
|
|
||||||
iq.addChild(ping);
|
|
||||||
pongReceived = false;
|
|
||||||
account.getXmppConnection().sendIqPacket(iq, new OnIqPacketReceived() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
|
||||||
pongReceived = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int i = 0;
|
|
||||||
while(i <= (5 * timeout)) {
|
|
||||||
if (pongReceived) {
|
|
||||||
scheduleWakeupCall(PING_INTERVAL,true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(200);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
if (!pongReceived) {
|
|
||||||
Log.d("xmppService",account.getJid()+" no pong after "+timeout+" seconds");
|
|
||||||
reconnectAccount(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -332,6 +332,9 @@ public class ConversationFragment extends Fragment {
|
|||||||
final ConversationActivity activity = (ConversationActivity) getActivity();
|
final ConversationActivity activity = (ConversationActivity) getActivity();
|
||||||
activity.registerListener();
|
activity.registerListener();
|
||||||
this.conversation = activity.getSelectedConversation();
|
this.conversation = activity.getSelectedConversation();
|
||||||
|
if (this.conversation==null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.selfBitmap = findSelfPicture();
|
this.selfBitmap = findSelfPicture();
|
||||||
updateMessages();
|
updateMessages();
|
||||||
// rendering complete. now go tell activity to close pane
|
// rendering complete. now go tell activity to close pane
|
||||||
@ -374,7 +377,6 @@ public class ConversationFragment extends Fragment {
|
|||||||
public void updateMessages() {
|
public void updateMessages() {
|
||||||
ConversationActivity activity = (ConversationActivity) getActivity();
|
ConversationActivity activity = (ConversationActivity) getActivity();
|
||||||
List<Message> encryptedMessages = new LinkedList<Message>();
|
List<Message> encryptedMessages = new LinkedList<Message>();
|
||||||
// TODO this.conversation could be null?!
|
|
||||||
for(Message message : this.conversation.getMessages()) {
|
for(Message message : this.conversation.getMessages()) {
|
||||||
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||||
encryptedMessages.add(message);
|
encryptedMessages.add(message);
|
||||||
|
@ -48,7 +48,6 @@ public class ManageAccountActivity extends XmppActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountListChangedListener() {
|
public void onAccountListChangedListener() {
|
||||||
Log.d("xmppService", "ui on account list changed listener");
|
|
||||||
accountList.clear();
|
accountList.clear();
|
||||||
accountList.addAll(xmppConnectionService.getAccounts());
|
accountList.addAll(xmppConnectionService.getAccounts());
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
|
@ -42,8 +42,9 @@ public abstract class XmppActivity extends Activity {
|
|||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
if (!xmppConnectionServiceBound) {
|
if (!xmppConnectionServiceBound) {
|
||||||
startService(new Intent(this, XmppConnectionService.class));
|
|
||||||
Intent intent = new Intent(this, XmppConnectionService.class);
|
Intent intent = new Intent(this, XmppConnectionService.class);
|
||||||
|
intent.setAction("ui");
|
||||||
|
startService(intent);
|
||||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import eu.siacs.conversations.entities.Conversation;
|
|||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xmpp.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
|
|
||||||
public class MessageParser {
|
public class MessageParser {
|
||||||
|
|
||||||
|
@ -5,25 +5,29 @@ import java.io.OutputStream;
|
|||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import android.util.Log;
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
|
||||||
public class TagWriter {
|
public class TagWriter {
|
||||||
|
|
||||||
private OutputStreamWriter outputStream;
|
private OutputStreamWriter outputStream;
|
||||||
private LinkedBlockingQueue<String> writeQueue = new LinkedBlockingQueue<String>();
|
private boolean finshed = false;
|
||||||
private Thread writer = new Thread() {
|
private LinkedBlockingQueue<AbstractStanza> writeQueue = new LinkedBlockingQueue<AbstractStanza>();
|
||||||
public boolean shouldStop = false;
|
private Thread asyncStanzaWriter = new Thread() {
|
||||||
|
private boolean shouldStop = false;
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while(!shouldStop) {
|
while(!shouldStop) {
|
||||||
|
if ((finshed)&&(writeQueue.size() == 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
String output = writeQueue.take();
|
AbstractStanza output = writeQueue.take();
|
||||||
outputStream.write(output);
|
outputStream.write(output.toString());
|
||||||
outputStream.flush();
|
outputStream.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.d("xmppService", "error writing to stream");
|
shouldStop = true;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
shouldStop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,34 +35,49 @@ public class TagWriter {
|
|||||||
|
|
||||||
|
|
||||||
public TagWriter() {
|
public TagWriter() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagWriter(OutputStream out) {
|
public TagWriter(OutputStream out) {
|
||||||
this.setOutputStream(out);
|
this.setOutputStream(out);
|
||||||
writer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputStream(OutputStream out) {
|
public void setOutputStream(OutputStream out) {
|
||||||
this.outputStream = new OutputStreamWriter(out);
|
this.outputStream = new OutputStreamWriter(out);
|
||||||
if (!writer.isAlive()) writer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagWriter beginDocument() {
|
public TagWriter beginDocument() throws IOException {
|
||||||
writeQueue.add("<?xml version='1.0'?>");
|
outputStream.write("<?xml version='1.0'?>");
|
||||||
|
outputStream.flush();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagWriter writeTag(Tag tag) {
|
public TagWriter writeTag(Tag tag) throws IOException {
|
||||||
writeQueue.add(tag.toString());
|
outputStream.write(tag.toString());
|
||||||
|
outputStream.flush();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeString(String string) {
|
public TagWriter writeElement(Element element) throws IOException {
|
||||||
writeQueue.add(string);
|
outputStream.write(element.toString());
|
||||||
|
outputStream.flush();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeElement(Element element) {
|
public TagWriter writeStanzaAsync(AbstractStanza stanza) {
|
||||||
writeQueue.add(element.toString());
|
if (finshed) {
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
if (!asyncStanzaWriter.isAlive()) asyncStanzaWriter.start();
|
||||||
|
writeQueue.add(stanza);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
this.finshed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean finished() {
|
||||||
|
return (this.writeQueue.size() == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
package eu.siacs.conversations.xmpp;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
|
||||||
public interface OnIqPacketReceived extends PacketReceived {
|
public interface OnIqPacketReceived extends PacketReceived {
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet);
|
public void onIqPacketReceived(Account account, IqPacket packet);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
package eu.siacs.conversations.xmpp;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
|
|
||||||
public interface OnMessagePacketReceived extends PacketReceived {
|
public interface OnMessagePacketReceived extends PacketReceived {
|
||||||
public void onMessagePacketReceived(Account account, MessagePacket packet);
|
public void onMessagePacketReceived(Account account, MessagePacket packet);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
package eu.siacs.conversations.xmpp;
|
||||||
|
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
|
|
||||||
public interface OnPresencePacketReceived extends PacketReceived {
|
public interface OnPresencePacketReceived extends PacketReceived {
|
||||||
public void onPresencePacketReceived(Account account, PresencePacket packet);
|
public void onPresencePacketReceived(Account account, PresencePacket packet);
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
|
||||||
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
|
||||||
|
|
||||||
public class PresencePacket extends Element {
|
|
||||||
private PresencePacket(String name) {
|
|
||||||
super("presence");
|
|
||||||
}
|
|
||||||
|
|
||||||
public PresencePacket() {
|
|
||||||
super("presence");
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,10 +26,12 @@ import javax.net.ssl.TrustManager;
|
|||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
@ -38,6 +40,14 @@ import eu.siacs.conversations.xml.Element;
|
|||||||
import eu.siacs.conversations.xml.Tag;
|
import eu.siacs.conversations.xml.Tag;
|
||||||
import eu.siacs.conversations.xml.TagWriter;
|
import eu.siacs.conversations.xml.TagWriter;
|
||||||
import eu.siacs.conversations.xml.XmlReader;
|
import eu.siacs.conversations.xml.XmlReader;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket;
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.streammgmt.ResumePacket;
|
||||||
|
|
||||||
public class XmppConnection implements Runnable {
|
public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
@ -57,6 +67,14 @@ public class XmppConnection implements Runnable {
|
|||||||
private Element streamFeatures;
|
private Element streamFeatures;
|
||||||
private HashSet<String> discoFeatures = new HashSet<String>();
|
private HashSet<String> discoFeatures = new HashSet<String>();
|
||||||
|
|
||||||
|
private String streamId = null;
|
||||||
|
|
||||||
|
private int stanzasReceived = 0;
|
||||||
|
private int stanzasSent = 0;
|
||||||
|
|
||||||
|
public long lastPaketReceived = 0;
|
||||||
|
public long lastPingSent = 0;
|
||||||
|
|
||||||
private static final int PACKET_IQ = 0;
|
private static final int PACKET_IQ = 0;
|
||||||
private static final int PACKET_MESSAGE = 1;
|
private static final int PACKET_MESSAGE = 1;
|
||||||
private static final int PACKET_PRESENCE = 2;
|
private static final int PACKET_PRESENCE = 2;
|
||||||
@ -77,14 +95,16 @@ public class XmppConnection implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void changeStatus(int nextStatus) {
|
protected void changeStatus(int nextStatus) {
|
||||||
|
if (account.getStatus() != nextStatus) {
|
||||||
account.setStatus(nextStatus);
|
account.setStatus(nextStatus);
|
||||||
if (statusListener != null) {
|
if (statusListener != null) {
|
||||||
statusListener.onStatusChanged(account);
|
statusListener.onStatusChanged(account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void connect() {
|
protected void connect() {
|
||||||
Log.d(LOGTAG, "connecting");
|
Log.d(LOGTAG,account.getJid()+ ": connecting");
|
||||||
try {
|
try {
|
||||||
tagReader = new XmlReader(wakeLock);
|
tagReader = new XmlReader(wakeLock);
|
||||||
tagWriter = new TagWriter();
|
tagWriter = new TagWriter();
|
||||||
@ -147,7 +167,6 @@ public class XmppConnection implements Runnable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
connect();
|
connect();
|
||||||
Log.d(LOGTAG, "end run");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processStream(Tag currentTag) throws XmlPullParserException,
|
private void processStream(Tag currentTag) throws XmlPullParserException,
|
||||||
@ -176,6 +195,35 @@ public class XmppConnection implements Runnable {
|
|||||||
} else if (nextTag.isStart("failure")) {
|
} else if (nextTag.isStart("failure")) {
|
||||||
Element failure = tagReader.readElement(nextTag);
|
Element failure = tagReader.readElement(nextTag);
|
||||||
changeStatus(Account.STATUS_UNAUTHORIZED);
|
changeStatus(Account.STATUS_UNAUTHORIZED);
|
||||||
|
} else if (nextTag.isStart("enabled")) {
|
||||||
|
this.stanzasSent = 0;
|
||||||
|
Element enabled = tagReader.readElement(nextTag);
|
||||||
|
if ("true".equals(enabled.getAttribute("resume"))) {
|
||||||
|
this.streamId = enabled.getAttribute("id");
|
||||||
|
Log.d(LOGTAG,account.getJid()+": stream managment enabled (resumable)");
|
||||||
|
} else {
|
||||||
|
Log.d(LOGTAG,account.getJid()+": stream managment enabled");
|
||||||
|
}
|
||||||
|
this.stanzasReceived = 0;
|
||||||
|
RequestPacket r = new RequestPacket();
|
||||||
|
tagWriter.writeStanzaAsync(r);
|
||||||
|
} else if (nextTag.isStart("resumed")) {
|
||||||
|
tagReader.readElement(nextTag);
|
||||||
|
changeStatus(Account.STATUS_ONLINE);
|
||||||
|
Log.d(LOGTAG,account.getJid()+": session resumed");
|
||||||
|
} else if (nextTag.isStart("r")) {
|
||||||
|
tagReader.readElement(nextTag);
|
||||||
|
AckPacket ack = new AckPacket(this.stanzasReceived);
|
||||||
|
//Log.d(LOGTAG,ack.toString());
|
||||||
|
tagWriter.writeStanzaAsync(ack);
|
||||||
|
} else if (nextTag.isStart("a")) {
|
||||||
|
Element ack = tagReader.readElement(nextTag);
|
||||||
|
lastPaketReceived = SystemClock.elapsedRealtime();
|
||||||
|
int serverSequence = Integer.parseInt(ack.getAttribute("h"));
|
||||||
|
if (serverSequence>this.stanzasSent) {
|
||||||
|
this.stanzasSent = serverSequence;
|
||||||
|
}
|
||||||
|
//Log.d(LOGTAG,"server ack"+ack.toString()+" ("+this.stanzasSent+")");
|
||||||
} else if (nextTag.isStart("iq")) {
|
} else if (nextTag.isStart("iq")) {
|
||||||
processIq(nextTag);
|
processIq(nextTag);
|
||||||
} else if (nextTag.isStart("message")) {
|
} else if (nextTag.isStart("message")) {
|
||||||
@ -221,6 +269,8 @@ public class XmppConnection implements Runnable {
|
|||||||
}
|
}
|
||||||
nextTag = tagReader.readTag();
|
nextTag = tagReader.readTag();
|
||||||
}
|
}
|
||||||
|
++stanzasReceived;
|
||||||
|
lastPaketReceived = SystemClock.elapsedRealtime();
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +321,7 @@ public class XmppConnection implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStartTLS() {
|
private void sendStartTLS() throws IOException {
|
||||||
Tag startTLS = Tag.empty("starttls");
|
Tag startTLS = Tag.empty("starttls");
|
||||||
startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
|
startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
|
||||||
tagWriter.writeTag(startTLS);
|
tagWriter.writeTag(startTLS);
|
||||||
@ -378,24 +428,44 @@ public class XmppConnection implements Runnable {
|
|||||||
} else if (this.streamFeatures.hasChild("mechanisms")
|
} else if (this.streamFeatures.hasChild("mechanisms")
|
||||||
&& shouldAuthenticate) {
|
&& shouldAuthenticate) {
|
||||||
sendSaslAuth();
|
sendSaslAuth();
|
||||||
}
|
} else if (this.streamFeatures.hasChild("sm") && streamId != null) {
|
||||||
if (this.streamFeatures.hasChild("bind") && shouldBind) {
|
Log.d(LOGTAG,"found old stream id. trying to remuse");
|
||||||
|
ResumePacket resume = new ResumePacket(this.streamId,stanzasReceived);
|
||||||
|
this.tagWriter.writeStanzaAsync(resume);
|
||||||
|
} else if (this.streamFeatures.hasChild("bind") && shouldBind) {
|
||||||
sendBindRequest();
|
sendBindRequest();
|
||||||
if (this.streamFeatures.hasChild("session")) {
|
if (this.streamFeatures.hasChild("session")) {
|
||||||
|
Log.d(LOGTAG,"sending session");
|
||||||
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
|
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
|
||||||
Element session = new Element("session");
|
Element session = new Element("session");
|
||||||
session.setAttribute("xmlns",
|
session.setAttribute("xmlns",
|
||||||
"urn:ietf:params:xml:ns:xmpp-session");
|
"urn:ietf:params:xml:ns:xmpp-session");
|
||||||
session.setContent("");
|
session.setContent("");
|
||||||
startSession.addChild(session);
|
startSession.addChild(session);
|
||||||
sendIqPacket(startSession, null);
|
this.sendIqPacket(startSession, null);
|
||||||
tagWriter.writeElement(startSession);
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Element presence = new Element("presence");
|
|
||||||
|
|
||||||
tagWriter.writeElement(presence);
|
private void sendInitialPresence() {
|
||||||
|
PresencePacket packet = new PresencePacket();
|
||||||
|
packet.setAttribute("from", account.getFullJid());
|
||||||
|
if (account.getKeys().has("pgp_signature")) {
|
||||||
|
try {
|
||||||
|
String signature = account.getKeys().getString("pgp_signature");
|
||||||
|
Element status = new Element("status");
|
||||||
|
status.setContent("online");
|
||||||
|
packet.addChild(status);
|
||||||
|
Element x = new Element("x");
|
||||||
|
x.setAttribute("xmlns", "jabber:x:signed");
|
||||||
|
x.setContent(signature);
|
||||||
|
packet.addChild(x);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.sendPresencePacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
private void sendBindRequest() throws IOException {
|
private void sendBindRequest() throws IOException {
|
||||||
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
|
||||||
@ -412,10 +482,15 @@ public class XmppConnection implements Runnable {
|
|||||||
.getContent().split("/")[1];
|
.getContent().split("/")[1];
|
||||||
account.setResource(resource);
|
account.setResource(resource);
|
||||||
account.setStatus(Account.STATUS_ONLINE);
|
account.setStatus(Account.STATUS_ONLINE);
|
||||||
|
if (streamFeatures.hasChild("sm")) {
|
||||||
|
EnablePacket enable = new EnablePacket();
|
||||||
|
tagWriter.writeStanzaAsync(enable);
|
||||||
|
}
|
||||||
|
sendInitialPresence();
|
||||||
|
sendServiceDiscovery();
|
||||||
if (statusListener != null) {
|
if (statusListener != null) {
|
||||||
statusListener.onStatusChanged(account);
|
statusListener.onStatusChanged(account);
|
||||||
}
|
}
|
||||||
sendServiceDiscovery();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -471,7 +546,7 @@ public class XmppConnection implements Runnable {
|
|||||||
Log.d(LOGTAG, "processStreamError");
|
Log.d(LOGTAG, "processStreamError");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStartStream() {
|
private void sendStartStream() throws IOException {
|
||||||
Tag stream = Tag.start("stream:stream");
|
Tag stream = Tag.start("stream:stream");
|
||||||
stream.setAttribute("from", account.getJid());
|
stream.setAttribute("from", account.getJid());
|
||||||
stream.setAttribute("to", account.getServer());
|
stream.setAttribute("to", account.getServer());
|
||||||
@ -489,39 +564,52 @@ public class XmppConnection implements Runnable {
|
|||||||
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) {
|
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) {
|
||||||
String id = nextRandomId();
|
String id = nextRandomId();
|
||||||
packet.setAttribute("id", id);
|
packet.setAttribute("id", id);
|
||||||
tagWriter.writeElement(packet);
|
this.sendPacket(packet, callback);
|
||||||
if (callback != null) {
|
|
||||||
packetCallbacks.put(id, callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessagePacket(MessagePacket packet) {
|
public void sendMessagePacket(MessagePacket packet) {
|
||||||
this.sendMessagePacket(packet, null);
|
this.sendPacket(packet, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessagePacket(MessagePacket packet,
|
public void sendMessagePacket(MessagePacket packet,
|
||||||
OnMessagePacketReceived callback) {
|
OnMessagePacketReceived callback) {
|
||||||
String id = nextRandomId();
|
this.sendPacket(packet, callback);
|
||||||
packet.setAttribute("id", id);
|
|
||||||
tagWriter.writeElement(packet);
|
|
||||||
if (callback != null) {
|
|
||||||
packetCallbacks.put(id, callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPresencePacket(PresencePacket packet) {
|
public void sendPresencePacket(PresencePacket packet) {
|
||||||
this.sendPresencePacket(packet, null);
|
this.sendPacket(packet, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PresencePacket sendPresencePacket(PresencePacket packet,
|
public void sendPresencePacket(PresencePacket packet,
|
||||||
OnPresencePacketReceived callback) {
|
OnPresencePacketReceived callback) {
|
||||||
String id = nextRandomId();
|
this.sendPacket(packet, callback);
|
||||||
packet.setAttribute("id", id);
|
}
|
||||||
tagWriter.writeElement(packet);
|
|
||||||
if (callback != null) {
|
private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) {
|
||||||
packetCallbacks.put(id, callback);
|
// TODO dont increment stanza count if packet = request packet or ack;
|
||||||
|
++stanzasSent;
|
||||||
|
tagWriter.writeStanzaAsync(packet);
|
||||||
|
if (callback != null) {
|
||||||
|
if (packet.getId()==null) {
|
||||||
|
packet.setId(nextRandomId());
|
||||||
|
}
|
||||||
|
packetCallbacks.put(packet.getId(), callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPing() {
|
||||||
|
if (streamFeatures.hasChild("sm")) {
|
||||||
|
Log.d(LOGTAG,account.getJid()+": sending r as ping");
|
||||||
|
tagWriter.writeStanzaAsync(new RequestPacket());
|
||||||
|
} else {
|
||||||
|
Log.d(LOGTAG,account.getJid()+": sending iq as ping");
|
||||||
|
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
|
||||||
|
Element ping = new Element("ping");
|
||||||
|
iq.setAttribute("from",account.getFullJid());
|
||||||
|
ping.setAttribute("xmlns", "urn:xmpp:ping");
|
||||||
|
iq.addChild(ping);
|
||||||
|
this.sendIqPacket(iq, null);
|
||||||
}
|
}
|
||||||
return packet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnMessagePacketReceivedListener(
|
public void setOnMessagePacketReceivedListener(
|
||||||
@ -547,8 +635,23 @@ public class XmppConnection implements Runnable {
|
|||||||
this.tlsListener = listener;
|
this.tlsListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() {
|
public void disconnect(boolean force) {
|
||||||
|
Log.d(LOGTAG,"disconnecting");
|
||||||
|
try {
|
||||||
|
if (force) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
tagWriter.finish();
|
||||||
|
while(!tagWriter.finished()) {
|
||||||
|
Log.d(LOGTAG,"not yet finished");
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
tagWriter.writeTag(Tag.end("stream:stream"));
|
tagWriter.writeTag(Tag.end("stream:stream"));
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(LOGTAG,"io exception during disconnect");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.d(LOGTAG,"interupted while waiting for disconnect");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasFeatureRosterManagment() {
|
public boolean hasFeatureRosterManagment() {
|
||||||
@ -558,4 +661,8 @@ public class XmppConnection implements Runnable {
|
|||||||
return this.streamFeatures.hasChild("ver");
|
return this.streamFeatures.hasChild("ver");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void r() {
|
||||||
|
this.tagWriter.writeStanzaAsync(new RequestPacket());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
34
src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java
Normal file
34
src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.xml.Element;
|
||||||
|
|
||||||
|
public class AbstractStanza extends Element {
|
||||||
|
|
||||||
|
protected AbstractStanza(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTo() {
|
||||||
|
return getAttribute("to");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrom() {
|
||||||
|
return getAttribute("from");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return this.getAttribute("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTo(String to) {
|
||||||
|
setAttribute("to", to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrom(String from) {
|
||||||
|
setAttribute("from",from);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
setAttribute("id",id);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
package eu.siacs.conversations.xmpp.stanzas;
|
||||||
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
|
||||||
|
|
||||||
public class IqPacket extends Element {
|
public class IqPacket extends AbstractStanza {
|
||||||
|
|
||||||
public static final int TYPE_SET = 0;
|
public static final int TYPE_SET = 0;
|
||||||
public static final int TYPE_RESULT = 1;
|
public static final int TYPE_RESULT = 1;
|
||||||
@ -33,8 +32,4 @@ public class IqPacket extends Element {
|
|||||||
super("iq");
|
super("iq");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return this.getAttribute("id");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,30 +1,18 @@
|
|||||||
package eu.siacs.conversations.xmpp;
|
package eu.siacs.conversations.xmpp.stanzas;
|
||||||
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
|
|
||||||
public class MessagePacket extends Element {
|
public class MessagePacket extends AbstractStanza {
|
||||||
public static final int TYPE_CHAT = 0;
|
public static final int TYPE_CHAT = 0;
|
||||||
public static final int TYPE_UNKNOWN = 1;
|
public static final int TYPE_UNKNOWN = 1;
|
||||||
public static final int TYPE_NO = 2;
|
public static final int TYPE_NO = 2;
|
||||||
public static final int TYPE_GROUPCHAT = 3;
|
public static final int TYPE_GROUPCHAT = 3;
|
||||||
public static final int TYPE_ERROR = 4;
|
public static final int TYPE_ERROR = 4;
|
||||||
|
|
||||||
private MessagePacket(String name) {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessagePacket() {
|
public MessagePacket() {
|
||||||
super("message");
|
super("message");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTo() {
|
|
||||||
return getAttribute("to");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFrom() {
|
|
||||||
return getAttribute("from");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBody() {
|
public String getBody() {
|
||||||
Element body = this.findChild("body");
|
Element body = this.findChild("body");
|
||||||
if (body!=null) {
|
if (body!=null) {
|
||||||
@ -34,14 +22,6 @@ public class MessagePacket extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTo(String to) {
|
|
||||||
setAttribute("to", to);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrom(String from) {
|
|
||||||
setAttribute("from",from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBody(String text) {
|
public void setBody(String text) {
|
||||||
this.children.remove(findChild("body"));
|
this.children.remove(findChild("body"));
|
||||||
Element body = new Element("body");
|
Element body = new Element("body");
|
@ -0,0 +1,9 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas;
|
||||||
|
|
||||||
|
|
||||||
|
public class PresencePacket extends AbstractStanza {
|
||||||
|
|
||||||
|
public PresencePacket() {
|
||||||
|
super("presence");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas.streammgmt;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
|
||||||
|
public class AckPacket extends AbstractStanza {
|
||||||
|
|
||||||
|
public AckPacket(int sequence) {
|
||||||
|
super("a");
|
||||||
|
this.setAttribute("xmlns","urn:xmpp:sm:3");
|
||||||
|
this.setAttribute("h", ""+sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas.streammgmt;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
|
||||||
|
public class EnablePacket extends AbstractStanza {
|
||||||
|
|
||||||
|
public EnablePacket() {
|
||||||
|
super("enable");
|
||||||
|
this.setAttribute("xmlns","urn:xmpp:sm:3");
|
||||||
|
this.setAttribute("resume", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas.streammgmt;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
|
||||||
|
public class RequestPacket extends AbstractStanza {
|
||||||
|
|
||||||
|
public RequestPacket() {
|
||||||
|
super("r");
|
||||||
|
this.setAttribute("xmlns","urn:xmpp:sm:3");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package eu.siacs.conversations.xmpp.stanzas.streammgmt;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
|
||||||
|
|
||||||
|
public class ResumePacket extends AbstractStanza {
|
||||||
|
|
||||||
|
public ResumePacket(String id, int sequence) {
|
||||||
|
super("resume");
|
||||||
|
this.setAttribute("xmlns","urn:xmpp:sm:3");
|
||||||
|
this.setAttribute("previd", id);
|
||||||
|
this.setAttribute("h", ""+sequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user