Author: ngn
Date: Tue Jun 29 20:38:59 2010
New Revision: 959093

URL: http://svn.apache.org/viewvc?rev=959093&view=rev
Log:
Better continuation implementation
Full SASL auth
Improved merged responses
Stanza routing
(VYSPER-213, by Bogdan Pistol)

Modified:
    
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
    
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java
    
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
    
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
    
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java

Modified: 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
URL: 
http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java?rev=959093&r1=959092&r2=959093&view=diff
==============================================================================
--- 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
 (original)
+++ 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
 Tue Jun 29 20:38:59 2010
@@ -67,6 +67,8 @@ public class NamespaceURIs {
     public static final String URN_XMPP_PING = "urn:xmpp:ping";
 
     public static final String URN_XMPP_DELAY = "urn:xmpp:delay";
+    
+    public static final String URN_XMPP_XBOSH = "urn:xmpp:xbosh";
 
     public static final String VCARD_TEMP = "vcard-temp";
 
@@ -93,5 +95,4 @@ public class NamespaceURIs {
     public static final String XEP0060_PUBSUB_ERRORS = 
"http://jabber.org/protocol/pubsub#errors";;
 
     public static final String XEP0124_BOSH = 
"http://jabber.org/protocol/httpbind";;
-
 }

Modified: 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java
URL: 
http://svn.apache.org/viewvc/mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java?rev=959093&r1=959092&r2=959093&view=diff
==============================================================================
--- 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java
 (original)
+++ 
mina/vysper/trunk/server/core/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java
 Tue Jun 29 20:38:59 2010
@@ -108,7 +108,7 @@ public class ServerResponses {
         return stanzaBuilder.build();
     }
 
-    private Stanza getFeaturesForSession() {
+    public Stanza getFeaturesForSession() {
         StanzaBuilder stanzaBuilder = startFeatureStanza();
 
         stanzaBuilder.startInnerElement("bind", 
NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_BIND).startInnerElement(

Modified: 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
URL: 
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java?rev=959093&r1=959092&r2=959093&view=diff
==============================================================================
--- 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
 (original)
+++ 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
 Tue Jun 29 20:38:59 2010
@@ -32,6 +32,7 @@ import org.apache.vysper.xmpp.server.Ses
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.writer.StanzaWriter;
 import org.eclipse.jetty.continuation.Continuation;
+import org.eclipse.jetty.continuation.ContinuationListener;
 import org.eclipse.jetty.continuation.ContinuationSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -63,7 +64,7 @@ public class BoshBackedSessionContext ex
 
     private Queue<HttpServletRequest> requestQueue;
 
-    private Queue<BoshResponse> delayedResponseQueue;
+    private Queue<Stanza> delayedResponseQueue;
 
     /**
      * Creates a new context for a session
@@ -72,10 +73,10 @@ public class BoshBackedSessionContext ex
      */
     public BoshBackedSessionContext(BoshHandler boshHandler, 
ServerRuntimeContext serverRuntimeContext) {
         super(serverRuntimeContext, new SessionStateHolder());
-        sessionStateHolder.setState(SessionState.INITIATED);
+        sessionStateHolder.setState(SessionState.ENCRYPTED);
         this.boshHandler = boshHandler;
         requestQueue = new LinkedList<HttpServletRequest>();
-        delayedResponseQueue = new LinkedList<BoshResponse>();
+        delayedResponseQueue = new LinkedList<Stanza>();
     }
 
     public SessionStateHolder getStateHolder() {
@@ -89,18 +90,25 @@ public class BoshBackedSessionContext ex
     public void setIsReopeningXMLStream() {
     }
 
-    public void write(Stanza stanza) {
-        write(getResponse(stanza));
+    synchronized public void write(Stanza stanza) {
+        write0(boshHandler.wrapStanza(stanza));
     }
 
-    public void write(BoshResponse resp) {
+    /*
+     *  package access
+     */
+    void write0(Stanza boshStanza) {
         HttpServletRequest req = requestQueue.poll();
         if (req == null) {
-            delayedResponseQueue.offer(resp);
+            delayedResponseQueue.offer(boshStanza);
             return;
         }
+        BoshResponse boshResponse = getBoshResponse(boshStanza);
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("BOSH writing stanza: {}", new 
String(boshResponse.getContent()));
+        }
         Continuation continuation = ContinuationSupport.getContinuation(req);
-        continuation.setAttribute("response", resp);
+        continuation.setAttribute("response", boshResponse);
         continuation.resume();
     }
 
@@ -169,15 +177,21 @@ public class BoshBackedSessionContext ex
         return requests;
     }
 
-    synchronized public void requestExpired(HttpServletRequest req) {
+    synchronized public void requestExpired(Continuation continuation) {
+        HttpServletRequest req = (HttpServletRequest) 
continuation.getAttribute("request");
+        if (req == null) {
+            LOGGER.warn("Continuation expired without having an associated 
request!");
+            return;
+        }
+        continuation.setAttribute("response", 
getBoshResponse(boshHandler.getEmptyStanza()));
         for (;;) {
             HttpServletRequest r = requestQueue.peek();
             if (r == null) {
-                return;
+                break;
             }
-            write(boshHandler.getEmptyStanza());
+            write0(boshHandler.getEmptyStanza());
             if (r == req) {
-                return;
+                break;
             }
         }
     }
@@ -186,21 +200,37 @@ public class BoshBackedSessionContext ex
         Continuation continuation = ContinuationSupport.getContinuation(req);
         continuation.setTimeout(wait * 1000);
         continuation.suspend();
-        continuation.setAttribute("session", this);
+        continuation.setAttribute("request", req);
         requestQueue.offer(req);
 
-        BoshResponse resp = delayedResponseQueue.poll();
-        if (resp != null) {
-            write(resp);
+        continuation.addContinuationListener(new ContinuationListener() {
+
+            public void onTimeout(Continuation continuation) {
+                requestExpired(continuation);
+            }
+
+            public void onComplete(Continuation continuation) {
+                // ignore
+            }
+
+        });
+
+        Stanza delayedStanza;
+        Stanza mergedStanza = null;
+        while ((delayedStanza = delayedResponseQueue.poll()) != null) {
+            mergedStanza = boshHandler.mergeStanzas(mergedStanza, 
delayedStanza);
+        }
+        if (mergedStanza != null) {
+            write0(mergedStanza);
             return;
         }
 
         if (requestQueue.size() > hold) {
-            write(boshHandler.getEmptyStanza());
+            write0(boshHandler.getEmptyStanza());
         }
     }
-
-    public BoshResponse getResponse(Stanza stanza) {
+    
+    private BoshResponse getBoshResponse(Stanza stanza) {
         byte[] content = new Renderer(stanza).getComplete().getBytes();
         return new BoshResponse(contentType, content);
     }

Modified: 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
URL: 
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java?rev=959093&r1=959092&r2=959093&view=diff
==============================================================================
--- 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
 (original)
+++ 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
 Tue Jun 29 20:38:59 2010
@@ -25,9 +25,11 @@ import java.util.concurrent.ConcurrentHa
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.vysper.xmpp.authorization.SASLMechanism;
+import org.apache.vysper.xml.fragment.XMLElement;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.server.response.ServerResponses;
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.stanza.StanzaBuilder;
 import org.slf4j.Logger;
@@ -86,10 +88,54 @@ public class BoshHandler {
                 return;
             }
         } else {
-            //            handleSession(req, stanza);
+            BoshBackedSessionContext session = 
sessions.get(stanza.getAttributeValue("sid"));
+            if (session == null) {
+                LOGGER.warn("Received an invalid 'sid'!");
+                return;
+            }
+            synchronized (session) {
+                session.addRequest(req);
+                processSession(session, stanza);
+            }
+        }
+    }
+    
+    private void processSession(BoshBackedSessionContext session, Stanza 
stanza) {
+        if (session.getState() == SessionState.ENCRYPTED) {
+            if (stanza.getInnerElements().isEmpty()) {
+                // session needs authentication
+                return;
+            }
+            for (XMLElement element : stanza.getInnerElements()) {
+                if 
(element.getNamespaceURI().equals(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL))
 {
+                    processStanza(session, element);
+                }
+            }
+        } else if (session.getState() == SessionState.AUTHENTICATED) {
+            if 
("true".equals(stanza.getAttributeValue(NamespaceURIs.URN_XMPP_XBOSH, 
"restart"))) {
+                // restart request
+                session.write0(getRestartResponseStanza());
+            } else {
+                // any other request
+                for (XMLElement element : stanza.getInnerElements()) {
+                    processStanza(session, element);
+                }
+            }
         }
     }
 
+    private void processStanza(BoshBackedSessionContext session, XMLElement 
element) {
+        Stanza innerStanza;
+        if (element instanceof Stanza) {
+            innerStanza = (Stanza) element;
+        } else {
+            innerStanza = new Stanza(element.getNamespaceURI(), 
element.getName(), element.getNamespacePrefix(),
+                    element.getAttributes(), element.getInnerFragments());
+        }
+        
serverRuntimeContext.getStanzaProcessor().processStanza(serverRuntimeContext, 
session, innerStanza,
+                session.getStateHolder());
+    }
+
     private void createSession(HttpServletRequest req, Stanza stanza) throws 
IOException {
         BoshBackedSessionContext session = new BoshBackedSessionContext(this, 
serverRuntimeContext);
         if (stanza.getAttribute("content") != null) {
@@ -110,7 +156,7 @@ public class BoshHandler {
         session.addRequest(req);
         sessions.put(session.getSessionId(), session);
 
-        session.write(getSessionCreationStanza(session));
+        session.write0(getSessionCreationStanza(session));
     }
 
     public Stanza getSessionCreationStanza(BoshBackedSessionContext session) {
@@ -124,15 +170,9 @@ public class BoshHandler {
         body.addAttribute("ver", session.getBoshVersion());
         body.addAttribute("from", 
session.getServerJID().getFullQualifiedName());
 
-        StanzaBuilder features = new StanzaBuilder("features", 
NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS, "stream");
-        features.startInnerElement("mechanisms", 
NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL);
-        for (SASLMechanism authenticationMethod : 
serverRuntimeContext.getServerFeatures().getAuthenticationMethods()) {
-            features.startInnerElement("mechanism", 
NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL).addText(
-                    authenticationMethod.getName()).endInnerElement();
-        }
-        features.endInnerElement();
-
-        body.addPreparedElement(features.build());
+        Stanza features = new 
ServerResponses().getFeaturesForAuthentication(serverRuntimeContext.getServerFeatures()
+                .getAuthenticationMethods());
+        body.addPreparedElement(features);
         return body.build();
     }
 
@@ -141,4 +181,35 @@ public class BoshHandler {
         return stanzaBuilder.build();
     }
 
+    public Stanza wrapStanza(Stanza stanza) {
+        StanzaBuilder body = new StanzaBuilder("body", 
NamespaceURIs.XEP0124_BOSH);
+        body.addPreparedElement(stanza);
+        return body.build();
+    }
+    
+    public Stanza mergeStanzas(Stanza stanza1, Stanza stanza2) {
+        if (stanza1 == null && stanza2 == null) {
+            return null;
+        }
+        if (stanza1 == null) {
+            return stanza2;
+        }
+        if (stanza2 == null) {
+            return stanza1;
+        }
+        StanzaBuilder body = new StanzaBuilder("body", 
NamespaceURIs.XEP0124_BOSH);
+        for (XMLElement element : stanza1.getInnerElements()) {
+            body.addPreparedElement(element);
+        }
+        for (XMLElement element : stanza2.getInnerElements()) {
+            body.addPreparedElement(element);
+        }
+        return body.build();
+    }
+    
+    private Stanza getRestartResponseStanza() {
+        Stanza features = new ServerResponses().getFeaturesForSession();
+        return wrapStanza(features);
+    }
+
 }

Modified: 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
URL: 
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java?rev=959093&r1=959092&r2=959093&view=diff
==============================================================================
--- 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
 (original)
+++ 
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
 Tue Jun 29 20:38:59 2010
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.vysper.xmpp.server.ServerRuntimeContext;
-import org.eclipse.jetty.continuation.ContinuationSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.SAXException;
@@ -129,23 +128,11 @@ public class BoshServlet extends HttpSer
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
         BoshResponse boshResponse = (BoshResponse) 
req.getAttribute("response");
         if (boshResponse != null) {
-            // if continuation is resumed
+            // if continuation is resumed or expired
             writeResponse(resp, boshResponse);
             return;
         }
 
-        if (ContinuationSupport.getContinuation(req).isExpired()) {
-            // BOSH wait time is reached
-            BoshBackedSessionContext session = (BoshBackedSessionContext) 
req.getAttribute("session");
-            if (session == null) {
-                logger.error("Continuation expired without having a session 
associated!");
-                return;
-            }
-            session.requestExpired(req);
-            //            writeResponse(resp, 
session.getResponse(boshHandler.getEmptyStanza()));
-            return;
-        }
-
         BoshDecoder decoder = new BoshDecoder(boshHandler, req);
         try {
             decoder.decode();


Reply via email to