📄 httpsession.java
字号:
/**
* $Revision: $
* $Date: $
*
* Copyright (C) 2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL)
* or a commercial license agreement with Jive, a copy of which is included
* in this distribution.
*/
package org.jivesoftware.openfire.http;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.PacketDeliverer;
import org.jivesoftware.openfire.SessionPacketRouter;
import org.jivesoftware.openfire.StreamID;
import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.multiplex.UnknownStanzaException;
import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.openfire.net.SASLAuthentication;
import org.jivesoftware.openfire.net.VirtualConnection;
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.util.Log;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Message;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* 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 LocalClientSession {
private static XmlPullParserFactory factory = null;
private static ThreadLocal<XMPPPacketReader> localParser = null;
static {
try {
factory = XmlPullParserFactory.newInstance(MXParser.class.getName(), null);
factory.setNamespaceAware(true);
}
catch (XmlPullParserException e) {
Log.error("Error creating a parser factory", e);
}
// Create xmpp parser to keep in each thread
localParser = new ThreadLocal<XMPPPacketReader>() {
protected XMPPPacketReader initialValue() {
XMPPPacketReader parser = new XMPPPacketReader();
factory.setNamespaceAware(true);
parser.setXPPFactory(factory);
return parser;
}
};
}
private int wait;
private int hold = 0;
private String language;
private final List<HttpConnection> connectionQueue = new LinkedList<HttpConnection>();
private final List<Deliverable> pendingElements = new ArrayList<Deliverable>();
private final List<Delivered> sentElements = new ArrayList<Delivered>();
private boolean isSecure;
private int maxPollingInterval;
private long lastPoll = -1;
private Set<SessionListener> listeners = new CopyOnWriteArraySet<SessionListener>();
private volatile boolean isClosed;
private int inactivityTimeout;
private long lastActivity;
private long lastRequestID;
private int maxRequests;
private PacketDeliverer backupDeliverer;
private Double version = Double.NaN;
private final Queue<Collection<Element>> packetsToSend = new LinkedList<Collection<Element>>();
// Semaphore which protects the packets to send, so, there can only be one consumer at a time.
private SessionPacketRouter router;
private static final Comparator<HttpConnection> connectionComparator
= new Comparator<HttpConnection>() {
public int compare(HttpConnection o1, HttpConnection o2) {
return (int) (o1.getRequestId() - o2.getRequestId());
}
};
public HttpSession(PacketDeliverer backupDeliverer, String serverName, InetAddress address,
StreamID streamID, long rid) {
super(serverName, null, streamID);
conn = new HttpVirtualConnection(address);
this.lastActivity = System.currentTimeMillis();
this.lastRequestID = rid;
this.backupDeliverer = backupDeliverer;
}
/**
* Returns the stream features which are available for this session.
*
* @return the stream features which are available for this session.
*/
public Collection<Element> getAvailableStreamFeaturesElements() {
List<Element> elements = new ArrayList<Element>();
Element sasl = SASLAuthentication.getSASLMechanismsElement(this);
if (sasl != null) {
elements.add(sasl);
}
// Include Stream Compression Mechanism
if (conn.getCompressionPolicy() != Connection.CompressionPolicy.disabled &&
!conn.isCompressed()) {
Element compression = DocumentHelper.createElement(new QName("compression",
new Namespace("", "http://jabber.org/features/compress")));
Element method = compression.addElement("method");
method.setText("zlib");
elements.add(compression);
}
Element bind = DocumentHelper.createElement(new QName("bind",
new Namespace("", "urn:ietf:params:xml:ns:xmpp-bind")));
elements.add(bind);
Element session = DocumentHelper.createElement(new QName("session",
new Namespace("", "urn:ietf:params:xml:ns:xmpp-session")));
elements.add(session);
return elements;
}
public String getAvailableStreamFeatures() {
StringBuilder sb = new StringBuilder(200);
for (Element element : getAvailableStreamFeaturesElements()) {
sb.append(element.asXML());
}
return sb.toString();
}
/**
* Closes the session. After a session has been closed it will no longer accept new connections
* on the session ID.
*/
public void close() {
if (isClosed) {
return;
}
conn.close();
}
/**
* Returns true if this session has been closed and no longer activley accepting connections.
*
* @return true if this session has been closed and no longer activley accepting connections.
*/
public synchronized boolean isClosed() {
return isClosed;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* Sets the language this session is using.
*
* @param language the language this session is using.
*/
public void setLanaguage(String language) {
this.language = language;
}
/**
* Returns the language this session is using.
*
* @return the language this session is using.
*/
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 maxPollingInterval 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 maxPollingInterval) {
this.maxPollingInterval = maxPollingInterval;
}
/**
* Returns 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.
*
* @return 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.
*/
public int getMaxPollingInterval() {
return this.maxPollingInterval;
}
/**
* The max number of requests it is permissable for this session to have open at any one time.
*
* @param maxRequests The max number of requests it is permissable for this session to have open
* at any one time.
*/
public void setMaxRequests(int maxRequests) {
this.maxRequests = maxRequests;
}
/**
* Returns the max number of requests it is permissable for this session to have open at any one
* time.
*
* @return the max number of requests it is permissable for this session to have open at any one
* time.
*/
public int getMaxRequests() {
return this.maxRequests;
}
/**
* Returns true if all connections on this session should be secured, and false if they should
* not.
*
* @return true if all connections on this session should be secured, and false if they should
* not.
*/
public boolean isSecure() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -