org.hd.d.pg2k.webSvr.exhibit
Class TunnelServlet

java.lang.Object
  extended by javax.servlet.GenericServlet
      extended by javax.servlet.http.HttpServlet
          extended by org.hd.d.pg2k.webSvr.exhibit.TunnelServlet
All Implemented Interfaces:
java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig

public final class TunnelServlet
extends javax.servlet.http.HttpServlet

This serves data through an HTTP tunnel from master Web-app to authorised slaves, ie is an RPC end-point. We are communicating on the client side with ExhibitDataHTTPTunnelSource and may have (at least) one long-running open connection per slave.

Takes data from whatever the DataSourceBean is using.

This allows concurrency between different slaves, and for multiple connections from each slave, though this concurrency may be limited by resource constraints.

Notice that all operations require some degree of authentication:

Note that for messages that have a MAC:

See Also:
Serialized Form

Nested Class Summary
private static class TunnelServlet.WrappedIOException
           
 
Field Summary
private  SecurityProps _gSP_cache
          Cached SecurityProps; private to getSecurityProps(); never null.
private  ExhibitDataTunnelSource.HIRPCCache _RPC_cache
          Cache/lock object to optimise handling of incoming RPCs; never null.
private static boolean isDebug
          If debugging locally, note some activity at protocol level.
static int LARGE_FRAME_BYTES
          Size in bytes of 'big' frame that may require special handling; strictly positive.
private  WebUtils.ServletLoggerWithFallback logger
          Our logger which falls back to System.out if servlet log not available; never null.
private static int MAX_TYPICAL_SERVICE_TIME_MS
          Maximum expected typical service time, ms.
private  DuplicateIDChecker<ROByteArray> messageIDs
          Record of unique request packet IDs around our acceptance window; never null.
private static long serialVersionUID
          Unique Serialisation class ID generated by http://random.hd.org/.
private  StatsLogger.StatsConfig statsIDTSV
          The stats set to which we log general tunnel servlet stats.
static java.lang.String TSVNAME_HTTPFAIL
          General stats event name: failures handling input HTTP requests.
static java.lang.String TSVNAME_HTTPREJADDR
          General stats event name: inbound HTTP request rejected by client IP address.
static java.lang.String TSVNAME_HTTPREJID
          General stats event name: inbound HTTP request rejected by ID/passwoed.
static java.lang.String TSVNAME_HTTPREJOP
          General stats event name: inbound HTTP request rejected by request op-code.
static java.lang.String TSVNAME_HTTPREQUEST
          General stats event name: inbound HTTP request.
static java.lang.String TSVNAMEP_HTTPSERVICETIME
          General stats event name prefix: inbound HTTP request service time (ms exponent).
static java.lang.String TSVNAMEP_HTTPSLOWOP
          General stats event name prefix: slow inbound HTTP request op code.
static java.lang.String TSVNAMEPR_RPCTYPE
          General stats event name prefix: RPC request packet type.
 
Constructor Summary
TunnelServlet()
           
 
Method Summary
static ExhibitDataTunnelSource createFromContext(javax.servlet.ServletContext ctxt)
          Factory method to create an instance given the ServletContext.
 void destroy()
          Unhook from servlet logger.
 void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
          Respond to a POST request to open and use an HTTP tunnel (for a single transfer).
private  SimpleExhibitPipelineIF getDataSource()
          Get data source/pipeline; never returns null.
private static DataSourceBean getDataSourceBean(javax.servlet.ServletContext ctxt, javax.servlet.http.HttpServletRequest request)
          Get singleton (per-servlet-context) data pipeline/cache instance.
private  SecurityProps getSecurityProps()
          Get SecurityProps (including sensitives values); never returns null.
 void init(javax.servlet.ServletConfig servletConfig)
          Hook into servlet logger.
private static boolean isPeerMirror(DataSourceBean ds, java.net.InetAddress addr)
          Returns true iff the address is that of a (peer) mirror/slave.
