package org.subethamail.core.postfix; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.charset.Charset; import java.util.logging.Level; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.Startup; import javax.inject.Inject; import lombok.extern.java.Log; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.SocketAcceptor; import org.subethamail.core.injector.i.Injector; import org.subethamail.core.smtp.SMTPService; /** * @author Jon Stevens * @author Jeff Schnitzer * @author Scott Hernandez */ @Startup @Log public class PostfixTcpTableService implements PostfixTcpTableManagement { @Inject Injector injector; @Inject SMTPService smtpService; /** */ public static final int DEFAULT_PORT = 2502; private int port = DEFAULT_PORT; private String hostName = null; private SocketAcceptor acceptor; /** */ public class Handler extends IoHandlerAdapter { /* (non-Javadoc) * @see org.apache.mina.common.IoHandlerAdapter#sessionOpened(org.apache.mina.common.IoSession) */ @Override public void sessionOpened(IoSession session) throws Exception { log.log(Level.FINE,"session opened!"); session.setIdleTime(IdleStatus.BOTH_IDLE, 60); } /* (non-Javadoc) * @see org.apache.mina.common.IoHandlerAdapter#messageReceived(org.apache.mina.common.IoSession, java.lang.Object) */ @Override public void messageReceived(IoSession session, Object msg) throws Exception { log.log(Level.FINE,"Message received: {0}", msg); String line = (String)msg; // need at least 5 characters... really need more though if (line.length() < 5) { session.write("500 Invalid command"); return; } // check for "get " String getPart = line.substring(0,4); if (!getPart.toLowerCase().equals("get ")) { session.write("500 Invalid command"); return; } // strip off the "get " // get<SPACE>STUFF<NEWLINE> line = line.substring(4, line.length()); boolean accepted = injector.accept(line); if (accepted) { int smtpPort = smtpService.getPort(); InetAddress binding = smtpService.getBinding(); if (binding == null) binding = InetAddress.getLocalHost(); session.write("200 smtp:[" + binding.getHostAddress() + "]:" + smtpPort); } else { session.write("500 Lookup failed for: " + line); } } /* (non-Javadoc) * @see org.apache.mina.common.IoHandlerAdapter#exceptionCaught(org.apache.mina.common.IoSession, java.lang.Throwable) */ @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { log.log(Level.INFO,"Closing due to exception", cause); session.close(); } /* (non-Javadoc) * @see org.apache.mina.common.IoHandlerAdapter#sessionIdle(org.apache.mina.common.IoSession, org.apache.mina.common.IdleStatus) */ @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { log.log(Level.FINE,"Closing idle connection with status {0}", status); session.close(); } } /** */ @PostConstruct public void start() throws IOException { if (this.acceptor != null) throw new IllegalStateException("TcpTableService already running"); InetAddress binding = null; String bindAddress = System.getProperty("jboss.bind.address"); if (bindAddress != null && !"0.0.0.0".equals(bindAddress)) binding = InetAddress.getByName(bindAddress); log.log(Level.INFO,"Starting TcpTableService: {0}:{1}", new Object[]{(binding==null ? "*" : binding),port}); this.acceptor = new SocketAcceptor(); this.acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory(Charset.forName("UTF-8")))); this.acceptor.bind(new InetSocketAddress(binding, this.port), new Handler()); } /** */ @PreDestroy public void stop() { log.info("Stopping TcpTable service"); this.acceptor.unbindAll(); this.acceptor = null; } /** */ public void setPort(int port) { if (this.acceptor != null) throw new IllegalStateException("TcpTable already running"); this.port = port; } /** */ public int getPort() { return this.port; } /** */ public void setHostName(String hostname) { if (this.acceptor != null) throw new IllegalStateException("TcpTable already running"); this.hostName = hostname; } /** */ public String getHostName() { return this.hostName; } }