View Javadoc
1   package com.ericsson.research.trap.spi.transports;
2   
3   /*
4    * ##_BEGIN_LICENSE_##
5    * Transport Abstraction Package (trap)
6    * ----------
7    * Copyright (C) 2014 Ericsson AB
8    * ----------
9    * Redistribution and use in source and binary forms, with or without modification,
10   * are permitted provided that the following conditions are met:
11   * 
12   * 1. Redistributions of source code must retain the above copyright notice, this
13   *    list of conditions and the following disclaimer.
14   * 
15   * 2. Redistributions in binary form must reproduce the above copyright notice,
16   *    this list of conditions and the following disclaimer in the documentation
17   *    and/or other materials provided with the distribution.
18   * 
19   * 3. Neither the name of the Ericsson AB nor the names of its contributors
20   *    may be used to endorse or promote products derived from this software without
21   *    specific prior written permission.
22   * 
23   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26   * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32   * OF THE POSSIBILITY OF SUCH DAMAGE.
33   * ##_END_LICENSE_##
34   */
35  
36  import java.io.IOException;
37  import java.net.InetAddress;
38  import java.net.InetSocketAddress;
39  import java.util.Collection;
40  
41  import javax.net.ssl.SSLContext;
42  
43  import com.ericsson.research.trap.TrapException;
44  import com.ericsson.research.trap.nio.Nio;
45  import com.ericsson.research.trap.nio.ServerSocket;
46  import com.ericsson.research.trap.nio.ServerSocket.ServerSocketHandler;
47  import com.ericsson.research.trap.nio.Socket;
48  import com.ericsson.research.trap.spi.ListenerTrapTransport;
49  import com.ericsson.research.trap.spi.ListenerTrapTransportDelegate;
50  import com.ericsson.research.trap.spi.TrapConfiguration;
51  import com.ericsson.research.trap.spi.TrapMessage;
52  import com.ericsson.research.trap.spi.TrapTransport;
53  import com.ericsson.research.trap.spi.TrapTransportDelegate;
54  import com.ericsson.research.trap.spi.TrapTransportPriority;
55  import com.ericsson.research.trap.spi.TrapTransportProtocol;
56  import com.ericsson.research.trap.spi.TrapTransportState;
57  import com.ericsson.research.trap.utils.SSLUtil;
58  import com.ericsson.research.trap.utils.SSLUtil.SSLMaterial;
59  
60  public class ServerSocketTransport extends AbstractListenerTransport implements ListenerTrapTransport, ServerSocketHandler
61  {
62  
63  	private ServerSocket	              serverSocket;
64  	private ListenerTrapTransportDelegate	listenerDelegate;
65  	private Object	                      listenerContext;
66  	boolean	                              defaultHost	= false;
67  	private boolean	                      secure	  = false;
68  
69  	public ServerSocketTransport()
70  	{
71  		this.transportPriority = TrapTransportPriority.SOCKET_ERNIO;
72  	}
73  
74  	public String getTransportName()
75  	{
76  		return "socket";
77  	}
78  
79  	public String getProtocolName()
80  	{
81  		return TrapTransportProtocol.TCP;
82  	}
83  
84  	/**
85  	 * Listen for incoming connections.
86  	 */
87  	public void listen(ListenerTrapTransportDelegate listener, Object context) throws TrapException
88  	{
89  		// Remember the delegate and context. We need them for callbacks
90  		this.listenerDelegate = listener;
91  		this.listenerContext = context;
92  		this.delegate = new TrapTransportDelegate()
93  		{
94  
95  			public void ttStateChanged(TrapTransportState newState, TrapTransportState oldState, TrapTransport transport, Object context)
96  			{
97  				// TODO Auto-generated method stub
98  
99  			}
100 
101 			public void ttMessageReceived(TrapMessage message, TrapTransport transport, Object context)
102 			{
103 				// TODO Auto-generated method stub
104 
105 			}
106 
107 			public void ttMessageSent(TrapMessage message, TrapTransport transport, Object context)
108 			{
109 				// TODO Auto-generated method stub
110 
111 			}
112 
113 			@Override
114 			public void ttMessagesFailedSending(Collection<TrapMessage> messages, TrapTransport transport, Object context)
115 			{
116 				// TODO Auto-generated method stub
117 
118 			}
119 
120 			@Override
121 			public void ttNeedTransport(TrapMessage message, TrapTransport transport, Object context)
122 			{
123 				// TODO Auto-generated method stub
124 
125 			}
126 		};
127 
128 		// Start a socket
129 		ServerSocket ss;
130 
131 		SSLContext sslc = null;
132 
133 		if (this.getOption(CERT_USE_INSECURE_TEST) != null)
134 		{
135 			sslc = SSLUtil.getContext(new SSLMaterial("jks", "trapserver.jks", "Ericsson"), new SSLMaterial("jks", "trapserver.jks", "Ericsson"));
136 			this.logger.warn("Using insecure SSL context");
137 		}
138 		else
139 		{
140 			try
141 			{
142 				String keyType = this.getOption(CERT_KEYSTORE_TYPE);
143 				String keyName = this.getOption(CERT_KEYSTORE_NAME);
144 				String keyPass = this.getOption(CERT_KEYSTORE_PASS);
145 
146 				String trustType = this.getOption(CERT_TRUSTSTORE_TYPE);
147 				String trustName = this.getOption(CERT_TRUSTSTORE_NAME);
148 				String trustPass = this.getOption(CERT_TRUSTSTORE_PASS);
149 
150 				if (keyName != null)
151 				{
152 					sslc = SSLUtil.getContext(new SSLMaterial(keyType, keyName, keyPass), new SSLMaterial(trustType, trustName, trustPass));
153 					this.logger.info("Using provided SSL context. Keystore [{}], Truststore [{}]", keyName, trustName);
154 				}
155 
156 			}
157 			catch (Exception e)
158 			{
159 				this.logger.warn("Not using SSL due to exception {}", e);
160 			}
161 		}
162 
163 		try
164 		{
165 
166 			if (sslc == null)
167 			{
168 				ss = Nio.factory().server(this);
169 			}
170 			else
171 			{
172 
173 				ss = Nio.factory().sslServer(sslc, this);
174 				this.secure = true;
175 			}
176 			// Listen on port 0
177 			int port = 0;
178 			try
179 			{
180 				port = Integer.parseInt(this.getOption(SocketConstants.CONFIG_PORT));
181 			}
182 			catch (Throwable t)
183 			{
184 			}
185 
186 			String host = null;
187 
188 			try
189 			{
190 				host = this.getOption(SocketConstants.CONFIG_HOST);
191 			}
192 			catch (Throwable t)
193 			{
194 			}
195 
196 			if ((host == null) || (host.trim().length() == 0))
197 			{
198 				this.defaultHost = true;
199 				host = "0.0.0.0";
200 			}
201 
202 			ss.listen(InetAddress.getByName(host), port);
203 			this.serverSocket = ss;
204 			this.setState(TrapTransportState.CONNECTED);
205 
206 			// We'll receive a callback when the socket is bound
207 		}
208 		catch (IOException e)
209 		{
210 			throw new TrapException(e);
211 		}
212 	}
213 
214 	/**
215 	 * Called when we want to configure a client to connect to us. See
216 	 * AsynchronousTransportTest for an example on when it is called.
217 	 */
218 	public void getClientConfiguration(TrapConfiguration destination, String defaultName)
219 	{
220 		// This function may be called before we're ready on the server socket
221 		// side. This loop will prevent us
222 		// from accessing a non-ready server socket.
223 		while ((this.serverSocket == null) && (this.getState() != TrapTransportState.ERROR) && (this.getState() != TrapTransportState.DISCONNECTED))
224 			try
225 			{
226 				System.out.println("Waiting...");
227 				Thread.sleep(10);
228 			}
229 			catch (InterruptedException e)
230 			{
231 				// TODO Auto-generated catch block
232 				e.printStackTrace();
233 			}
234 
235 		// If we still don't have a server socket, we're not going to be ready
236 		// (state == ERROR or interrupted).
237 		if (this.serverSocket == null)
238 			throw new IllegalStateException("Could not initialise Server Socket");
239 
240 		// Insert the appropriate values into the TrapConfiguration. These are
241 		// the same values we expect on the client side.
242 		// The exact values are not defined by Trap but are Transport-specific.
243 		// Each transport can and will have a different
244 		// set of values they want transferred.
245 		InetSocketAddress inetAddress;
246 		try
247 		{
248 			inetAddress = this.serverSocket.getInetAddress();
249 
250 			// Check for pre-existing port
251 			String port = this.getOption("autoconfig.port");
252 
253 			if (port == null)
254 				port = Integer.toString(inetAddress.getPort());
255 
256 			String hostName = this.getOption("autoconfig.host");
257 
258 			if (hostName == null)
259 				hostName = defaultName;
260 
261 			if (hostName == null)
262 				hostName = this.getHostName(inetAddress.getAddress(), this.defaultHost, true);
263 
264 			destination.setOption(this.prefix, SocketConstants.CONFIG_HOST, hostName);
265 			destination.setOption(this.prefix, SocketConstants.CONFIG_PORT, port);
266 		}
267 		catch (IOException e)
268 		{
269 			// TODO Auto-generated catch block
270 			e.printStackTrace();
271 		}
272 		destination.setOption(this.prefix, SocketConstants.CONFIG_SECURE, "" + this.secure);
273 
274 	}
275 
276 	// Called when we want to close the server socket (=stop listening).
277 	@Override
278 	protected void internalDisconnect()
279 	{
280 		this.serverSocket.close();
281 	}
282 
283 	@Override
284 	public void flushTransport()
285 	{
286 
287 	}
288 
289 	@Override
290 	public void accept(Socket sock, ServerSocket ss)
291 	{
292 		// Create a SocketTransport that wraps around the socket
293 		TrapTransport transport = new SocketTransport(sock);
294 
295 		// Notify the listener of a new connection
296 		this.listenerDelegate.ttsIncomingConnection(transport, this, this.listenerContext);
297 
298 	}
299 
300 	@Override
301 	public void error(Throwable exc, ServerSocket ss)
302 	{
303 		this.setState(TrapTransportState.ERROR);
304 
305 	}
306 
307 }