private  void writeResponsePacketToWire(javax.servlet.http.HttpServletResponse response, javax.crypto.SecretKey xk, javax.servlet.ServletOutputStream os, ExhibitDataTunnelSource.RawPacket rawResponse)
          Efficiently write the raw response frame/packet to the write, with a MAC if possible.
 
Methods inherited from class javax.servlet.http.HttpServlet
doDelete, doGet, doHead, doOptions, doPut, doTrace, getLastModified, service, service
 
Methods inherited from class javax.servlet.GenericServlet
getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

isDebug

private static final boolean isDebug
If debugging locally, note some activity at protocol level.

See Also:
Constant Field Values

logger

private final WebUtils.ServletLoggerWithFallback logger
Our logger which falls back to System.out if servlet log not available; never null.


statsIDTSV

private final StatsLogger.StatsConfig statsIDTSV
The stats set to which we log general tunnel servlet stats. The unique codes are the constants TSNAME_XXX.


TSVNAME_HTTPREQUEST

public static final java.lang.String TSVNAME_HTTPREQUEST
General stats event name: inbound HTTP request.

See Also:
Constant Field Values

TSVNAMEP_HTTPSERVICETIME

public static final java.lang.String TSVNAMEP_HTTPSERVICETIME
General stats event name prefix: inbound HTTP request service time (ms exponent).

See Also:
Constant Field Values

TSVNAMEP_HTTPSLOWOP

public static final java.lang.String TSVNAMEP_HTTPSLOWOP
General stats event name prefix: slow inbound HTTP request op code.

See Also:
Constant Field Values

TSVNAME_HTTPFAIL

public static final java.lang.String TSVNAME_HTTPFAIL
General stats event name: failures handling input HTTP requests.

See Also:
Constant Field Values

TSVNAME_HTTPREJADDR

public static final java.lang.String TSVNAME_HTTPREJADDR
General stats event name: inbound HTTP request rejected by client IP address.

See Also:
Constant Field Values

TSVNAME_HTTPREJID

public static final java.lang.String TSVNAME_HTTPREJID
General stats event name: inbound HTTP request rejected by ID/passwoed.

See Also:
Constant Field Values

TSVNAME_HTTPREJOP

public static final java.lang.String TSVNAME_HTTPREJOP
General stats event name: inbound HTTP request rejected by request op-code.

See Also:
Constant Field Values

TSVNAMEPR_RPCTYPE

public static final java.lang.String TSVNAMEPR_RPCTYPE
General stats event name prefix: RPC request packet type.

See Also:
Constant Field Values

MAX_TYPICAL_SERVICE_TIME_MS

private static final int MAX_TYPICAL_SERVICE_TIME_MS
Maximum expected typical service time, ms. Should generally be well under 1000ms.

This should in fact be a tiny bit less than the total RTT, since there is a short delay from when we send the last response byte to it being processed by the receiver (eg due to transmission delays), but we ignore that for now.

See Also:
Constant Field Values

LARGE_FRAME_BYTES

public static final int LARGE_FRAME_BYTES
Size in bytes of 'big' frame that may require special handling; strictly positive. Inbound frames at least this big may need to be rejected or handled serially because of the heap space they may consume, and indeed may be rejected simply because the system is temporarily busy with another memory-intensive task at the time.

Almost all 'normal' inbound packets should be below this threshold.

See Also:
Constant Field Values

_gSP_cache

private volatile SecurityProps _gSP_cache
Cached SecurityProps; private to getSecurityProps(); never null. Volatile so as to allow access without a lock.


_RPC_cache

private final ExhibitDataTunnelSource.HIRPCCache _RPC_cache
Cache/lock object to optimise handling of incoming RPCs; never null.


messageIDs

private final DuplicateIDChecker<ROByteArray> messageIDs
Record of unique request packet IDs around our acceptance window; never null. We use the final MAC segment ID, as that covers the entire frame.

