// --------------------------------------------------------------------------- // jWebSocket - Base Connector Implementation // Copyright (c) 2010 Alexander Schulze, Innotrade GmbH // --------------------------------------------------------------------------- // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published by the // Free Software Foundation; either version 3 of the License, or (at your // option) any later version. // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for // more details. // You should have received a copy of the GNU Lesser General Public License along // with this program; if not, see <http://www.gnu.org/licenses/lgpl.html>. // --------------------------------------------------------------------------- package org.jwebsocket.connectors; import java.net.InetAddress; import java.util.Map; import javolution.util.FastMap; import org.jwebsocket.api.WebSocketConnector; import org.jwebsocket.api.WebSocketConnectorStatus; import org.jwebsocket.api.WebSocketEngine; import org.jwebsocket.api.WebSocketPacket; import org.jwebsocket.async.IOFuture; import org.jwebsocket.config.JWebSocketCommonConstants; import org.jwebsocket.config.JWebSocketConfig; import org.jwebsocket.kit.*; /** * Provides the basic implementation of the jWebSocket connectors. The * {@code BaseConnector} is supposed to be used as ancestor for the connector * implementations like e.g. the {@code TCPConnector} or the * {@code NettyConnector }. * * @author aschulze */ public class BaseConnector implements WebSocketConnector { /** * Default reserved name for shared custom variable <tt>username</tt>. */ public final static String VAR_USERNAME = "$username"; /** * Default reserved name for shared custom variable <tt>subprot</tt>. */ public final static String VAR_SUBPROT = "$subprot"; /** * Default reserved name for shared custom variable <tt>version</tt>. */ public final static String VAR_VERSION = "$version"; /** * Default name for shared custom variable <tt>nodeid</tt>. */ public final static String VAR_NODEID = "$nodeid"; /** * Is connector using SSL encryption? */ private boolean mIsSSL = false; /* * Status of the connector. */ private volatile WebSocketConnectorStatus mStatus = WebSocketConnectorStatus.DOWN; /** * The WebSocket protocol version. */ private int mVersion = JWebSocketCommonConstants.WS_VERSION_DEFAULT; /** * Backward reference to the engine of this connector. */ private WebSocketEngine mEngine = null; /** * Backup of the original request header and it's fields. * TODO: maybe obsolete for the future */ private RequestHeader mHeader = null; /** * Session object for the WebSocket connection. */ private final WebSocketSession mSession = new WebSocketSession(); /** * Shared Variables container for this connector. */ private final Map<String, Object> mCustomVars = new FastMap<String, Object>(); private final Object mWriteLock = new Object(); private final Object mReadLock = new Object(); /** * * @param aEngine */ public BaseConnector(WebSocketEngine aEngine) { mEngine = aEngine; } @Override public void startConnector() { if (mEngine != null) { mEngine.connectorStarted(this); } } @Override public void stopConnector(CloseReason aCloseReason) { if (mEngine != null) { mEngine.connectorStopped(this, aCloseReason); } } /** * Returns the current status for the connector. * Please refer to the WebSocketConnectorStatus enumeration. * * @return */ @Override public WebSocketConnectorStatus getStatus() { return mStatus; } /** * Sets the current status for the connector. * Please refer to the WebSocketConnectorStatus enumeration. * * @param aStatus */ @Override public void setStatus(WebSocketConnectorStatus aStatus) { mStatus = aStatus; } /** * * @return */ @Override public Object getWriteLock() { return mWriteLock; } /** * * @return */ @Override public Object getReadLock() { return mReadLock; } @Override public void processPacket(WebSocketPacket aDataPacket) { if (mEngine != null) { mEngine.processPacket(this, aDataPacket); } } @Override public void processPing(WebSocketPacket aDataPacket) { /* if (mEngine != null) { mEngine.processPing(this, aDataPacket); } */ } @Override public void processPong(WebSocketPacket aDataPacket) { /* if (mEngine != null) { mEngine.processPong(this, aDataPacket); } */ } @Override public void sendPacketInTransaction(WebSocketPacket aDataPacket) throws WebSocketException { } @Override public void sendPacket(WebSocketPacket aDataPacket) { } @Override public IOFuture sendPacketAsync(WebSocketPacket aDataPacket) { return null; } @Override public WebSocketEngine getEngine() { return mEngine; } @Override public RequestHeader getHeader() { return mHeader; } /** * @param aHeader * the header to set */ @Override public void setHeader(RequestHeader aHeader) { // TODO: the sub protocol should be a connector variable! not part of // the header! this.mHeader = aHeader; // TODO: this can be improved, maybe distinguish between header and URL // args! Map lArgs = aHeader.getArgs(); if (lArgs != null) { String lNodeId = (String) lArgs.get("unid"); if (lNodeId != null) { setNodeId(lNodeId); lArgs.remove("unid"); } } } @Override public Object getVar(String aKey) { return mCustomVars.get(aKey); } @Override public void setVar(String aKey, Object aValue) { mCustomVars.put(aKey, aValue); } @Override public Boolean getBoolean(String aKey) { return (Boolean) getVar(aKey); } @Override public boolean getBool(String aKey) { Boolean lBool = getBoolean(aKey); return (lBool != null && lBool); } @Override public void setBoolean(String aKey, Boolean aValue) { setVar(aKey, aValue); } @Override public String getString(String aKey) { return (String) getVar(aKey); } @Override public void setString(String aKey, String aValue) { setVar(aKey, aValue); } @Override public Integer getInteger(String aKey) { return (Integer) getVar(aKey); } @Override public void setInteger(String aKey, Integer aValue) { setVar(aKey, aValue); } @Override public void removeVar(String aKey) { mCustomVars.remove(aKey); } @Override public String generateUID() { return null; } @Override public int getRemotePort() { return -1; } @Override public InetAddress getRemoteHost() { return null; } private String mUniqueId = null; private static Integer mCounter = 0; @Override public String getId() { synchronized (mCounter) { if (null == mUniqueId) { String lNodeId = JWebSocketConfig.getConfig().getNodeId(); mUniqueId = ((lNodeId != null && lNodeId.length() > 0) ? lNodeId + "." : "") + String.valueOf(getRemotePort()) + "." + mCounter++; } return mUniqueId; } } @Override public WebSocketSession getSession() { return mSession; } public Map<String, Object> getVars() { return mCustomVars; } // some convenience methods to easier process username (login-status) // and configured unique node id for clusters (independent from tcp port) @Override public String getUsername() { return getString(BaseConnector.VAR_USERNAME); } @Override public void setUsername(String aUsername) { setString(BaseConnector.VAR_USERNAME, aUsername); } @Override public void removeUsername() { removeVar(BaseConnector.VAR_USERNAME); } // some convenience methods to easier process subprot (login-status) // and configured unique node id for clusters (independent from tcp port) @Override public String getSubprot() { return getString(BaseConnector.VAR_SUBPROT); } @Override public void setSubprot(String aSubprot) { setString(BaseConnector.VAR_SUBPROT, aSubprot); } @Override public int getVersion() { return mVersion; } @Override public void setVersion(int aVersion) { mVersion = aVersion; } @Override public void removeSubprot() { removeVar(BaseConnector.VAR_SUBPROT); } @Override public boolean isLocal() { // TODO: This has to be updated for the cluster approach return true; } @Override public String getNodeId() { return getString(BaseConnector.VAR_NODEID); } @Override public void setNodeId(String aNodeId) { setString(BaseConnector.VAR_NODEID, aNodeId); } @Override public void removeNodeId() { removeVar(BaseConnector.VAR_NODEID); } @Override public boolean isSSL() { return mIsSSL; } @Override public void setSSL(boolean aIsSSL) { mIsSSL = aIsSSL; } @Override public boolean isHixie() { return WebSocketProtocolAbstraction.isHixieVersion(getVersion()); } @Override public boolean isHybi() { return WebSocketProtocolAbstraction.isHybiVersion(getVersion()); } }