public static StartTls parseStartTlsFeature(XmlPullParser parser) throws XmlPullParserException, IOException { assert (parser.getEventType() == XmlPullParser.START_TAG); assert (parser.getNamespace().equals(StartTls.NAMESPACE)); int initalDepth = parser.getDepth(); boolean required = false; outerloop: while (true) { int event = parser.next(); switch (event) { case XmlPullParser.START_TAG: String name = parser.getName(); switch (name) { case "required": required = true; break; } break; case XmlPullParser.END_TAG: if (parser.getDepth() == initalDepth) { break outerloop; } } } assert(parser.getEventType() == XmlPullParser.END_TAG); return new StartTls(required); }
@Override protected void afterFeaturesReceived() throws SecurityRequiredException, NotConnectedException { StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE); if (startTlsFeature != null) { if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) { notifyConnectionError(new SecurityRequiredByServerException()); return; } // 发送StartTLS的封包 // 让我们进入TLS链接 if (config.getSecurityMode() != ConnectionConfiguration.SecurityMode.disabled) { send(new StartTls()); } } // If TLS is required but the server doesn't offer it, disconnect // from the server and throw an error. First check if we've already negotiated TLS // and are secure, however (features get parsed a second time after TLS is established). if (!isSecureConnection() && startTlsFeature == null && getConfiguration().getSecurityMode() == SecurityMode.required) { throw new SecurityRequiredByClientException(); } if (getSASLAuthentication().authenticationSuccessful()) { // If we have received features after the SASL has been successfully completed, then we // have also *maybe* received, as it is an optional feature, the compression feature // from the server. maybeCompressFeaturesReceived.reportSuccess(); } }
@Override protected void afterFeaturesReceived() throws NotConnectedException, InterruptedException { StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE); if (startTlsFeature != null) { if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) { SmackException smackException = new SecurityRequiredByServerException(); tlsHandled.reportFailure(smackException); notifyConnectionError(smackException); return; } if (config.getSecurityMode() != ConnectionConfiguration.SecurityMode.disabled) { sendNonza(new StartTls()); } else { tlsHandled.reportSuccess(); } } else { tlsHandled.reportSuccess(); } if (getSASLAuthentication().authenticationSuccessful()) { // If we have received features after the SASL has been successfully completed, then we // have also *maybe* received, as it is an optional feature, the compression feature // from the server. maybeCompressFeaturesReceived.reportSuccess(); } }
protected final void parseFeatures(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException { streamFeatures.clear(); final int initialDepth = parser.getDepth(); while (true) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG && parser.getDepth() == initialDepth + 1) { ExtensionElement streamFeature = null; String name = parser.getName(); String namespace = parser.getNamespace(); switch (name) { case StartTls.ELEMENT: streamFeature = PacketParserUtils.parseStartTlsFeature(parser); break; case Mechanisms.ELEMENT: streamFeature = new Mechanisms(PacketParserUtils.parseMechanisms(parser)); break; case Bind.ELEMENT: streamFeature = Bind.Feature.INSTANCE; break; case Session.ELEMENT: streamFeature = PacketParserUtils.parseSessionFeature(parser); break; case Compress.Feature.ELEMENT: streamFeature = PacketParserUtils.parseCompressionFeature(parser); break; default: ExtensionElementProvider<ExtensionElement> provider = ProviderManager.getStreamFeatureProvider(name, namespace); if (provider != null) { streamFeature = provider.parse(parser); } break; } if (streamFeature != null) { // 将特性放入列表中 addStreamFeature(streamFeature); } } else if (eventType == XmlPullParser.END_TAG && parser.getDepth() == initialDepth) { break; } } if (hasFeature(Mechanisms.ELEMENT, Mechanisms.NAMESPACE)) { // Only proceed with SASL auth if TLS is disabled or if the server doesn't announce it if (!hasFeature(StartTls.ELEMENT, StartTls.NAMESPACE) || config.getSecurityMode() == SecurityMode.disabled) { // connecting算事完成了 saslFeatureReceived.reportSuccess(); } } // If the server reported the bind feature then we are that that we did SASL and maybe // STARTTLS. We can then report that the last 'stream:features' have been parsed if (hasFeature(Bind.ELEMENT, Bind.NAMESPACE)) { if (!hasFeature(Compress.Feature.ELEMENT, Compress.NAMESPACE) || !config.isCompressionEnabled()) { // This was was last features from the server is either it did not contain // compression or if we disabled it lastFeaturesReceived.reportSuccess(); } } afterFeaturesReceived(); }