We actually remember IDs for about twice the age implied by the skew so that if our clock is wrong by, or slips by, the maximum skew, we won't start admitting very old duplicate messages.

We should only add IDs if possible when we are already fairly sure of the source and when we have, for example, already checked for acceptable skew, to make any sort of DoS attack against us harder.

We should reject otherwise-acceptable messages that have an ID already present in this Map.

Thread-safe.


serialVersionUID

private static final long serialVersionUID
Unique Serialisation class ID generated by http://random.hd.org/.

See Also:
Constant Field Values
Constructor Detail

TunnelServlet

public TunnelServlet()
Method Detail

destroy

public void destroy()
Unhook from servlet logger.

Specified by:
destroy in interface javax.servlet.Servlet
Overrides:
destroy in class javax.servlet.GenericServlet

init

public void init(javax.servlet.ServletConfig servletConfig)
          throws javax.servlet.ServletException
Hook into servlet logger.

Specified by:
init in interface javax.servlet.Servlet
Overrides:
init in class javax.servlet.GenericServlet
Throws:
javax.servlet.ServletException

getDataSourceBean

private static DataSourceBean getDataSourceBean(javax.servlet.ServletContext ctxt,
                                                javax.servlet.http.HttpServletRequest request)
Get singleton (per-servlet-context) data pipeline/cache instance. The config param must not be null, but for some operations (such as calling destroy()) request can be null.

This does not cache its return value.


getDataSource

private SimpleExhibitPipelineIF getDataSource()
Get data source/pipeline; never returns null. This routine may or may not cache its result, but the caller should not cache it.


getSecurityProps

private SecurityProps getSecurityProps()
                                throws java.io.IOException
Get SecurityProps (including sensitives values); never returns null. May cache results for performance.

Throws:
TunnelServlet.WrappedIOException - if SecurityProps cannot be retrieved (eg because no local file exists)
java.io.IOException

doPost

public void doPost(javax.servlet.http.HttpServletRequest request,
                   javax.servlet.http.HttpServletResponse response)
            throws java.io.IOException
Respond to a POST request to open and use an HTTP tunnel (for a single transfer). Slave servers should refuse to respond to these requests; ie only respond if seemingly a master.

Normal slave servers are primarily authenticated by IP address and have full real/write access.

Uploader JWS clients are authenticated by username/password, and have partial, read-only access.

Overrides:
doPost in class javax.servlet.http.HttpServlet
Throws:
TunnelServlet.WrappedIOException - if an input/output error occurs
java.io.IOException

writeResponsePacketToWire

private void writeResponsePacketToWire(javax.servlet.http.HttpServletResponse response,
                                       javax.crypto.SecretKey xk,
                                       javax.servlet.ServletOutputStream os,
                                       ExhibitDataTunnelSource.RawPacket rawResponse)
                                throws java.security.InvalidKeyException,
                                       java.io.IOException
Efficiently write the raw response frame/packet to the write, with a MAC if possible. TODO: This may also log traffic volumes by type and destination.

Throws:
java.security.InvalidKeyException
java.io.IOException

isPeerMirror

private static boolean isPeerMirror(DataSourceBean ds,
                                    java.net.InetAddress addr)
                             throws java.io.IOException
Returns true iff the address is that of a (peer) mirror/slave. Does this by looking at the IP addresses of inbound slave connections as seen by the master, so as to capture the outgoing IP addresses of each mirror.

No local/loopback addresses are considered valid.

Parameters:
ds - current data source; never null
addr - client address; never null
Throws:
java.io.IOException

createFromContext

public static ExhibitDataTunnelSource createFromContext(javax.servlet.ServletContext ctxt)
Factory method to create an instance given the ServletContext. Will fail if the CoreConsts.WAR_CTXTPARAM_BOOTURL param is not set.


DHD Multimedia Gallery V1.57.21

Copyright (c) 1996-2011, Damon Hart-Davis. All rights reserved.