Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
import com.cloudbees.syslog.util.CachingReference;
import com.cloudbees.syslog.util.IoUtils;

import com.cloudbees.syslog.sender.proxy.ProxyConfig;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
Expand Down Expand Up @@ -70,6 +73,13 @@ public class TcpSyslogMessageSender extends AbstractSyslogMessageSender implemen
private int socketConnectTimeoutInMillis = SETTING_SOCKET_CONNECT_TIMEOUT_IN_MILLIS_DEFAULT_VALUE;
private boolean ssl;
private SSLContext sslContext;
private ProxyConfig proxyConfig;
/**
* If the last connection was via a proxy server this will contain the
* InetAddress of the syslog server that was connected to via the proxy.
*/
private InetAddress proxyConnectedSyslogServer;

/**
* Number of retries to send a message before throwing an exception.
*/
Expand Down Expand Up @@ -122,9 +132,36 @@ public synchronized void sendMessage(@Nonnull SyslogMessage message) throws IOEx
}
}

/**
* @return true if not proxy connected and the socket is connected to current configured syslog
*/
private boolean notProxyConnectedAddressChange(final InetAddress inetAddress) {
return proxyConnectedSyslogServer == null && !Objects.equals(socket.getInetAddress(), inetAddress);
}

/**
* @return true if currentProxyConfig status does not match proxyConnectedSyslogServer
*/
private boolean proxyUseHasChanged(final ProxyConfig currentProxyConfig) {
return (currentProxyConfig != null && proxyConnectedSyslogServer == null)
|| (currentProxyConfig == null && proxyConnectedSyslogServer != null);
}

/**
* @return true if proxy connected and either proxy connection or syslog server connection have changed
*/
private boolean proxyConnectedAddressChange(final InetAddress syslogServer, final ProxyConfig currentProxyConfig) {
return proxyConnectedSyslogServer != null && (!Objects.equals(syslogServer, proxyConnectedSyslogServer)
|| !Objects.equals(socket.getInetAddress(), currentProxyConfig.getHostnameReference().get()));
}

private synchronized void ensureSyslogServerConnection() throws IOException {
InetAddress inetAddress = syslogServerHostnameReference.get();
if (socket != null && !Objects.equals(socket.getInetAddress(), inetAddress)) {
final ProxyConfig currentProxyConfig = this.proxyConfig;
if (socket != null && (
notProxyConnectedAddressChange(inetAddress)
|| proxyUseHasChanged(currentProxyConfig)
|| proxyConnectedAddressChange(inetAddress, currentProxyConfig))) {
logger.info("InetAddress of the Syslog Server have changed, create a new connection. " +
"Before=" + socket.getInetAddress() + ", new=" + inetAddress);
IoUtils.closeQuietly(socket, writer);
Expand All @@ -145,19 +182,44 @@ private synchronized void ensureSyslogServerConnection() throws IOException {
if (!socketIsValid) {
writer = null;
try {
if (ssl) {
final SocketFactory socketFactory;
if (ssl) {
if (sslContext == null) {
socket = SSLSocketFactory.getDefault().createSocket();
socketFactory = SSLSocketFactory.getDefault();
} else {
socket = sslContext.getSocketFactory().createSocket();
socketFactory = sslContext.getSocketFactory();
}
} else {
socket = SocketFactory.getDefault().createSocket();
socketFactory = SocketFactory.getDefault();
}
socket.setKeepAlive(true);
socket.connect(
new InetSocketAddress(inetAddress, syslogServerPort),
socketConnectTimeoutInMillis);

final InetSocketAddress syslogServer = new InetSocketAddress(inetAddress, syslogServerPort);

if(currentProxyConfig == null) {
socket = socketFactory.createSocket();
socket.setKeepAlive(true);
socket.connect(
syslogServer,
socketConnectTimeoutInMillis);
proxyConnectedSyslogServer = null;
}else {
final InetSocketAddress proxyAddr = new InetSocketAddress(currentProxyConfig.getHostnameReference().get(), currentProxyConfig.getPort());
final Socket underlying = new Socket(new Proxy(Proxy.Type.HTTP, proxyAddr));
underlying.setKeepAlive(true);
underlying.connect(syslogServer);
socket = ((SSLSocketFactory)socketFactory).createSocket(
underlying,
syslogServer.getHostName(),
syslogServer.getPort(),
true);
socket.setKeepAlive(true);
final SSLSocket sslSocket = (SSLSocket) socket;
final SSLParameters sslParams = new SSLParameters();
sslParams.setEndpointIdentificationAlgorithm("HTTPS");
sslSocket.setSSLParameters(sslParams);
proxyConnectedSyslogServer = inetAddress;
}


if (socket instanceof SSLSocket && logger.isLoggable(Level.FINER)) {
try {
Expand Down Expand Up @@ -241,7 +303,15 @@ public synchronized SSLContext getSSLContext() {
return this.sslContext;
}

public int getSocketConnectTimeoutInMillis() {
public ProxyConfig getProxyConfig() {
return proxyConfig;
}

public void setProxyConfig(ProxyConfig proxyConfig) {
this.proxyConfig = proxyConfig;
}

public int getSocketConnectTimeoutInMillis() {
return socketConnectTimeoutInMillis;
}

Expand Down Expand Up @@ -287,6 +357,7 @@ public String toString() {

@Override
public void close() throws IOException {
this.socket.close();
if(this.socket != null)
this.socket.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public String toString() {

@Override
public void close() throws IOException {
this.datagramSocket.close();
if(this.datagramSocket != null)
this.datagramSocket.close();
}
}
46 changes: 46 additions & 0 deletions src/main/java/com/cloudbees/syslog/sender/proxy/ProxyConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.cloudbees.syslog.sender.proxy;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.annotation.Nullable;

import com.cloudbees.syslog.sender.SyslogMessageSender;
import com.cloudbees.syslog.util.CachingReference;

public class ProxyConfig {

private final int port;
private final String hostname;
private final CachingReference<InetAddress> hostnameReference;

public ProxyConfig (final int port, final String hostname) {
this.port = port;
this.hostname = hostname;
this.hostnameReference = new CachingReference<InetAddress>(SyslogMessageSender.DEFAULT_INET_ADDRESS_TTL_IN_NANOS) {
@Nullable
@Override
protected InetAddress newObject() {
try {
return InetAddress.getByName(hostname);
} catch (UnknownHostException e) {
throw new IllegalStateException(e);
}
}
};
}

public int getPort() {
return port;
}

public String getHostname() {
return hostname;
}

public CachingReference<InetAddress> getHostnameReference() {
return hostnameReference;
}


}