diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/gui/MessageBean.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/gui/MessageBean.java
index 053bed57d98acf7a1a348a4a3b8f26070b89e839..8560473281dd005668fd33a117071c143fb38f2d 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/gui/MessageBean.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/gui/MessageBean.java
@@ -30,6 +30,7 @@ import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.PartSource;
 import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.log4j.Logger;
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Name;
@@ -42,6 +43,8 @@ import org.jboss.seam.international.StatusMessage;
 @Scope(ScopeType.PAGE)
 public class MessageBean {
 
+	private static final Logger log = Logger.getLogger(MessageBean.class);
+
 	@In
 	private EntityManager entityManager;
 
@@ -227,7 +230,6 @@ public class MessageBean {
 			e.printStackTrace();
 		}
 		// redirect the user to the good page
-		boolean fail = false;
 		if (status == HttpStatus.SC_OK) {
 			try {
 				String key = filePost.getResponseBodyAsString();
@@ -238,11 +240,8 @@ public class MessageBean {
 
 				response.sendRedirect(url);
 			} catch (IOException e) {
-				fail = true;
-				e.printStackTrace();
+				log.error(e);
 			}
-		} else {
-			fail = true;
 		}
 	}
 }
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/HL7EventListener.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/HL7EventListener.java
index 305812993b560e9e5c19f7064ef2f4b9f06f854b..4e2a1f2988de4718edadae4ab6b97ab1727c5dce 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/HL7EventListener.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/HL7EventListener.java
@@ -17,7 +17,7 @@ public class HL7EventListener extends SameEventListener<String> {
 					requestChannelId, responseChannelId, side);
 			hl7message.setMessageReceivedAsString(message);
 
