001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.server.ntp; 021 022 023 import java.io.IOException; 024 025 import org.apache.directory.server.ntp.protocol.NtpProtocolCodecFactory; 026 import org.apache.directory.server.ntp.protocol.NtpProtocolHandler; 027 import org.apache.directory.server.protocol.shared.AbstractProtocolService; 028 import org.apache.directory.server.protocol.shared.transport.Transport; 029 import org.apache.directory.server.protocol.shared.transport.UdpTransport; 030 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 031 import org.apache.mina.core.service.IoAcceptor; 032 import org.apache.mina.core.service.IoHandler; 033 import org.apache.mina.filter.codec.ProtocolCodecFilter; 034 import org.apache.mina.transport.socket.DatagramAcceptor; 035 import org.apache.mina.transport.socket.DatagramSessionConfig; 036 import org.apache.mina.transport.socket.SocketAcceptor; 037 import org.slf4j.Logger; 038 import org.slf4j.LoggerFactory; 039 040 041 /** 042 * Contains the configuration parameters for the NTP protocol provider. 043 * 044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 045 * @version $Rev: 896599 $, $Date: 2010-01-06 19:26:43 +0100 (Wed, 06 Jan 2010) $ 046 * @org.apache.xbean.XBean 047 */ 048 public class NtpServer extends AbstractProtocolService 049 { 050 /** logger for this class */ 051 private static final Logger LOG = LoggerFactory.getLogger( NtpServer.class.getName() ); 052 053 /** 054 * The default IP port. 055 */ 056 private static final int IP_PORT_DEFAULT = 123; 057 058 /** The default service pid. */ 059 private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ntp"; 060 061 /** The default service name. */ 062 private static final String SERVICE_NAME_DEFAULT = "ApacheDS NTP Service"; 063 064 065 /** 066 * Creates a new instance of NtpConfiguration. 067 */ 068 public NtpServer() 069 { 070 super.setServiceId( SERVICE_PID_DEFAULT ); 071 super.setServiceName( SERVICE_NAME_DEFAULT ); 072 } 073 074 075 /** 076 * Start the NTPServer. We initialize the Datagram and Socket, if necessary. 077 * 078 * Note that we don't have any filter in the chain, everything is done 079 * in the handler. 080 * @throws IOException if there are issues binding 081 */ 082 public void start() throws IOException 083 { 084 IoHandler ntpProtocolHandler = new NtpProtocolHandler(); 085 086 // Create the chain for the NTP server 087 DefaultIoFilterChainBuilder ntpChain = new DefaultIoFilterChainBuilder(); 088 ntpChain.addLast( "codec", new ProtocolCodecFilter( NtpProtocolCodecFactory.getInstance() ) ); 089 090 if ( ( transports == null ) || ( transports.size() == 0 ) ) 091 { 092 // Default to UDP with port 123 093 // We have to create a DatagramAcceptor 094 UdpTransport transport = new UdpTransport( IP_PORT_DEFAULT ); 095 setTransports( transport ); 096 097 DatagramAcceptor acceptor = (DatagramAcceptor)transport.getAcceptor(); 098 099 // Set the handler 100 acceptor.setHandler( ntpProtocolHandler ); 101 102 // Allow the port to be reused even if the socket is in TIME_WAIT state 103 ((DatagramSessionConfig)acceptor.getSessionConfig()).setReuseAddress( true ); 104 105 // Inject the chain 106 acceptor.setFilterChainBuilder( ntpChain ); 107 108 // Start the listener 109 acceptor.bind(); 110 } 111 else 112 { 113 for ( Transport transport:transports ) 114 { 115 IoAcceptor acceptor = transport.getAcceptor(); 116 117 // Set the handler 118 acceptor.setHandler( ntpProtocolHandler ); 119 120 if ( transport instanceof UdpTransport ) 121 { 122 // Allow the port to be reused even if the socket is in TIME_WAIT state 123 ((DatagramSessionConfig)acceptor.getSessionConfig()).setReuseAddress( true ); 124 } 125 else 126 { 127 // Disable the disconnection of the clients on unbind 128 acceptor.setCloseOnDeactivation( false ); 129 130 // Allow the port to be reused even if the socket is in TIME_WAIT state 131 ((SocketAcceptor)acceptor).setReuseAddress( true ); 132 133 // No Nagle's algorithm 134 ((SocketAcceptor)acceptor).getSessionConfig().setTcpNoDelay( true ); 135 } 136 137 // Inject the chain 138 acceptor.setFilterChainBuilder( ntpChain ); 139 140 // Start the listener 141 acceptor.bind(); 142 } 143 } 144 145 LOG.info( "NTP server started." ); 146 System.out.println( "NTP server started." ); 147 } 148 149 150 /** 151 * {@inheritDoc} 152 */ 153 public void stop() 154 { 155 for ( Transport transport :getTransports() ) 156 { 157 IoAcceptor acceptor = transport.getAcceptor(); 158 159 if ( acceptor != null ) 160 { 161 acceptor.dispose(); 162 } 163 } 164 165 LOG.info( "NTP Server stopped." ); 166 System.out.println( "NTP Server stopped." ); 167 } 168 169 170 /** 171 * @see Object#toString() 172 */ 173 public String toString() 174 { 175 StringBuilder sb = new StringBuilder(); 176 177 sb.append( "NTPServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' ); 178 179 if ( getTransports() != null ) 180 { 181 for ( Transport transport:getTransports() ) 182 { 183 sb.append( " " ).append( transport ).append( '\n' ); 184 } 185 } 186 187 return sb.toString(); 188 } 189 }