*/
private void acceptConnection() throws Exception {
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, "TcpConnectionListener.acceptConnection()");
Socket sock = proxyService.getServerSocket().accept();
String inaddr = sock.getInetAddress().getHostAddress();
connectionCount++;
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, " -> accept connection from " + inaddr);
try {
sock.setTcpNoDelay(true);
// Fix bug when the client doesn't use the right protocol (e.g. Telnet)
// and blocks this listener.
sock.setSoTimeout(timeout);
InputStream is = sock.getInputStream();
NetOutputStream nos = new NetOutputStream(sock);
byte[] magic = StreamUtil.readByteArrayFrom(is, 8);
for (int i = 0; i < 5; i++) {
if (magic.length == i || magic[i] != MetaData.joramMagic[i] && magic[i] > 0) {
String errorMsg = "Bad magic number. Client is not compatible with JORAM.";
logger.log(BasicLevel.ERROR, errorMsg);
protocolErrorCount++;
throw new IllegalAccessException(errorMsg);
}
}
if (magic[7] != MetaData.joramMagic[7]) {
if (magic[7] > 0 && MetaData.joramMagic[7] > 0) {
String errorMsg = "Bad protocol version number " + magic[7] + " != " + MetaData.joramMagic[7];
logger.log(BasicLevel.ERROR, errorMsg);
protocolErrorCount++;
throw new IllegalAccessException(errorMsg);
}
logger.log(BasicLevel.WARN,
"Wildcard protocol version number: from stream = " + magic[7] + ", from MetaData = " + MetaData.joramMagic[7]);
}
long dt = Math.abs(StreamUtil.readLongFrom(is) - System.currentTimeMillis());
if (dt > clockSynchroThreshold)
logger.log(BasicLevel.WARN, " -> bad clock synchronization between client and server: " + dt);
StreamUtil.writeTo(dt, nos);
Identity identity = Identity.read(is);
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, " -> read identity = " + identity);
int key = StreamUtil.readIntFrom(is);
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, " -> read key = " + key);
int heartBeat = 0;
if (key == -1) {
heartBeat = StreamUtil.readIntFrom(is);
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, " -> read heartBeat = " + heartBeat);
}
GetProxyIdNot gpin = new GetProxyIdNot(identity, inaddr);
AgentId proxyId;
try {
gpin.invoke(AdminTopic.getDefault());
proxyId = gpin.getProxyId();
} catch (Exception exc) {
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, "", exc);
failedLoginCount++;
StreamUtil.writeTo(1, nos);
StreamUtil.writeTo(exc.getMessage(), nos);
nos.send();
return;
}
IOControl ioctrl;
ReliableConnectionContext ctx;
if (key == -1) {
OpenConnectionNot ocn = new OpenConnectionNot(true, heartBeat);
ocn.invoke(proxyId);
StreamUtil.writeTo(0, nos);
ctx = (ReliableConnectionContext) ocn.getConnectionContext();
key = ctx.getKey();
StreamUtil.writeTo(key, nos);
nos.send();
ioctrl = new IOControl(sock);
} else {
GetConnectionNot gcn = new GetConnectionNot(key);
try {
gcn.invoke(proxyId);
} catch (Exception exc) {
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, "", exc);
StreamUtil.writeTo(1, nos);
StreamUtil.writeTo(exc.getMessage(), nos);
nos.send();
return;
}
ctx = (ReliableConnectionContext) gcn.getConnectionContext();
StreamUtil.writeTo(0, nos);
nos.send();
ioctrl = new IOControl(sock, ctx.getInputCounter());
TcpConnection tcpConnection = proxyService.getConnection(proxyId, key);
if (tcpConnection != null) {
tcpConnection.close();
}
}
// Reset the timeout in order to enable the server to indefinitely
// wait for requests.
sock.setSoTimeout(0);
TcpConnection tcpConnection = new TcpConnection(ioctrl, ctx, proxyId, proxyService, identity);
tcpConnection.start();
} catch (IllegalAccessException exc) {
if (logger.isLoggable(BasicLevel.ERROR))
logger.log(BasicLevel.ERROR, "", exc);
sock.close();
throw exc;
} catch (IOException exc) {
if (logger.isLoggable(BasicLevel.DEBUG))
logger.log(BasicLevel.DEBUG, "", exc);
sock.close();
throw exc;
}
}