-			messageListener.processMessageSimple(hl7message);
+			messageListener.processMessage(hl7message);
 		}
 	}
 }
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListener.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListener.java
index 9ddb816203527fc6c8ce539caa6e1468d44757aa..328ccafa225d4e6e5fca00408d08c854e7751b88 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListener.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListener.java
@@ -6,7 +6,7 @@ import net.ihe.gazelle.proxy.model.message.AbstractMessage;
 
 public interface MessageListener {
 
-	void processMessageSimple(AbstractMessage abstractMessage);
+	void processMessage(AbstractMessage abstractMessage);
 
 	EntityManager getEntityManager();
 
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListenerSaveAbstract.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListenerSaveAbstract.java
index 42d4ad1e580474eda3e5411eb032bee054fcd5a7..88f2f4947edba65205d0e821e14fc47bde76167a 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListenerSaveAbstract.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/MessageListenerSaveAbstract.java
@@ -6,8 +6,6 @@ import net.ihe.gazelle.proxy.model.message.AbstractMessage;
 
 public abstract class MessageListenerSaveAbstract implements MessageListener {
 
-	private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(MessageListenerSaveAbstract.class);
-
 	@Override
 	public void processMessage(EntityManager em, AbstractMessage abstractMessage) {
 		if (abstractMessage.getId() == null) {
@@ -18,38 +16,10 @@ public abstract class MessageListenerSaveAbstract implements MessageListener {
 	}
 
 	@Override
-	public void processMessageSimple(AbstractMessage abstractMessage) {
+	public void processMessage(AbstractMessage abstractMessage) {
 		EntityManager em = getEntityManager();
 		processMessage(em, abstractMessage);
 		releaseEntityManager(em);
 	}
-	/*
-		public void processMessage(EntityManager em, AbstractMessage abstractMessage) {
-			if (em == null || abstractMessage == null) {
-				log.fatal("entityManager null or abstractMessage null");
-				return null;
-			}
-			AbstractMessage messageToReturn = null;
-			synchronized (em) {
-
-				boolean transactionWasActive = false;
-
-				EntityTransaction transaction = em.getTransaction();
-				synchronized (transaction) {
-					if (!transaction.isActive()) {
-						transaction.begin();
-					} else
-						transactionWasActive = true;
 
-					em.persist(abstractMessage);
-					messageToReturn = em.merge(abstractMessage);
-
-					if (!transactionWasActive) {
-						transaction.commit();
-					}
-				}
-			}
-			return messageToReturn;
-		}
-	*/
 }
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/RawEventListener.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/RawEventListener.java
index 8cf79ee776fd58efd7e1821fe93bb485bc6aa6a1..16aaad566db2868be140356136d1760522d5c206 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/RawEventListener.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/RawEventListener.java
@@ -17,7 +17,7 @@ public class RawEventListener extends SameEventListener<byte[]> {
 					requestChannelId, responseChannelId, side);
 			rawmessage.setMessageReceived(message);
 
-			messageListener.processMessageSimple(rawmessage);
+			messageListener.processMessage(rawmessage);
 		}
 	}
 
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/SyslogEventListener.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/SyslogEventListener.java
index 6ec184548075ac31e74d438e30ccedda75c3fc9e..8953d8555c1ffcc0fffc7684bbd44f537cc891eb 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/SyslogEventListener.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/listeners/SyslogEventListener.java
@@ -1,23 +1,35 @@
 package net.ihe.gazelle.proxy.listeners;
 
+import net.ihe.gazelle.proxy.model.message.RawMessage;
 import net.ihe.gazelle.proxy.model.message.SyslogMessage;
 import net.ihe.gazelle.proxy.netty.channel.ProxySide;
+import net.ihe.gazelle.proxy.netty.protocols.syslog.SyslogData;
 
-public class SyslogEventListener extends SameEventListener<String> {
+public class SyslogEventListener extends GazelleProxyEventListener<SyslogData, byte[]> {
 
 	public SyslogEventListener(MessageListener messageListener) {
 		super(messageListener);
 	}
 
-	protected void saveMessage(String message, String requesterIp, int requesterPort, int proxyPort,
-			String responderIp, int responderPort, int requestChannelId, int responseChannelId, ProxySide side) {
-		// Messages are coming from different threads!
+	@Override
+	public void onRequest(SyslogData request, String requesterIp, int requesterPort, int proxyProviderPort,
+			String responderIp, int responderPort, int providerChannelId, int consumerChannelId) {
 		synchronized (this) {
-			SyslogMessage syslogMessage = new SyslogMessage(requesterIp, requesterPort, proxyPort, responderIp,
-					responderPort, requestChannelId, responseChannelId, side);
-			syslogMessage.setMessageReceivedAsString(message);
-			messageListener.processMessageSimple(syslogMessage);
+			SyslogMessage syslogMessage = new SyslogMessage(requesterIp, requesterPort, proxyProviderPort, responderIp,
+					responderPort, providerChannelId, consumerChannelId, request);
+			messageListener.processMessage(syslogMessage);
 		}
 	}
 
+	@Override
+	public void onResponse(byte[] response, String requesterIp, int requesterPort, int proxyProviderPort,
+			String responderIp, int responderPort, int providerChannelId, int consumerChannelId) {
+		// Messages are coming from different threads!
+		synchronized (this) {
+			RawMessage rawmessage = new RawMessage(requesterIp, requesterPort, proxyProviderPort, responderIp,
+					responderPort, providerChannelId, consumerChannelId, ProxySide.RESPONSE);
+			rawmessage.setMessageReceived(response);
+			messageListener.processMessage(rawmessage);
+		}
+	}
 }
diff --git a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/model/message/SyslogMessage.java b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/model/message/SyslogMessage.java
index d2766ff263d205c71877e969f78db7b726c5f6c1..069b5bbea027be22b34cd27c58a88f90425ad620 100644
--- a/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/model/message/SyslogMessage.java
+++ b/gazelle-proxy-jar/src/main/java/net/ihe/gazelle/proxy/model/message/SyslogMessage.java
@@ -19,6 +19,7 @@ import javax.persistence.Entity;
 
 import net.ihe.gazelle.proxy.netty.ChannelType;
 import net.ihe.gazelle.proxy.netty.channel.ProxySide;
+import net.ihe.gazelle.proxy.netty.protocols.syslog.SyslogData;
 
 import org.jboss.seam.annotations.Name;
 
@@ -28,17 +29,107 @@ public class SyslogMessage extends AbstractMessage implements java.io.Serializab
 
 	private static final long serialVersionUID = -2767782636271713844L;
 
+	private Integer facility;
+
+	private String hostName;
+
+	private Integer severity;
+
+	private String timestamp;
+
+	private String tag;
+
+	private String appName;
+
+	private String messageId;
+
+	private String procId;
+
 	public SyslogMessage() {
 		super();
+		setProxySide(ProxySide.REQUEST);
 	}
 
 	public SyslogMessage(String fromIP, Integer localPort, Integer proxyPort, String toIP, Integer remotePort,
-			Integer requestChannelId, Integer responseChannelId, ProxySide proxySide) {
-		super(fromIP, localPort, proxyPort, toIP, remotePort, requestChannelId, responseChannelId, proxySide);
+			Integer requestChannelId, Integer responseChannelId, SyslogData request) {
+		super(fromIP, localPort, proxyPort, toIP, remotePort, requestChannelId, responseChannelId, ProxySide.REQUEST);
+		this.facility = request.getFacility();
+		this.hostName = request.getHostName();
+		this.severity = request.getSeverity();
+		this.timestamp = request.getTimestamp();
+		this.tag = request.getTag();
+		this.appName = request.getAppName();
+		this.messageId = request.getMessageId();
+		this.procId = request.getProcId();
+		setMessageReceivedAsString(request.getMessage());
 	}
 
 	public ChannelType getChannelType() {
 		return ChannelType.SYSLOG;
 	}
 
+	public Integer getFacility() {
+		return facility;
+	}
+
+	public void setFacility(Integer facility) {
+		this.facility = facility;
+	}
+
+	public String getHostName() {
+		return hostName;
+	}
+
+	public void setHostName(String hostName) {
+		this.hostName = hostName;
+	}
+
+	public Integer getSeverity() {
+		return severity;
+	}
+
+	public void setSeverity(Integer severity) {
+		this.severity = severity;
+	}
+
+	public String getTimestamp() {
+		return timestamp;
+	}
+
+	public void setTimestamp(String timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public String getTag() {
+		return tag;
+	}
+
+	public void setTag(String tag) {
+		this.tag = tag;
+	}
+
+	public String getAppName() {
+		return appName;
+	}
+
+	public void setAppName(String appName) {
+		this.appName = appName;
+	}
+
+	public String getMessageId() {
+		return messageId;
+	}
+
+	public void setMessageId(String messageId) {
+		this.messageId = messageId;
+	}
+
+	public String getProcId() {
+		return procId;
+	}
+
+	public void setProcId(String procId) {
+		this.procId = procId;
+	}
+
 }
diff --git a/gazelle-proxy-netty/pom.xml b/gazelle-proxy-netty/pom.xml
index 11fabe65d026abfcf33b9a21069f93640a212f76..d3fbc91e64f8fc4f6434edc8bdb1f7ee577ae39f 100644
--- a/gazelle-proxy-netty/pom.xml
+++ b/gazelle-proxy-netty/pom.xml
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
 	<parent>
 		<groupId>net.ihe.gazelle.proxy</groupId>
@@ -37,6 +38,17 @@
 			<artifactId>ihej-dicom</artifactId>
 			<version>1.0</version>
 		</dependency>
+		<dependency>
+			<groupId>org.openhealthtools.openatna</groupId>
+			<artifactId>syslog-core</artifactId>
+			<version>1.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.openhealthtools.openatna</groupId>
+			<artifactId>syslog-mina</artifactId>
+			<version>1.2</version>
+			<scope>test</scope>
+		</dependency>
 		<dependency>
 			<groupId>apache-log4j</groupId>
 			<artifactId>log4j</artifactId>
diff --git a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/raw/RawEventListenerSimple.java b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/raw/RawEventListenerSimple.java
new file mode 100644
index 0000000000000000000000000000000000000000..773cf5390e89bb4e0b76dfee05efbba9b3b7a8b8
--- /dev/null
+++ b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/raw/RawEventListenerSimple.java
@@ -0,0 +1,23 @@
+package net.ihe.gazelle.proxy.netty.protocols.raw;
+
+import java.io.PrintStream;
+
+import net.ihe.gazelle.proxy.netty.ProxyEventListenerToStream;
+
+public class RawEventListenerSimple extends ProxyEventListenerToStream<byte[], byte[]> {
+
+	public RawEventListenerSimple(PrintStream printStream) {
+		super(printStream);
+	}
+
+	@Override
+	protected String decodeResponse(byte[] response) {
+		return new String(response);
+	}
+
+	@Override
+	protected String decodeRequest(byte[] request) {
+		return new String(request);
+	}
+
+}
diff --git a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogData.java b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogData.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6392f39c191604a56ebabf465fc194dae3d73ce
--- /dev/null
+++ b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogData.java
@@ -0,0 +1,127 @@
+package net.ihe.gazelle.proxy.netty.protocols.syslog;
+
+import java.io.ByteArrayOutputStream;
+
+import org.openhealthtools.openatna.syslog.LogMessage;
+import org.openhealthtools.openatna.syslog.SyslogException;
+import org.openhealthtools.openatna.syslog.SyslogMessage;
+import org.openhealthtools.openatna.syslog.bsd.BsdMessage;
+import org.openhealthtools.openatna.syslog.protocol.ProtocolMessage;
+
+public class SyslogData {
+
+	private int facility;
+	private String hostName;
+	private int severity;
+	private String timestamp;
+	private String message;
+	private String tag;
+	private String appName;
+	private String messageId;
+	private String procId;
+
+	public SyslogData(SyslogMessage<?> syslogMessage) {
+		super();
+
+		facility = syslogMessage.getFacility();
+		hostName = syslogMessage.getHostName();
+		severity = syslogMessage.getSeverity();
+		timestamp = syslogMessage.getTimestamp();
+
+		LogMessage<?> logMessage = syslogMessage.getMessage();
+		message = null;
+		if (logMessage != null) {
+			Object messageObject = logMessage.getMessageObject();
+
+			if (messageObject instanceof String) {
+				message = (String) messageObject;
+			} else {
+				ByteArrayOutputStream bos = new ByteArrayOutputStream();
+				try {
+					logMessage.write(bos);
+					message = new String(bos.toByteArray());
+				} catch (SyslogException e) {
+					message = null;
+				}
+			}
+		}
+		tag = null;
+		if (syslogMessage instanceof BsdMessage) {
+			BsdMessage<?> bsdMessage = (BsdMessage<?>) syslogMessage;
+			tag = bsdMessage.getTag();
+		}
+
+		appName = null;
+		messageId = null;
+		procId = null;
+		if (syslogMessage instanceof ProtocolMessage) {
+			ProtocolMessage<?> protocolMessage = (ProtocolMessage<?>) syslogMessage;
+			appName = protocolMessage.getAppName();
+			messageId = protocolMessage.getMessageId();
+			procId = protocolMessage.getProcId();
+		}
+
+	}
+
+	public int getFacility() {
+		return facility;
+	}
+
+	public String getHostName() {
+		return hostName;
+	}
+
+	public int getSeverity() {
+		return severity;
+	}
+
+	public String getTimestamp() {
+		return timestamp;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public String getTag() {
+		return tag;
+	}
+
+	public String getAppName() {
+		return appName;
+	}
+
+	public String getMessageId() {
+		return messageId;
+	}
+
+	public String getProcId() {
+		return procId;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("SyslogData [facility=");
+		builder.append(facility);
+		builder.append(", hostName=");
+		builder.append(hostName);
+		builder.append(", severity=");
+		builder.append(severity);
+		builder.append(", timestamp=");
+		builder.append(timestamp);
+		builder.append(", message=");
+		builder.append(message);
+		builder.append(", tag=");
+		builder.append(tag);
+		builder.append(", appName=");
+		builder.append(appName);
+		builder.append(", messageId=");
+		builder.append(messageId);
+		builder.append(", procId=");
+		builder.append(procId);
+		builder.append("]");
+		return builder.toString();
+	}
+
+}
diff --git a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogFrameDecoder.java b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogFrameDecoder.java
new file mode 100644
index 0000000000000000000000000000000000000000..d952089d5cbf0f965ad87006f2ca8beafe450684
--- /dev/null
+++ b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogFrameDecoder.java
@@ -0,0 +1,57 @@
+package net.ihe.gazelle.proxy.netty.protocols.syslog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+import org.openhealthtools.openatna.syslog.SyslogMessage;
+import org.openhealthtools.openatna.syslog.SyslogMessageFactory;
+
+class SyslogFrameDecoder extends FrameDecoder {
+
+	private static final int STATUS_SIZE = 0;
+	private static final int STATUS_READ = 1;
+	private static final int STATUS_END = 2;
+
+	private int status = STATUS_SIZE;
+	private StringBuffer messageSizeBuffer = new StringBuffer();
+	private int messageSize;
+	private ByteArrayOutputStream currentFrame = null;
+
+	@Override
+	protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
+		while (buffer.readableBytes() > 0) {
+			byte readByte = buffer.readByte();
+			switch (status) {
+			case STATUS_SIZE:
+				if (readByte == 32) {
+					status = STATUS_READ;
+					messageSize = Integer.parseInt(messageSizeBuffer.toString());
+					currentFrame = new ByteArrayOutputStream();
+				} else {
+					char c = (char) readByte;
+					messageSizeBuffer.append(c);
+				}
+				break;
+			case STATUS_READ:
+				if (currentFrame.size() == messageSize) {
+					status = STATUS_END;
+					byte[] bytes = currentFrame.toByteArray();
+					SyslogMessage<?> syslogMessage = SyslogMessageFactory.getFactory().read(
+							new ByteArrayInputStream(bytes));
+					return new SyslogData(syslogMessage);
+				}
+				currentFrame.write(readByte);
+				break;
+			case STATUS_END:
+				return null;
+			default:
+				break;
+			}
+		}
+		return null;
+	}
+}
diff --git a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogProxy.java b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogProxy.java
index 72aac403fb62916b442a8ce5969b1069123bedcd..efca84684c81548d3d5f9c3982d644e1bb941595 100644
--- a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogProxy.java
+++ b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/protocols/syslog/SyslogProxy.java
@@ -6,16 +6,14 @@ import java.util.List;
 import net.ihe.gazelle.proxy.netty.ConnectionConfig;
 import net.ihe.gazelle.proxy.netty.Proxy;
 import net.ihe.gazelle.proxy.netty.ProxyEventListener;
+import net.ihe.gazelle.proxy.netty.channel.ProxyTools;
 
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
 import org.jboss.netty.channel.ChannelHandler;
-import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
-import org.jboss.netty.util.CharsetUtil;
 
-public class SyslogProxy extends Proxy<String, String> {
+public class SyslogProxy extends Proxy<SyslogData, byte[]> {
 
-	public SyslogProxy(ProxyEventListener<String, String> proxyEventListener, ConnectionConfig connectionConfig) {
+	public SyslogProxy(ProxyEventListener<SyslogData, byte[]> proxyEventListener, ConnectionConfig connectionConfig) {
 		super(proxyEventListener, connectionConfig);
 	}
 
@@ -23,32 +21,31 @@ public class SyslogProxy extends Proxy<String, String> {
 		List<ChannelHandler> channels = new ArrayList<ChannelHandler>();
 
 		// Decode syslog messages
-		channels.add(new DelimiterBasedFrameDecoder(1024 * 1024, getSyslogDelimiter()));
+		channels.add(new SyslogFrameDecoder());
 
 		return channels;
 	}
 
-	public static ChannelBuffer[] getSyslogDelimiter() {
-		return new ChannelBuffer[] { ChannelBuffers.wrappedBuffer("auditmessage".getBytes(CharsetUtil.UTF_8)) };
-	}
-
 	public List<ChannelHandler> getDecodersForResponse() {
-		return getDecodersForRequest();
+		return new ArrayList<ChannelHandler>();
 	}
 
 	@Override
-	public String handleRequest(Object message) {
-		if (message instanceof ChannelBuffer) {
-			ChannelBuffer cb = (ChannelBuffer) message;
-			String result = cb.toString(CharsetUtil.UTF_8);
-			return result;
+	public SyslogData handleRequest(Object message) {
+		if (message instanceof SyslogData) {
+			SyslogData syslogData = (SyslogData) message;
+			return syslogData;
 		}
 		return null;
 	}
 
 	@Override
-	public String handleResponse(Object message) {
-		return handleRequest(message);
+	public byte[] handleResponse(Object message) {
+		if (message instanceof ChannelBuffer) {
+			ChannelBuffer cb = (ChannelBuffer) message;
+			return ProxyTools.getBytes(cb);
+		}
+		return null;
 	}
 
 }
diff --git a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/tools/SyslogEventListenerSimple.java b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/tools/SyslogEventListenerSimple.java
index 2f8e528e465693dda153149854aaff17ea281d96..8db74ac28172c7342f407a5d412e2a7f07cff1b9 100644
--- a/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/tools/SyslogEventListenerSimple.java
+++ b/gazelle-proxy-netty/src/main/java/net/ihe/gazelle/proxy/netty/tools/SyslogEventListenerSimple.java
@@ -3,21 +3,22 @@ package net.ihe.gazelle.proxy.netty.tools;
 import java.io.PrintStream;
 
 import net.ihe.gazelle.proxy.netty.ProxyEventListenerToStream;
+import net.ihe.gazelle.proxy.netty.protocols.syslog.SyslogData;
 
-public class SyslogEventListenerSimple extends ProxyEventListenerToStream<String, String> {
+public class SyslogEventListenerSimple extends ProxyEventListenerToStream<SyslogData, byte[]> {
 
 	public SyslogEventListenerSimple(PrintStream printStream) {
 		super(printStream);
 	}
 
 	@Override
-	protected String decodeResponse(String response) {
-		return response;
+	protected String decodeRequest(SyslogData request) {
+		return request.toString();
 	}
 
 	@Override
-	protected String decodeRequest(String request) {
-		return request;
+	protected String decodeResponse(byte[] request) {
+		return new String(request);
 	}
 
 }
diff --git a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/App.java b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/App.java
index 3649b19dde7b3d4ea12a008d5ff96565f21eb297..4eb227a8670cb15bb6feb455b74916f0a8d5722c 100644
--- a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/App.java
+++ b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/App.java
@@ -1,6 +1,12 @@
 package net.ihe.gazelle.proxy.netty;
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 
 import jp.digitalsensation.ihej.transactionmonitor.dicom.messageexchange.DimseMessage;
 import net.ihe.gazelle.proxy.netty.basictls.ConnectionConfigSimpleTls;
@@ -8,14 +14,29 @@ import net.ihe.gazelle.proxy.netty.basictls.TlsConfig;
 import net.ihe.gazelle.proxy.netty.basictls.TlsCredentials;
 import net.ihe.gazelle.proxy.netty.protocols.dicom.DicomProxy;
 import net.ihe.gazelle.proxy.netty.protocols.http.HttpProxy;
+import net.ihe.gazelle.proxy.netty.protocols.raw.RawEventListenerSimple;
+import net.ihe.gazelle.proxy.netty.protocols.raw.RawProxy;
+import net.ihe.gazelle.proxy.netty.syslog.AuthSSLSocketFactory;
+import net.ihe.gazelle.proxy.netty.syslog.KeystoreDetails;
 import net.ihe.gazelle.proxy.netty.tools.DicomEventListenerSimple;
 import net.ihe.gazelle.proxy.netty.tools.HttpEventListenerSimple;
 
+import org.openhealthtools.openatna.syslog.Constants;
+import org.openhealthtools.openatna.syslog.SyslogException;
+import org.openhealthtools.openatna.syslog.SyslogMessage;
+import org.openhealthtools.openatna.syslog.message.StringLogMessage;
+import org.openhealthtools.openatna.syslog.mina.tls.TlsServer;
+import org.openhealthtools.openatna.syslog.protocol.ProtocolMessage;
+import org.openhealthtools.openatna.syslog.protocol.SdParam;
+import org.openhealthtools.openatna.syslog.protocol.StructuredElement;
+import org.openhealthtools.openatna.syslog.transport.SyslogListener;
+
 public class App {
 	public static void main(String[] args) throws Exception {
 		// testHttpsConnection();
 
-		startDicomProxyTLS(10004);
+		// startDicomProxyTLS(10004);
+		startSyslogProxyTLS();
 
 		/*
 		startHTTPProxyBasic(10000);
@@ -45,11 +66,103 @@ public class App {
 
 	}
 
+	private static void startSyslogProxyTLS() {
+		// Syslog Client -TLS> Proxy1 -> Proxy Web app -> Proxy3 -TLS> Syslog
+		// Server
+
+		// Starts a Syslog server (8443)
+		try {
+			AuthSSLSocketFactory serverSocketFactory = getSyslogServerSocketFactory();
+			org.openhealthtools.openatna.syslog.mina.tls.TlsConfig serverConfig = new org.openhealthtools.openatna.syslog.mina.tls.TlsConfig();
+			serverConfig.setSSLContext(serverSocketFactory.getSSLContext());
+			serverConfig.setHost("localhost");
+			serverConfig.setPort(8443);
+			TlsServer server = new TlsServer();
+			server.configure(serverConfig);
+			server.addSyslogListener(new Listener());
+			server.start();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		RawEventListenerSimple listener = new RawEventListenerSimple(System.out);
+
+		// Starts proxy3
+		InputStream clientKeyStoreStream = listener.getClass().getResourceAsStream("/keys/clientKeyStore");
+		TlsCredentials clientCredentials = new TlsCredentials(clientKeyStoreStream, "clientStorePass".toCharArray(),
+				"myClientCert", "password".toCharArray());
+		TlsConfig tlsConfigClient = new TlsConfig(null, true, clientCredentials);
+		ConnectionConfig connectionConfigClient = new ConnectionConfigSimpleTls(8442, "127.0.0.1", 8443,
+				ChannelType.SYSLOG, tlsConfigClient);
+		RawProxy proxy3 = new RawProxy(listener, connectionConfigClient);
+		proxy3.start();
+
+		// Starts proxy2
+		InputStream serverKeyStoreStream = listener.getClass().getResourceAsStream("/keys/serverKeyStore");
+		TlsCredentials serverCredentials = new TlsCredentials(serverKeyStoreStream, "serverStorePass".toCharArray(),
+				"myServerCert", "password".toCharArray());
+		TlsConfig tlsConfigServer = new TlsConfig(serverCredentials, false, null);
+		ConnectionConfig connectionConfigServer = new ConnectionConfigSimpleTls(9443, "127.0.0.1", 10000,
+				ChannelType.SYSLOG, tlsConfigServer);
+		RawProxy proxy1 = new RawProxy(listener, connectionConfigServer);
+		proxy1.start();
+
+		// Ping!
+		try {
+			AuthSSLSocketFactory clientSocketFactory = getSyslogClientSocketFactory();
+
+			ProtocolMessage sl = new ProtocolMessage(10, 5, "2009-08-14T14:12:23.115Z", "localhost",
+					new StringLogMessage("<atna></atna>"), "IHE_XDS", "ATNALOG", "1234");
+			List<SdParam> params = new ArrayList<SdParam>();
+			params.add(new SdParam("param1", "param value\\=1"));
+			params.add(new SdParam("param2", "param value] 2"));
+			params.add(new SdParam("param3", "param value 3"));
+			params.add(new SdParam("param3", "param value 4"));
+			StructuredElement se = new StructuredElement("exampleSDID@1234", params);
+			sl.addStructuredElement(se);
+
+			Socket s = clientSocketFactory.createSecureSocket("localhost", 9443);
+			OutputStream out = s.getOutputStream();
+			byte[] bytes = sl.toByteArray();
+			for (int i = 0; i < 5; i++) {
+				// add message length plus space before message
+				out.write((String.valueOf(bytes.length) + " ").getBytes(Constants.ENC_UTF8));
+				out.write(bytes);
+				out.flush();
+			}
+			out.close();
+			s.close();
+		} catch (SyslogException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	private static AuthSSLSocketFactory getSyslogServerSocketFactory() throws IOException {
+		URL u = Thread.currentThread().getContextClassLoader().getResource("keys/serverKeyStore");
+		KeystoreDetails key = new KeystoreDetails(u.toString(), "serverStorePass", "myServerCert", "password");
+		URL uu = Thread.currentThread().getContextClassLoader().getResource("keys/clientKeyStore");
+		KeystoreDetails trust = new KeystoreDetails(uu.toString(), "clientStorePass", "myClientCert");
+		AuthSSLSocketFactory f = new AuthSSLSocketFactory(key, trust);
+		return f;
+	}
+
+	private static AuthSSLSocketFactory getSyslogClientSocketFactory() throws IOException {
+		URL u = Thread.currentThread().getContextClassLoader().getResource("keys/serverKeyStore");
+		KeystoreDetails trust = new KeystoreDetails(u.toString(), "serverStorePass", "myServerCert");
+		URL uu = Thread.currentThread().getContextClassLoader().getResource("keys/clientKeyStore");
+		KeystoreDetails key = new KeystoreDetails(uu.toString(), "clientStorePass", "myClientCert", "password");
+		AuthSSLSocketFactory f = new AuthSSLSocketFactory(key, trust);
+		return f;
+	}
+
 	private static void startDicomProxyTLS(int port) {
 		final ProxyEventListener<DimseMessage, DimseMessage> dicomProxyEvent = new DicomEventListenerSimple(System.out);
 
-		TlsConfig tlsConfig = new TlsConfig(new TlsCredentials(getStream("/home/glandais/435.p12"), "password".toCharArray()), false,
-				null);
+		TlsConfig tlsConfig = new TlsConfig(new TlsCredentials(getStream("/home/glandais/435.p12"),
+				"password".toCharArray()), false, null);
 
 		ConnectionConfigSimpleTls connectionConfig = new ConnectionConfigSimpleTls(port, "kujira.irisa.fr", 10002,
 				ChannelType.DICOM, tlsConfig);
@@ -61,8 +174,8 @@ public class App {
 
 	private static void startHTTPProxyTLSServer(int port) {
 		HttpEventListenerSimple eventListener = new HttpEventListenerSimple(System.out);
-		TlsConfig tlsConfig = new TlsConfig(new TlsCredentials(getStream("/home/glandais/435.p12"), "password".toCharArray()), false,
-				null);
+		TlsConfig tlsConfig = new TlsConfig(new TlsCredentials(getStream("/home/glandais/435.p12"),
+				"password".toCharArray()), false, null);
 		HttpProxy httpProxy = new HttpProxy(eventListener, new ConnectionConfigSimpleTls(port, "www.google.fr", 80,
 				ChannelType.HTTP, tlsConfig));
 		httpProxy.start();
@@ -95,4 +208,18 @@ public class App {
 				ChannelType.HTTP));
 		httpProxy.start();
 	}
+
+	static class Listener implements SyslogListener {
+
+		public void messageArrived(SyslogMessage message) {
+			System.out.println("serialized message:");
+			System.out.println(message.toString());
+			System.out.println("application message:");
+			System.out.println(message.getMessage().getMessageObject());
+		}
+
+		public void exceptionThrown(SyslogException exception) {
+			exception.printStackTrace();
+		}
+	}
 }
diff --git a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLSocketFactory.java b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLSocketFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..01bd93207862383bbeda9920bf7fa54c26f056a8
--- /dev/null
+++ b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLSocketFactory.java
@@ -0,0 +1,257 @@
+/**
+ *  Copyright (c) 2009-2011 University of Cardiff and others
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  permissions and limitations under the License.
+ *
+ *  Contributors:
+ *    University of Cardiff - initial API and implementation
+ *    -
+ */
+
+package net.ihe.gazelle.proxy.netty.syslog;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.logging.Logger;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+
+/**
+ *
+ */
+public class AuthSSLSocketFactory {
+
+    static Logger log = Logger.getLogger("org.openhealthtools.openatna.syslog.test.tls.ssl.AuthSSLSocketFactory");
+
+    private KeystoreDetails details = null;
+    private KeystoreDetails truststore = null;
+
+    private SSLContext sslcontext = null;
+    private X509TrustManager defaultTrustManager = null;
+
+    public AuthSSLSocketFactory(KeystoreDetails details, KeystoreDetails truststore, X509TrustManager defaultTrustManager) throws IOException {
+        super();
+
+        if (details != null) {
+            this.details = details;
+        }
+        if (truststore != null) {
+            this.truststore = truststore;
+        }
+        if (defaultTrustManager == null) {
+            log.fine(" using sun default trust manager");
+            this.defaultTrustManager = KeystoreManager.getDefaultTrustManager();
+        } else {
+            this.defaultTrustManager = defaultTrustManager;
+        }
+    }
+
+    public AuthSSLSocketFactory(KeystoreDetails details, KeystoreDetails truststore) throws IOException {
+        this(details, truststore, null);
+    }
+
+    public AuthSSLSocketFactory(KeystoreDetails details, X509TrustManager defaultTrustManager) throws IOException {
+        this(details, null, defaultTrustManager);
+    }
+
+    public AuthSSLSocketFactory(KeystoreDetails details) throws IOException {
+        this(details, null, null);
+    }
+
+    private static KeyStore createKeyStore(KeystoreDetails details)
+            throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
+        if (details.getKeystoreLocation() == null) {
+            throw new IllegalArgumentException("Keystore location may not be null");
+        }
+
+        log.fine("Initializing key store");
+        KeyStore keystore = KeyStore.getInstance(details.getKeystoreType());
+        InputStream is = null;
+        try {
+            is = getKeystoreInputStream(details.getKeystoreLocation());
+            if (is == null) {
+                throw new IOException("Could not open stream to " + details.getKeystoreLocation());
+            }
+            String password = details.getKeystorePassword();
+            keystore.load(is, password != null ? password.toCharArray() : null);
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+        return keystore;
+    }
+
+    private static InputStream getKeystoreInputStream(String location) {
+        try {
+            File file = new File(location);
+            if (file.exists()) {
+                return new FileInputStream(file);
+            }
+        } catch (Exception e) {
+
+        }
+        try {
+            URL url = new URL(location);
+            return url.openStream();
+        } catch (Exception e) {
+
+        }
+        log.fine("could not open stream to:" + location);
+        return null;
+    }
+
+    private KeyManager[] createKeyManagers(final KeyStore keystore, KeystoreDetails details)
+            throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
+        if (keystore == null) {
+            throw new IllegalArgumentException("Keystore may not be null");
+        }
+        log.fine("Initializing key manager");
+        KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(details.getAlgType());
+        String password = details.getKeyPassword();
+        kmfactory.init(keystore, (password == null || password.length() == 0) ? details.getKeystorePassword().toCharArray() : password.toCharArray());
+        return kmfactory.getKeyManagers();
+
+    }
+
+    private TrustManager[] createTrustManagers(KeystoreDetails truststore, final KeyStore keystore, X509TrustManager defaultTrustManager)
+            throws KeyStoreException, NoSuchAlgorithmException {
+
+        if (keystore == null) {
+            throw new IllegalArgumentException("Keystore may not be null");
+        }
+        TrustManagerFactory tmfactory =
+                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());//TrustManagerFactory.getInstance(algorithm);
+        tmfactory.init(keystore);
+        TrustManager[] trustmanagers = tmfactory.getTrustManagers();
+        for (int i = 0; i < trustmanagers.length; i++) {
+
+            if (trustmanagers[i] instanceof X509TrustManager) {
+                return new TrustManager[]{
+                        new AuthSSLX509TrustManager((X509TrustManager) trustmanagers[i], defaultTrustManager, truststore.getAuthorizedDNs())};
+            }
+        }
+        return trustmanagers;
+    }
+
+    private SSLContext createSSLContext() throws IOException {
+        try {
+            KeyManager[] keymanagers = null;
+            TrustManager[] trustmanagers = null;
+            if (this.details != null) {
+                KeyStore keystore = createKeyStore(details);
+                Enumeration aliases = keystore.aliases();
+                while (aliases.hasMoreElements()) {
+                    String alias = (String) aliases.nextElement();
+                    Certificate[] certs = keystore.getCertificateChain(alias);
+                    if (certs != null) {
+                        log.fine("Certificate chain '" + alias + "':");
+                        for (int c = 0; c < certs.length; c++) {
+                            if (certs[c] instanceof X509Certificate) {
+                                X509Certificate cert = (X509Certificate) certs[c];
+                                log.fine(" Certificate " + (c + 1) + ":");
+                                log.fine("  Subject DN: " + cert.getSubjectDN());
+                                log.fine("  Signature Algorithm: " + cert.getSigAlgName());
+                                log.fine("  Valid from: " + cert.getNotBefore());
+                                log.fine("  Valid until: " + cert.getNotAfter());
+                                log.fine("  Issuer: " + cert.getIssuerDN());
+                            }
+                        }
+                    }
+
+                }
+                keymanagers = createKeyManagers(keystore, details);
+            }
+            if (this.truststore != null) {
+                KeyStore keystore = createKeyStore(truststore);
+                Enumeration aliases = keystore.aliases();
+                while (aliases.hasMoreElements()) {
+                    String alias = (String) aliases.nextElement();
+                    log.fine("Trusted certificate '" + alias + "':");
+                    Certificate trustedcert = keystore.getCertificate(alias);
+                    if (trustedcert != null && trustedcert instanceof X509Certificate) {
+                        X509Certificate cert = (X509Certificate) trustedcert;
+                        log.fine("  Subject DN: " + cert.getSubjectDN());
+                        log.fine("  Signature Algorithm: " + cert.getSigAlgName());
+                        log.fine("  Valid from: " + cert.getNotBefore());
+                        log.fine("  Valid until: " + cert.getNotAfter());
+                        log.fine("  Issuer: " + cert.getIssuerDN());
+                    }
+                }
+                trustmanagers = createTrustManagers(truststore, keystore, defaultTrustManager);
+            }
+            if (trustmanagers == null) {
+                log.fine(" created trustmanagers from the default...");
+                trustmanagers = new TrustManager[]{defaultTrustManager};
+            }
+
+            SSLContext sslcontext = SSLContext.getInstance("SSL");
+            sslcontext.init(keymanagers, trustmanagers, null);
+            return sslcontext;
+        } catch (NoSuchAlgorithmException e) {
+            log.warning(e.getMessage());
+            throw new IOException("Unsupported algorithm exception: " + e.getMessage());
+        } catch (KeyStoreException e) {
+            log.warning(e.getMessage());
+            throw new IOException("Keystore exception: " + e.getMessage());
+        } catch (GeneralSecurityException e) {
+            log.warning(e.getMessage());
+            throw new IOException("Key management exception: " + e.getMessage());
+        } catch (IOException e) {
+            log.warning(e.getMessage());
+            throw new IOException("I/O error reading keystore/truststore file: " + e.getMessage());
+        }
+    }
+
+    public SSLContext getSSLContext() throws IOException {
+        if (this.sslcontext == null) {
+            this.sslcontext = createSSLContext();
+        }
+        return this.sslcontext;
+    }
+
+    public Socket createSecureSocket(String host, int port) throws IOException {
+        return getSSLContext().getSocketFactory().createSocket(host, port);
+    }
+
+    public ServerSocket createServerSocket(int port) throws IOException {
+        return getSSLContext().getServerSocketFactory().createServerSocket(port);
+    }
+
+    public boolean isSecured() {
+        return true;
+    }
+
+
+}
\ No newline at end of file
diff --git a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLX509TrustManager.java b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLX509TrustManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..a10565691d3929427cd0d04133713b2689542cdc
--- /dev/null
+++ b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/AuthSSLX509TrustManager.java
@@ -0,0 +1,140 @@
+/**
+ *  Copyright (c) 2009-2011 University of Cardiff and others
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  permissions and limitations under the License.
+ *
+ *  Contributors:
+ *    University of Cardiff - initial API and implementation
+ *    -
+ */
+
+package net.ihe.gazelle.proxy.netty.syslog;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * <p>
+ * <p/>
+ * </p>
+ */
+
+public class AuthSSLX509TrustManager implements X509TrustManager {
+
+    private X509TrustManager trustManager = null;
+    private X509TrustManager defaultTrustManager = null;
+    List<String> authorizedDns = null;
+    /**
+     * Log object for this class.
+     */
+    static Logger log = Logger.getLogger("org.openhealthtools.openatna.syslog.test.tls.ssl.AuthSSLX509TrustManager");
+
+    /**
+     * Constructor for AuthSSLX509TrustManager.
+     */
+    public AuthSSLX509TrustManager(final X509TrustManager trustManager, final X509TrustManager defaultTrustManager, List<String> authorizedDns) {
+        super();
+        if (trustManager == null) {
+            throw new IllegalArgumentException("Trust manager may not be null");
+        }
+        this.trustManager = trustManager;
+        this.defaultTrustManager = defaultTrustManager;
+        this.authorizedDns = authorizedDns;
+        if (this.authorizedDns == null) {
+            this.authorizedDns = new ArrayList<String>();
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
+     */
+    public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        if (certificates != null) {
+            boolean isAuthDN = false;
+            if (authorizedDns.size() == 0) {
+                isAuthDN = true;
+            }
+            for (int c = 0; c < certificates.length; c++) {
+                X509Certificate cert = certificates[c];
+                if (isAuthDN == false) {
+                    for (String authorizedDn : authorizedDns) {
+                        if (authorizedDn.equals(cert.getSubjectDN())) {
+                            isAuthDN = true;
+                        }
+                    }
+                }
+                log.fine(" Client certificate " + (c + 1) + ":");
+                log.fine("  Subject DN: " + cert.getSubjectDN());
+                log.fine("  Signature Algorithm: " + cert.getSigAlgName());
+                log.fine("  Valid from: " + cert.getNotBefore());
+                log.fine("  Valid until: " + cert.getNotAfter());
+                log.fine("  Issuer: " + cert.getIssuerDN());
+            }
+            if (!isAuthDN) {
+                throw new CertificateException("Subject DN is not authorized to perform the requested action.");
+            }
+            trustManager.checkClientTrusted(certificates, authType);
+        }
+
+    }
+
+    /**
+     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
+     */
+    public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
+        if (certificates != null) {
+            for (int c = 0; c < certificates.length; c++) {
+                X509Certificate cert = certificates[c];
+                log.fine(" Server certificate " + (c + 1) + ":");
+                log.fine("  Subject DN: " + cert.getSubjectDN());
+                log.fine("  Signature Algorithm: " + cert.getSigAlgName());
+                log.fine("  Valid from: " + cert.getNotBefore());
+                log.fine("  Valid until: " + cert.getNotAfter());
+                log.fine("  Issuer: " + cert.getIssuerDN());
+            }
+        }
+
+        try {
+            if (defaultTrustManager != null) {
+                defaultTrustManager.checkServerTrusted(certificates, authType);
+            }
+        } catch (CertificateException e) {
+            trustManager.checkServerTrusted(certificates, authType);
+        }
+    }
+
+    /**
+     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
+     */
+    public X509Certificate[] getAcceptedIssuers() {
+        X509Certificate[] certs = this.trustManager.getAcceptedIssuers();
+
+        if (defaultTrustManager != null) {
+            X509Certificate[] suncerts = this.defaultTrustManager.getAcceptedIssuers();
+            X509Certificate[] all = new X509Certificate[certs.length + suncerts.length];
+            System.arraycopy(certs, 0, all, 0, certs.length);
+            System.arraycopy(suncerts, 0, all, certs.length, suncerts.length);
+            certs = all;
+        }
+        if (certs == null) {
+            certs = new X509Certificate[0];
+        }
+
+        return certs;
+    }
+}
\ No newline at end of file
diff --git a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreDetails.java b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreDetails.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0a14ce2e5e2c083f60bde9180da6662adeb0376
--- /dev/null
+++ b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreDetails.java
@@ -0,0 +1,138 @@
+/**
+ *  Copyright (c) 2009-2011 University of Cardiff and others
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  permissions and limitations under the License.
+ *
+ *  Contributors:
+ *    University of Cardiff - initial API and implementation
+ *    -
+ */
+
+package net.ihe.gazelle.proxy.netty.syslog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * interface for classes that can retrieve details required for signing a jar or authetication.
+ *
+ * @author Andrew Harrison
+ * @version $Revision: 72 $
+ * @created Mar 16, 2007: 3:13:50 PM
+ * @date $Date: 2007-03-23 09:52:50 +0000 (Fri, 23 Mar 2007) $ modified by $Author: scmabh $
+ * @todo Put your notes here...
+ */
+public class KeystoreDetails {
+
+    private String keystoreLocation = "";
+    private String keystorePassword = "";
+    private String alias = "";
+    private String keyPassword = null;
+    private String keystoreType = "JKS";
+    private String algType = "SunX509";
+    private String authority = "";
+    private List<String> authorizedDNs = new ArrayList<String>();
+
+    /**
+     * create a KeystoreDetails for accessing a certificate
+     *
+     * @param keystoreLocation
+     * @param keystorePassword
+     * @param alias
+     * @param keyPassword
+     */
+    public KeystoreDetails(String keystoreLocation, String keystorePassword, String alias, String keyPassword) {
+        this.keystoreLocation = keystoreLocation;
+        this.keystorePassword = keystorePassword;
+        this.alias = alias;
+        this.keyPassword = keyPassword;
+    }
+
+    public KeystoreDetails(String keystoreLocation, String keystorePassword, String alias) {
+        this.keystoreLocation = keystoreLocation;
+        this.keystorePassword = keystorePassword;
+        this.alias = alias;
+        this.keyPassword = keystorePassword;
+    }
+
+    /**
+     * constructor used when loading details from file.
+     */
+    public KeystoreDetails() {
+    }
+
+    public String getKeystoreLocation() {
+        return keystoreLocation;
+    }
+
+    public String getKeystorePassword() {
+        return keystorePassword;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public String getKeyPassword() {
+        return keyPassword;
+    }
+
+    public void setKeyPassword(String keyPassword) {
+        this.keyPassword = keyPassword;
+    }
+
+    public String getKeystoreType() {
+        return keystoreType;
+    }
+
+    public void setKeystoreType(String keystoreType) {
+        this.keystoreType = keystoreType;
+    }
+
+    public String getAlgType() {
+        return algType;
+    }
+
+    public void setAlgType(String algType) {
+        this.algType = algType;
+    }
+
+    /**
+     * combination of host (domain or IP) and port separated by a colon.
+     *
+     * @return
+     */
+    public String getAuthority() {
+        return authority;
+    }
+
+    public void setAuthority(String authority) {
+        this.authority = authority;
+    }
+
+    public void addAuthorizedDN(String dn) {
+        if (!authorizedDNs.contains(dn)) {
+            authorizedDNs.add(dn);
+        }
+    }
+
+    public List<String> getAuthorizedDNs() {
+        return authorizedDNs;
+    }
+
+    public void setAuthorizedDNs(List<String> authorizedDNs) {
+        this.authorizedDNs = authorizedDNs;
+    }
+
+}
diff --git a/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreManager.java b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..22563e63f31b28265ef68e13a9a64ba6ea470352
--- /dev/null
+++ b/gazelle-proxy-netty/src/test/java/net/ihe/gazelle/proxy/netty/syslog/KeystoreManager.java
@@ -0,0 +1,430 @@
+/**
+ *  Copyright (c) 2009-2011 University of Cardiff and others
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  permissions and limitations under the License.
+ *
+ *  Contributors:
+ *    University of Cardiff - initial API and implementation
+ *    -
+ */
+
+package net.ihe.gazelle.proxy.netty.syslog;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Class Description Here...
+ *
+ * @author Andrew Harrison
+ * @version $Revision:$
+ * @created Nov 20, 2008: 7:58:07 PM
+ * @date $Date:$ modified by $Author:$
+ * @todo Put your notes here...
+ */
+
+public class KeystoreManager {
+
+    static Logger log = Logger.getLogger("org.wspeer.security.KeystoreManager");
+
+    private static X509TrustManager sunTrustManager = null;
+    private KeystoreDetails defaultKeyDetails;
+    private HashMap<String, KeystoreDetails> allKeys = new HashMap<String, KeystoreDetails>();
+    private HashMap<String, KeystoreDetails> allStores = new HashMap<String, KeystoreDetails>();
+
+    private File keysDir;
+    private File certsDir;
+    private String home;
+
+    static {
+        loadDefaultTrustManager();
+    }
+
+    private static void loadDefaultTrustManager() {
+        try {
+            File certs;
+            String definedcerts = System.getProperty("javax.net.ssl.trustStore");
+            String pass = System.getProperty("javax.net.ssl.trustStorePassword");
+            if (definedcerts != null) {
+                certs = new File(definedcerts);
+            } else {
+                String common = System.getProperty("java.home") +
+                        File.separator +
+                        "lib" +
+                        File.separator +
+                        "security" +
+                        File.separator;
+                String cacerts = common + "cacerts";
+                String jssecacerts = common + "jssecacerts";
+                certs = new File(jssecacerts);
+                if (!certs.exists() || certs.length() == 0) {
+                    certs = new File(cacerts);
+                }
+
+            }
+            if (pass == null) {
+                pass = "changeit";
+            }
+            if (certs != null) {
+                KeyStore ks = KeyStore.getInstance("jks");
+                ks.load(new FileInputStream(certs), pass.toCharArray());
+                TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");
+                tmf.init(ks);
+                TrustManager tms[] = tmf.getTrustManagers();
+                for (int i = 0; i < tms.length; i++) {
+                    if (tms[i] instanceof X509TrustManager) {
+                        log.info(" found default trust manager.");
+                        sunTrustManager = (X509TrustManager) tms[i];
+                        break;
+                    }
+                }
+            }
+
+        } catch (KeyStoreException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        } catch (NoSuchAlgorithmException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        } catch (CertificateException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        } catch (NoSuchProviderException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        } catch (FileNotFoundException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        } catch (IOException e) {
+            log.fine("Exception thrown trying to create default trust manager:" + e.getMessage());
+        }
+    }
+
+    public KeystoreManager(String home) {
+        if (home != null) {
+            this.home = home;
+            loadKeys(this.home);
+        }
+    }
+
+    private void loadKeys(String home) {
+        File sec = new File(home);
+        if (!sec.exists()) {
+            return;
+        }
+
+        keysDir = new File(sec, "keys");
+        if (!keysDir.exists()) {
+            keysDir.mkdir();
+        }
+        certsDir = new File(sec, "certs");
+        if (!certsDir.exists()) {
+            certsDir.mkdir();
+        }
+        File[] keyfiles = keysDir.listFiles();
+        if (keyfiles != null) {
+            for (File keyfile : keyfiles) {
+                try {
+                    KeystoreDetails kd = load(new FileInputStream(keyfile));
+                    if (kd.getAuthority() != null && kd.getAuthority().trim().equalsIgnoreCase("default")) {
+                        defaultKeyDetails = kd;
+                    }
+                    allKeys.put(keyfile.getName(), kd);
+
+                } catch (IOException e) {
+                    log.info(" exception thrown while loading details from " + keyfile.getAbsolutePath());
+                    continue;
+                }
+            }
+        }
+        keyfiles = certsDir.listFiles();
+        if (keyfiles != null) {
+            for (File keyfile : keyfiles) {
+                try {
+                    KeystoreDetails kd = load(new FileInputStream(keyfile));
+                    allStores.put(keyfile.getName(), kd);
+
+                } catch (IOException e) {
+                    log.info(" exception thrown while loading details from " + keyfile.getAbsolutePath());
+                    continue;
+                }
+            }
+        }
+    }
+
+    public static X509TrustManager getDefaultTrustManager() {
+        return sunTrustManager;
+    }
+
+    public void addKeyDetails(String fileName, KeystoreDetails details) throws IOException {
+        storeAsKey(details, fileName);
+        allKeys.put(fileName, details);
+    }
+
+    public void addTrustDetails(String fileName, KeystoreDetails details) throws IOException {
+        storeAsCert(details, fileName);
+        allStores.put(fileName, details);
+    }
+
+    public void deleteKeyDetails(String fileName) {
+        allKeys.remove(fileName);
+        deleteKey(fileName);
+    }
+
+    public void deleteTrustDetails(String fileName) {
+        allStores.remove(fileName);
+        deleteCert(fileName);
+    }
+
+    public KeystoreDetails getKeyDetails(String fileName) {
+        return allKeys.get(fileName);
+    }
+
+    public KeystoreDetails getTrustStoreDetails(String fileName) {
+        return allStores.get(fileName);
+    }
+
+    public void setDefaultKeystoreDetails(KeystoreDetails details) {
+        defaultKeyDetails = details;
+    }
+
+    public KeystoreDetails getDefaultKeyDetails() {
+        return defaultKeyDetails;
+    }
+
+    public File getKeysDirectory() {
+        return keysDir;
+    }
+
+    public File getCertsDirectory() {
+        return certsDir;
+    }
+
+    public KeystoreDetails getKeyFileDetails(String fileName) {
+        return allKeys.get(fileName);
+    }
+
+    public KeystoreDetails getStoreFileDetails(String fileName) {
+        return allStores.get(fileName);
+    }
+
+    public String[] getKeyfileNames() {
+        return allKeys.keySet().toArray(new String[allKeys.keySet().size()]);
+    }
+
+    public String[] getTrustfileNames() {
+        return allStores.keySet().toArray(new String[allStores.keySet().size()]);
+    }
+
+    public KeystoreDetails getKeyFileForHost(String host) {
+        KeystoreDetails def = null;
+        for (KeystoreDetails keystoreDetails : allKeys.values()) {
+            System.out.println("KeystoreManager.getKeyFileForHost getting next key authority:" + keystoreDetails.getAuthority());
+            String auth = keystoreDetails.getAuthority();
+            if (auth != null) {
+                if (auth.endsWith("*")) {
+                    String s = trimPort(host);
+                    if (s != null) {
+                        log.fine("KeystoreManager.getKeyFileForHost trimmed port:" + s);
+                        String a = getAnyPort(auth);
+                        if (a != null) {
+                            log.fine("KeystoreManager.getKeyFileForHost trimmed auth:" + a);
+                            auth = a;
+                            host = s;
+                        }
+                    }
+                }
+                if (auth.equals(host)) {
+                    return keystoreDetails;
+                } else if (auth.equalsIgnoreCase("default")) {
+                    def = keystoreDetails;
+                }
+            }
+        }
+        return def;
+    }
+
+    private static String trimPort(String host) {
+        int colon = host.indexOf(":");
+        if (colon > 0 && colon < host.length() - 1) {
+            try {
+                int port = Integer.parseInt(host.substring(colon + 1, host.length()), host.length());
+                host = host.substring(0, colon);
+                log.fine("KeystoreManager.trimPort up to colon:" + host);
+                log.fine("KeystoreManager.trimPort port:" + port);
+
+                return host;
+            } catch (NumberFormatException e) {
+            }
+        }
+        return null;
+    }
+
+    private static String getAnyPort(String auth) {
+        int star = auth.indexOf("*");
+        if (star == auth.length() - 1) {
+            int colon = auth.indexOf(":");
+            if (colon == star - 1) {
+                auth = auth.substring(0, colon);
+                return auth;
+            }
+        }
+        return null;
+    }
+
+    public KeystoreDetails getTrustFileForHost(String host) {
+
+        KeystoreDetails def = null;
+        for (KeystoreDetails keystoreDetails : allStores.values()) {
+            String auth = keystoreDetails.getAuthority();
+            if (auth != null) {
+                if (auth.endsWith("*")) {
+                    String s = trimPort(host);
+                    if (s != null) {
+                        String a = getAnyPort(auth);
+                        if (a != null) {
+                            auth = a;
+                            host = s;
+                        }
+                    }
+                }
+                if (auth.equals(host)) {
+                    return keystoreDetails;
+                } else if (auth.equalsIgnoreCase("default")) {
+                    def = keystoreDetails;
+                }
+            }
+        }
+        return def;
+    }
+
+
+    public KeystoreDetails load(InputStream in) throws IOException {
+        Properties props = new Properties();
+        props.load(in);
+        String keystoreLocation = props.getProperty("keystoreLocation");
+        if (keystoreLocation == null || keystoreLocation.length() == 0) {
+            throw new IOException("no location defined");
+        }
+        String keystorePassword = props.getProperty("keystorePassword");
+        if (keystorePassword == null || keystorePassword.length() == 0) {
+            throw new IOException("no keystore password defined");
+        }
+        String alias = props.getProperty("alias");
+        String keyPassword = props.getProperty("keyPassword");
+        if (keyPassword == null || keyPassword.length() == 0) {
+            keyPassword = keystorePassword;
+        }
+        String keystoreType = props.getProperty("keystoreType");
+        if (keystoreType == null || keystoreType.length() == 0) {
+            keystoreType = "JKS";
+        }
+        String algType = props.getProperty("algType");
+        if (algType == null || algType.length() == 0) {
+            algType = "SunX509";
+        }
+        String authority = props.getProperty("authority");
+        if (authority == null) {
+            authority = "";
+        }
+
+        String dns = props.getProperty("authorizedDNs");
+        List<String> authorizedDNs = new ArrayList<String>();
+        if (dns != null && dns.length() > 0) {
+            String[] dn = dns.split("&");
+            for (String s : dn) {
+                String decoded = URLDecoder.decode(s, "UTF-8");
+                if (decoded.length() > 0) {
+                    authorizedDNs.add(decoded);
+                }
+            }
+        }
+        KeystoreDetails details = new KeystoreDetails(keystoreLocation, keystorePassword, alias, keyPassword);
+        details.setAlgType(algType);
+        details.setKeystoreType(keystoreType);
+        details.setAuthority(authority);
+        for (String authorizedDN : authorizedDNs) {
+            details.addAuthorizedDN(authorizedDN);
+        }
+        return details;
+    }
+
+    public void storeAsKey(KeystoreDetails details, String name) throws IOException {
+        store(details, name, true);
+    }
+
+    public void storeAsCert(KeystoreDetails details, String name) throws IOException {
+        store(details, name, false);
+    }
+
+    public boolean deleteKey(String name) {
+        return delete(name, true);
+    }
+
+    public boolean deleteCert(String name) {
+        return delete(name, false);
+    }
+
+    private boolean delete(String name, boolean key) {
+        File f = key ? getKeysDirectory() : getCertsDirectory();
+        f = new File(f, name);
+        return f.delete();
+    }
+
+    private void store(KeystoreDetails details, String name, boolean key) throws IOException {
+        Properties props = new Properties();
+        props.setProperty("keystoreLocation", details.getKeystoreLocation());
+        props.setProperty("keystorePassword", details.getKeystorePassword());
+        props.setProperty("alias", details.getAlias());
+        if (details.getKeyPassword() == null) {
+            details.setKeyPassword("");
+        }
+        props.setProperty("keyPassword", details.getKeyPassword());
+        props.setProperty("keystoreType", details.getKeystoreType());
+        props.setProperty("algType", details.getAlgType());
+        if (details.getAuthority() != null) {
+            props.setProperty("authority", details.getAuthority());
+        }
+        List<String> authorizedDNs = details.getAuthorizedDNs();
+        if (authorizedDNs.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            for (String dn : authorizedDNs) {
+                sb.append(URLEncoder.encode(dn, "UTF-8")).append("&");
+            }
+            props.setProperty("authorizedDNs", sb.toString());
+        }
+        File f = key ? getKeysDirectory() : getCertsDirectory();
+        f = new File(f, name);
+        FileOutputStream out = new FileOutputStream(f);
+        props.store(out, "Details for " + details.getAlias() + " keystore access.");
+        out.close();
+    }
+
+
+}
diff --git a/gazelle-proxy-netty/src/test/resources/keys/clientKeyStore b/gazelle-proxy-netty/src/test/resources/keys/clientKeyStore
new file mode 100644
index 0000000000000000000000000000000000000000..d5e6c1b6103503afc66add97c9c6cf28eaca9a65
Binary files /dev/null and b/gazelle-proxy-netty/src/test/resources/keys/clientKeyStore differ
diff --git a/gazelle-proxy-netty/src/test/resources/keys/serverKeyStore b/gazelle-proxy-netty/src/test/resources/keys/serverKeyStore
new file mode 100644
index 0000000000000000000000000000000000000000..db9b60cdde7f88c77584883ffb6210881c3d83b5
Binary files /dev/null and b/gazelle-proxy-netty/src/test/resources/keys/serverKeyStore differ