in server/core/src/main/java/org/apache/vysper/xmpp/modules/core/base/handler/StreamStartHandler.java [63:192]
public void execute(Stanza stanza, ServerRuntimeContext serverRuntimeContext, boolean isOutboundStanza,
SessionContext sessionContext, SessionStateHolder sessionStateHolder, StanzaBroker stanzaBroker) {
XMLElementVerifier xmlElementVerifier = stanza.getVerifier();
boolean jabberNamespace = NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS.equals(stanza.getNamespaceURI());
boolean clientCall = xmlElementVerifier.namespacePresent(NamespaceURIs.JABBER_CLIENT);
boolean serverCall = xmlElementVerifier.namespacePresent(NamespaceURIs.JABBER_SERVER);
// TODO is it better to derive c2s or s2s from the type of endpoint and verify
// the namespace here?
if (clientCall && serverCall)
serverCall = false; // silently ignore ambiguous attributes
if (serverCall)
sessionContext.setServerToServer();
else
sessionContext.setClientToServer();
if (sessionStateHolder.getState() != SessionState.INITIATED
&& sessionStateHolder.getState() != SessionState.ENCRYPTED
&& sessionStateHolder.getState() != SessionState.AUTHENTICATED) {
stanzaBroker.writeToSession(buildUnsupportedStanzaType("unexpected stream start"));
return;
}
// http://etherx.jabber.org/streams cannot be omitted
if (!jabberNamespace) {
stanzaBroker.writeToSession(buildIllegalNamespaceError(
"namespace is mandatory: " + NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS));
return;
}
// processing xml:lang
String xmlLang = stanza.getXMLLang();
sessionContext.setXMLLang(xmlLang);
// processing version
XMPPVersion responseVersion = null;
// if version is not present, version "0.0" is assumed, represented by NULL.
String versionAttributeValue = stanza.getAttributeValue("version");
if (versionAttributeValue != null) {
XMPPVersion clientVersion;
try {
clientVersion = new XMPPVersion(versionAttributeValue);
} catch (IllegalArgumentException e) {
// version string does not conform to spec
stanzaBroker.writeToSession(
buildUnsupportedVersionError(xmlLang, versionAttributeValue, "illegal version value: "));
return;
}
// check if version is supported
if (!clientVersion.equals(XMPPVersion.VERSION_1_0)) {
if (clientVersion.getMajor() == XMPPVersion.VERSION_1_0.getMajor()) {
// we live with the higher minor version, but only support ours
responseVersion = XMPPVersion.VERSION_1_0;
} else {
// we do not support major changes, as of RFC3920
stanzaBroker.writeToSession(buildUnsupportedVersionError(xmlLang, versionAttributeValue,
"major version change not supported: "));
return;
}
} else {
responseVersion = clientVersion;
}
}
if (xmlElementVerifier.attributePresent("id")) {
// ignore silently (see RFC3920 4.4)
}
Stanza responseStanza = null;
if (clientCall) {
// RFC3920: 'to' attribute SHOULD be used by the initiating entity
String toValue = stanza.getAttributeValue("to");
if (toValue != null) {
try {
EntityImpl.parse(toValue);
} catch (EntityFormatException e) {
stanzaBroker.writeToSession(ServerErrorResponses.getStreamError(
StreamErrorCondition.IMPROPER_ADDRESSING, sessionContext.getXMLLang(),
"could not parse incoming stanza's TO attribute", null));
return;
}
// TODO check if toEntity is served by this server
// if (!server.doesServe(toEntity)) throw WhateverException();
// TODO RFC3920: 'from' attribute SHOULD be silently ignored by the receiving
// entity
// TODO RFC3920bis: 'from' attribute SHOULD be not ignored by the receiving
// entity and used as 'to' in responses
}
responseStanza = new ServerResponses().getStreamOpenerForClient(sessionContext.getServerJID(),
responseVersion, sessionContext);
} else if (serverCall) {
// RFC3920: 'from' attribute SHOULD be used by the receiving entity
String fromValue = stanza.getAttributeValue("from");
if (fromValue != null) {
try {
EntityImpl.parse(fromValue);
} catch (EntityFormatException e) {
stanzaBroker.writeToSession(ServerErrorResponses.getStreamError(StreamErrorCondition.INVALID_FROM,
sessionContext.getXMLLang(), "could not parse incoming stanza's FROM attribute", null));
return;
}
}
responseStanza = new ServerResponses().getStreamOpenerForServerAcceptor(sessionContext.getServerJID(),
responseVersion, sessionContext, serverRuntimeContext.getSslContext() != null);
} else {
String descriptiveText = "one of the two namespaces must be present: " + NamespaceURIs.JABBER_CLIENT
+ " or " + NamespaceURIs.JABBER_SERVER;
stanzaBroker.writeToSession(buildIllegalNamespaceError(descriptiveText));
return;
}
// if all is correct, go to next phase
switch (sessionStateHolder.getState()) {
case AUTHENTICATED:
case ENCRYPTED:
// do not change state!
break;
default:
sessionStateHolder.setState(SessionState.STARTED);
}
if (responseStanza == null) {
return;
}
stanzaBroker.writeToSession(responseStanza);
}