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 (Mer, 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 }