use of org.jivesoftware.smack.debugger.SmackDebugger in project Zom-Android by zom.
the class XmppConnection method initConnection.
// Runs in executor thread
private void initConnection(Imps.ProviderSettings.QueryMap providerSettings, String userName) throws InterruptedException, NoSuchAlgorithmException, KeyManagementException, XMPPException, SmackException, IOException {
// never! // providerSettings.getAllowPlainAuth();
boolean allowPlainAuth = false;
// providerSettings.getRequireTls(); //always!
boolean requireTls = true;
boolean doDnsSrv = providerSettings.getDoDnsSrv();
// boolean tlsCertVerify = providerSettings.getTlsCertVerify();
// boolean useSASL = true;//!allowPlainAuth;
// boolean useProxy = providerSettings.getUseTor();
String domain = providerSettings.getDomain();
mPriority = providerSettings.getXmppResourcePrio();
int serverPort = providerSettings.getPort();
String server = providerSettings.getServer();
if ("".equals(server))
server = null;
if (domain.equals("dukgo.com")) {
doDnsSrv = false;
server = "dukgo.com";
}
debug(TAG, "TLS required? " + requireTls);
if (// if serverPort is set to 0 then use 5222 as default
serverPort == 0)
serverPort = 5222;
mConfig = XMPPTCPConnectionConfiguration.builder();
mConfig.setServiceName(JidCreate.domainBareFrom(domain));
mConfig.setPort(serverPort);
mConfig.setCompressionEnabled(true);
mConfig.setConnectTimeout(CONNECT_TIMEOUT);
mConfig.setXmppDomain(domain);
mConfig.setHost(domain);
if (!TextUtils.isEmpty(server))
mConfig.setHost(server);
if (!TextUtils.isEmpty(Preferences.getProxyServerHost())) {
setProxy("SOCKS5", Preferences.getProxyServerHost(), Preferences.getProxyServerPort());
} else if (Preferences.useAdvancedNetworking()) {
setProxy("SOCKS5", "127.0.0.1", 31059);
} else {
mProxyInfo = null;
// SRV lookup shouldn't be done through a proxy
if (doDnsSrv) {
// java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
// java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
debug(TAG, "(DNS SRV) resolving: " + domain);
List<HostAddress> listHostsFailed = new ArrayList<>();
List<HostAddress> listHosts = DNSUtil.resolveXMPPServiceDomain(domain, listHostsFailed, ConnectionConfiguration.DnssecMode.disabled);
if (listHosts.size() > 0) {
server = listHosts.get(0).getFQDN();
serverPort = listHosts.get(0).getPort();
debug(TAG, "(DNS SRV) resolved: " + domain + "=" + server + ":" + serverPort);
if (!TextUtils.isEmpty(server))
mConfig.setHost(server);
if (serverPort != -1)
mConfig.setPort(serverPort);
}
}
if (!TextUtils.isEmpty(server)) {
try {
String[] addressParts = server.split("\\.");
if (Integer.parseInt(addressParts[0]) != -1) {
byte[] parts = new byte[addressParts.length];
for (int i = 0; i < 4; i++) parts[i] = (byte) Integer.parseInt(addressParts[i]);
byte[] ipAddr = new byte[] { parts[0], parts[1], parts[2], parts[3] };
InetAddress addr = InetAddress.getByAddress(ipAddr);
mConfig.setHostAddress(addr);
} else {
mConfig.setHostAddress(InetAddress.getByName(server));
}
} catch (Exception e) {
debug(TAG, "error parsing server as IP address; using as hostname instead");
mConfig.setHostAddress(InetAddress.getByName(server));
}
}
}
mConfig.setProxyInfo(mProxyInfo);
mConfig.setDebuggerEnabled(Debug.DEBUG_ENABLED);
SmackConfiguration.DEBUG = Debug.DEBUG_ENABLED;
SmackConfiguration.setDebuggerFactory(new SmackDebuggerFactory() {
@Override
public SmackDebugger create(XMPPConnection xmppConnection, Writer writer, Reader reader) throws IllegalArgumentException {
return new AndroidDebugger(xmppConnection, writer, reader);
}
});
// mConfig.setSASLAuthenticationEnabled(useSASL);
// Android has no support for Kerberos or GSSAPI, so disable completely
SASLAuthentication.unregisterSASLMechanism("KERBEROS_V4");
SASLAuthentication.unregisterSASLMechanism("GSSAPI");
if (allowPlainAuth)
SASLAuthentication.unBlacklistSASLMechanism("PLAIN");
SASLAuthentication.unBlacklistSASLMechanism("DIGEST-MD5");
if (mMemTrust == null)
mMemTrust = new MemorizingTrustManager(mContext);
if (sslContext == null) {
sslContext = SSLContext.getInstance(SSLCONTEXT_TYPE);
secureRandom = new java.security.SecureRandom();
sslContext.init(null, MemorizingTrustManager.getInstanceList(mContext), secureRandom);
while (true) {
try {
if (Build.VERSION.SDK_INT >= 20) {
sslContext.getDefaultSSLParameters().setCipherSuites(XMPPCertPins.SSL_IDEAL_CIPHER_SUITES_API_20);
} else {
sslContext.getDefaultSSLParameters().setCipherSuites(XMPPCertPins.SSL_IDEAL_CIPHER_SUITES);
}
break;
} catch (IllegalStateException e) {
debug(TAG, "error setting cipher suites; waiting for SSLContext to init...");
try {
Thread.sleep(1000);
} catch (Exception e2) {
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mConfig.setKeystoreType("AndroidCAStore");
mConfig.setKeystorePath(null);
} else {
mConfig.setKeystoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null)
path = System.getProperty("java.home") + File.separator + "etc" + File.separator + "security" + File.separator + "cacerts.bks";
mConfig.setKeystorePath(path);
}
// wait a second while the ssl context init's
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= 16) {
while (true) {
try {
mConfig.setEnabledSSLProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" });
sslContext.getDefaultSSLParameters().setProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" });
break;
} catch (IllegalStateException ise) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
}
}
}
if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mConfig.setEnabledSSLCiphers(XMPPCertPins.SSL_IDEAL_CIPHER_SUITES);
}
mConfig.setCustomSSLContext(sslContext);
mConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
mConfig.setHostnameVerifier(mMemTrust.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()));
mConfig.setSendPresence(true);
XMPPTCPConnection.setUseStreamManagementDefault(true);
XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true);
mConnection = new XMPPTCPConnection(mConfig.build());
DeliveryReceiptManager.getInstanceFor(mConnection).addReceiptReceivedListener(new ReceiptReceivedListener() {
@Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
ChatSession session = mSessionManager.findSession(fromJid.asBareJid());
if (session != null)
session.onMessageReceipt(receiptId);
}
});
mConnection.addSyncStanzaListener(new StanzaListener() {
@Override
public void processStanza(Stanza stanza) {
debug(TAG, "receive message: " + stanza.getFrom() + " to " + stanza.getTo());
org.jivesoftware.smack.packet.Message smackMessage = (org.jivesoftware.smack.packet.Message) stanza;
handleMessage(smackMessage, false, true);
String msg_xml = smackMessage.toXML().toString();
try {
handleChatState(smackMessage.getFrom().toString(), msg_xml);
} catch (RemoteException re) {
// no worries
}
}
}, new StanzaTypeFilter(org.jivesoftware.smack.packet.Message.class));
mConnection.addSyncStanzaListener(new StanzaListener() {
@Override
public void processStanza(Stanza packet) {
org.jivesoftware.smack.packet.Presence presence = (org.jivesoftware.smack.packet.Presence) packet;
qPresence.add(presence);
}
}, new StanzaTypeFilter(org.jivesoftware.smack.packet.Presence.class));
if (mTimerPackets != null)
mTimerPackets.cancel();
initPacketProcessor();
if (mTimerPresence != null)
mTimerPresence.cancel();
initPresenceProcessor();
if (mTimerNewContacts != null)
mTimerNewContacts.cancel();
initNewContactProcessor();
ConnectionListener connectionListener = new ConnectionListener() {
/**
* Called from smack when connect() is fully successful
*
* This is called on the executor thread while we are in reconnect()
*/
@Override
public void reconnectionSuccessful() {
if (mStreamHandler == null || !mStreamHandler.isResumePending()) {
debug(TAG, "Reconnection success");
onReconnectionSuccessful();
mRoster = Roster.getInstanceFor(mConnection);
sendPresencePacket();
mChatGroupManager.reconnectAll();
} else {
debug(TAG, "Ignoring reconnection callback due to pending resume");
}
}
@Override
public void reconnectionFailed(Exception e) {
debug(TAG, "reconnection failed", e);
// We are not using the reconnection manager
// throw new UnsupportedOperationException();
execute(new Runnable() {
public void run() {
mNeedReconnect = true;
setState(LOGGING_IN, new ImErrorInfo(ImErrorInfo.NETWORK_ERROR, "network error"));
reconnect();
}
});
}
@Override
public void reconnectingIn(int seconds) {
// // We are not using the reconnection manager
// throw new UnsupportedOperationException();
debug(TAG, "reconnecting in " + seconds + " seconds...");
}
@Override
public void connectionClosedOnError(final Exception e) {
/*
* This fires when:
* - Packet reader or writer detect an error
* - Stream compression failed
* - TLS fails but is required
* - Network error
* - We forced a socket shutdown
*/
debug(TAG, "reconnect on error: " + e.getMessage(), e);
if (e.getMessage().contains("conflict")) {
execute(new Runnable() {
@Override
public void run() {
// disconnect();
disconnected(new ImErrorInfo(ImpsErrorInfo.ALREADY_LOGGED, "logged in from another location"));
}
});
} else if (!mNeedReconnect) {
execute(new Runnable() {
public void run() {
if (getState() == LOGGED_IN) {
mNeedReconnect = true;
setState(LOGGING_IN, new ImErrorInfo(ImErrorInfo.NETWORK_ERROR, "network error"));
reconnect();
}
}
});
}
}
@Override
public void connected(XMPPConnection connection) {
debug(TAG, "connected");
try {
initOmemo((XMPPTCPConnection) connection);
} catch (Exception e) {
debug("OMEMO", "There was a problem init'g omemo", e);
}
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
debug(TAG, "authenticated: resumed=" + resumed);
sendPresencePacket();
mChatGroupManager.reconnectAll();
}
@Override
public void connectionClosed() {
debug(TAG, "connection closed");
// if the state is logged in, we should try to reconnect!
if (getState() == LOGGED_IN) {
execute(new Runnable() {
public void run() {
mNeedReconnect = true;
setState(LOGGING_IN, new ImErrorInfo(ImErrorInfo.NETWORK_ERROR, "network error"));
reconnect();
}
});
}
}
};
mConnection.addConnectionListener(connectionListener);
mStreamHandler = new XmppStreamHandler(mConnection, connectionListener);
Exception xmppConnectException = null;
AbstractXMPPConnection conn = mConnection.connect();
}
use of org.jivesoftware.smack.debugger.SmackDebugger in project Smack by igniterealtime.
the class XmppTcpTransportModule method onChannelSelected.
private void onChannelSelected(SelectableChannel selectedChannel, SelectionKey selectedSelectionKey) {
assert selectionKey == null || selectionKey == selectedSelectionKey;
SocketChannel selectedSocketChannel = (SocketChannel) selectedChannel;
// We are *always* interested in OP_READ.
int newInterestedOps = SelectionKey.OP_READ;
boolean newPendingOutputFilterData = false;
if (!channelSelectedCallbackLock.tryLock()) {
rejectedChannelSelectedCallbacks.incrementAndGet();
return;
}
handledChannelSelectedCallbacks++;
long callbackBytesRead = 0;
long callbackBytesWritten = 0;
try {
boolean destinationAddressChanged = false;
boolean isLastPartOfElement = false;
TopLevelStreamElement currentlyOutgonigTopLevelStreamElement = null;
StringBuilder outgoingStreamForDebugger = null;
writeLoop: while (true) {
final boolean moreDataAvailable = !isLastPartOfElement || !connectionInternal.outgoingElementsQueue.isEmpty();
if (filteredOutgoingBuffer != null || !networkOutgoingBuffers.isEmpty()) {
if (filteredOutgoingBuffer != null) {
networkOutgoingBuffers.add(filteredOutgoingBuffer);
networkOutgoingBuffersBytes += filteredOutgoingBuffer.remaining();
filteredOutgoingBuffer = null;
if (moreDataAvailable && networkOutgoingBuffersBytes < 8096) {
continue;
}
}
ByteBuffer[] output = networkOutgoingBuffers.toArray(new ByteBuffer[networkOutgoingBuffers.size()]);
long bytesWritten;
try {
bytesWritten = selectedSocketChannel.write(output);
} catch (IOException e) {
// We have seen here so far
// - IOException "Broken pipe"
handleReadWriteIoException(e);
break;
}
if (bytesWritten == 0) {
newInterestedOps |= SelectionKey.OP_WRITE;
break;
}
callbackBytesWritten += bytesWritten;
networkOutgoingBuffersBytes -= bytesWritten;
List<? extends Buffer> prunedBuffers = pruneBufferList(networkOutgoingBuffers);
for (Buffer prunedBuffer : prunedBuffers) {
List<TopLevelStreamElement> sendElements = bufferToElementMap.remove(prunedBuffer);
if (sendElements == null) {
continue;
}
for (TopLevelStreamElement elementJustSend : sendElements) {
connectionInternal.fireFirstLevelElementSendListeners(elementJustSend);
}
}
// written a certain amount.
if (callbackBytesWritten > CALLBACK_MAX_BYTES_WRITEN) {
newInterestedOps |= SelectionKey.OP_WRITE;
callbackPreemtBecauseBytesWritten++;
break;
}
} else if (outgoingBuffer != null || pendingOutputFilterData) {
pendingOutputFilterData = false;
if (outgoingBuffer != null) {
totalBytesWrittenBeforeFilter += outgoingBuffer.remaining();
if (isLastPartOfElement) {
assert currentlyOutgonigTopLevelStreamElement != null;
currentlyOutgoingElements.add(currentlyOutgonigTopLevelStreamElement);
}
}
ByteBuffer outputFilterInputData = outgoingBuffer;
// We can now null the outgoingBuffer since the filter step will take care of it from now on.
outgoingBuffer = null;
for (ListIterator<XmppInputOutputFilter> it = connectionInternal.getXmppInputOutputFilterBeginIterator(); it.hasNext(); ) {
XmppInputOutputFilter inputOutputFilter = it.next();
XmppInputOutputFilter.OutputResult outputResult;
try {
outputResult = inputOutputFilter.output(outputFilterInputData, isLastPartOfElement, destinationAddressChanged, moreDataAvailable);
} catch (IOException e) {
connectionInternal.notifyConnectionError(e);
break writeLoop;
}
newPendingOutputFilterData |= outputResult.pendingFilterData;
outputFilterInputData = outputResult.filteredOutputData;
if (outputFilterInputData != null) {
outputFilterInputData.flip();
}
}
// It is ok if outpuFilterInputData is 'null' here, this is expected behavior.
if (outputFilterInputData != null && outputFilterInputData.hasRemaining()) {
filteredOutgoingBuffer = outputFilterInputData;
} else {
filteredOutgoingBuffer = null;
}
// pending output data then we have a pending write request after read.
if (filteredOutgoingBuffer == null && newPendingOutputFilterData) {
pendingWriteInterestAfterRead = true;
}
if (filteredOutgoingBuffer != null && isLastPartOfElement) {
bufferToElementMap.put(filteredOutgoingBuffer, new ArrayList<>(currentlyOutgoingElements));
currentlyOutgoingElements.clear();
}
// Reset that the destination address has changed.
if (destinationAddressChanged) {
destinationAddressChanged = false;
}
} else if (outgoingCharSequenceIterator != null) {
CharSequence nextCharSequence = outgoingCharSequenceIterator.next();
outgoingBuffer = UTF8.encode(nextCharSequence);
if (!outgoingCharSequenceIterator.hasNext()) {
outgoingCharSequenceIterator = null;
isLastPartOfElement = true;
} else {
isLastPartOfElement = false;
}
final SmackDebugger debugger = connectionInternal.smackDebugger;
if (debugger != null) {
if (outgoingStreamForDebugger == null) {
outgoingStreamForDebugger = new StringBuilder();
}
outgoingStreamForDebugger.append(nextCharSequence);
if (isLastPartOfElement) {
try {
outputDebugSplitter.append(outgoingStreamForDebugger);
} catch (IOException e) {
throw new AssertionError(e);
}
debugger.onOutgoingElementCompleted();
outgoingStreamForDebugger = null;
}
}
} else if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
currentlyOutgonigTopLevelStreamElement = connectionInternal.outgoingElementsQueue.poll();
if (currentlyOutgonigTopLevelStreamElement instanceof Stanza) {
Stanza currentlyOutgoingStanza = (Stanza) currentlyOutgonigTopLevelStreamElement;
Jid currentDestinationAddress = currentlyOutgoingStanza.getTo();
destinationAddressChanged = !JidUtil.equals(lastDestinationAddress, currentDestinationAddress);
lastDestinationAddress = currentDestinationAddress;
}
CharSequence nextCharSequence = currentlyOutgonigTopLevelStreamElement.toXML(StreamOpen.CLIENT_NAMESPACE);
if (nextCharSequence instanceof XmlStringBuilder) {
XmlStringBuilder xmlStringBuilder = (XmlStringBuilder) nextCharSequence;
XmlEnvironment outgoingStreamXmlEnvironment = connectionInternal.getOutgoingStreamXmlEnvironment();
outgoingCharSequenceIterator = xmlStringBuilder.toList(outgoingStreamXmlEnvironment).iterator();
} else {
outgoingCharSequenceIterator = Collections.singletonList(nextCharSequence).iterator();
}
assert outgoingCharSequenceIterator != null;
} else {
// There is nothing more to write.
break;
}
}
pendingOutputFilterData = newPendingOutputFilterData;
if (!pendingWriteInterestAfterRead && pendingOutputFilterData) {
newInterestedOps |= SelectionKey.OP_WRITE;
}
readLoop: while (true) {
// read a certain amount.
if (callbackBytesRead > CALLBACK_MAX_BYTES_READ) {
callbackPreemtBecauseBytesRead++;
break;
}
int bytesRead;
incomingBuffer.clear();
try {
bytesRead = selectedSocketChannel.read(incomingBuffer);
} catch (IOException e) {
handleReadWriteIoException(e);
return;
}
if (bytesRead < 0) {
LOGGER.finer("NIO read() returned " + bytesRead + " for " + this + ". This probably means that the TCP connection was terminated.");
/*
IOException exception = new IOException("NIO read() returned " + bytesRead);
notifyConnectionError(exception);
*/
return;
}
if (!pendingInputFilterData) {
if (bytesRead == 0) {
// Nothing more to read.
break;
}
} else {
pendingInputFilterData = false;
}
if (pendingWriteInterestAfterRead) {
// We have successfully read something and someone announced a write interest after a read. It is
// now possible that a filter is now also able to write additional data (for example SSLEngine).
pendingWriteInterestAfterRead = false;
newInterestedOps |= SelectionKey.OP_WRITE;
}
callbackBytesRead += bytesRead;
ByteBuffer filteredIncomingBuffer = incomingBuffer;
for (ListIterator<XmppInputOutputFilter> it = connectionInternal.getXmppInputOutputFilterEndIterator(); it.hasPrevious(); ) {
filteredIncomingBuffer.flip();
ByteBuffer newFilteredIncomingBuffer;
try {
newFilteredIncomingBuffer = it.previous().input(filteredIncomingBuffer);
} catch (IOException e) {
connectionInternal.notifyConnectionError(e);
return;
}
if (newFilteredIncomingBuffer == null) {
break readLoop;
}
filteredIncomingBuffer = newFilteredIncomingBuffer;
}
final int bytesReadAfterFilter = filteredIncomingBuffer.flip().remaining();
totalBytesReadAfterFilter += bytesReadAfterFilter;
try {
splitter.write(filteredIncomingBuffer);
} catch (IOException e) {
connectionInternal.notifyConnectionError(e);
return;
}
}
} finally {
totalBytesWritten += callbackBytesWritten;
totalBytesRead += callbackBytesRead;
channelSelectedCallbackLock.unlock();
}
// Indicate that there is no reactor thread racing towards handling this selection key.
final SelectionKeyAttachment selectionKeyAttachment = this.selectionKeyAttachment;
if (selectionKeyAttachment != null) {
selectionKeyAttachment.resetReactorThreadRacing();
}
// called resetReactorThreadRacing() a few lines above.
if (!connectionInternal.outgoingElementsQueue.isEmpty()) {
setWriteInterestAfterChannelSelectedCallback.incrementAndGet();
newInterestedOps |= SelectionKey.OP_WRITE;
}
connectionInternal.setInterestOps(selectionKey, newInterestedOps);
}
Aggregations