/** * $RCSfile$ * $Revision: $ * $Date: $ * * Copyright (C) 2006 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */ package org.jivesoftware.multiplexer.net.http; import org.jivesoftware.multiplexer.*; import org.dom4j.Element; import org.dom4j.DocumentHelper; import java.util.*; /** * A session represents a serious of interactions with an XMPP client sending packets using the HTTP * Binding protocol specified in * <a href="http://www.xmpp.org/extensions/xep-0124.html">XEP-0124</a>. A session can have several * client connections open simultaneously while awaiting packets bound for the client from the * server. * * @author Alexander Wenckus */ public class HttpSession extends Session { private int wait; private int hold = -1000; private String language; private final Queue<HttpConnection> connectionQueue = new LinkedList<HttpConnection>(); private final List<Element> pendingElements = new ArrayList<Element>(); protected HttpSession(String serverName, String streamID) { super(serverName, null, streamID); } void addConnection(HttpConnection connection, boolean isPoll) { if(connection == null) { throw new IllegalArgumentException("Connection cannot be null."); } connection.setSession(this); if(pendingElements.size() > 0) { createDeliverable(pendingElements); pendingElements.clear(); return; } // With this connection we need to check if we will have too many connections open, closing // any extras. while(hold > 0 && connectionQueue.size() >= hold) { HttpConnection toClose = connectionQueue.remove(); toClose.close(); } connectionQueue.offer(connection); } public String getAvailableStreamFeatures() { return null; } public void close() { } public void close(boolean isServerShuttingDown) { } public synchronized void deliver(Element stanza) { String deliverable = createDeliverable(Arrays.asList(stanza)); boolean delivered = false; while(!delivered && connectionQueue.size() > 0) { HttpConnection connection = connectionQueue.remove(); try { connection.deliverBody(deliverable); delivered = true; } catch (HttpConnectionClosedException e) { /* Connection was closed, try the next one */ } } if(!delivered) { pendingElements.add(stanza); } } private String createDeliverable(Collection<Element> elements) { Element body = DocumentHelper.createElement("body"); body.addAttribute("xmlns", "http://jabber.org/protocol/httpbind"); for(Element child : elements) { child = child.createCopy(); child.setParent(null); body.add(child); } return body.asXML(); } /** * This attribute specifies the longest time (in seconds) that the connection manager is allowed * to wait before responding to any request during the session. This enables the client to * prevent its TCP connection from expiring due to inactivity, as well as to limit the delay * before it discovers any network failure. * * @param wait the longest time it is permissible to wait for a response. */ public void setWait(int wait) { this.wait = wait; } /** * This attribute specifies the longest time (in seconds) that the connection manager is allowed * to wait before responding to any request during the session. This enables the client to * prevent its TCP connection from expiring due to inactivity, as well as to limit the delay * before it discovers any network failure. * * @return the longest time it is permissible to wait for a response. */ public int getWait() { return wait; } /** * This attribute specifies the maximum number of requests the connection manager is allowed * to keep waiting at any one time during the session. (For example, if a constrained client * is unable to keep open more than two HTTP connections to the same HTTP server simultaneously, * then it SHOULD specify a value of "1".) * * @param hold the maximum number of simultaneous waiting requests. * */ public void setHold(int hold) { this.hold = hold; } /** * This attribute specifies the maximum number of requests the connection manager is allowed * to keep waiting at any one time during the session. (For example, if a constrained client * is unable to keep open more than two HTTP connections to the same HTTP server simultaneously, * then it SHOULD specify a value of "1".) * * @return the maximum number of simultaneous waiting requests */ public int getHold() { return hold; } public void setLanaguage(String language) { this.language = language; } public String getLanguage() { return language; } /** * Sets the max interval within which a client can send polling requests. If more than one * request occurs in the interval the session will be terminated. * * @param pollingInterval time in seconds a client needs to wait before sending polls to the * server, a negative <i>int</i> indicates that there is no limit. */ public void setMaxPollingInterval(int pollingInterval) { } }