1 /*
2  * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *   - Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *   - Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *   - Neither the name of Oracle nor the names of its
16  *     contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 import java.io.*;
42 import java.net.*;
43 import java.nio.channels.*;
44 import java.security.*;
45 import javax.net.ssl.*;
46 
47 /**
48  * The main server base class.
49  * <P>
50  * This class is responsible for setting up most of the server state
51  * before the actual server subclasses take over.
52  *
53  * @author Mark Reinhold
54  * @author Brad R. Wetmore
55  */
56 public abstract class Server {
57 
58     ServerSocketChannel ssc;
59     SSLContext sslContext = null;
60 
61     static private int PORT = 8000;
62     static private int BACKLOG = 1024;
63     static private boolean SECURE = false;
64 
Server(int port, int backlog, boolean secure)65     Server(int port, int backlog,
66             boolean secure) throws Exception {
67 
68         if (secure) {
69             createSSLContext();
70         }
71 
72         ssc = ServerSocketChannel.open();
73         ssc.socket().setReuseAddress(true);
74         ssc.socket().bind(new InetSocketAddress(port), backlog);
75     }
76 
77     /*
78      * If this is a secure server, we now setup the SSLContext we'll
79      * use for creating the SSLEngines throughout the lifetime of
80      * this process.
81      */
createSSLContext()82     private void createSSLContext() throws Exception {
83 
84         char[] passphrase = "passphrase".toCharArray();
85 
86         KeyStore ks = KeyStore.getInstance("JKS");
87         ks.load(new FileInputStream("testkeys"), passphrase);
88 
89         KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
90         kmf.init(ks, passphrase);
91 
92         TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
93         tmf.init(ks);
94 
95         sslContext = SSLContext.getInstance("TLS");
96         sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
97     }
98 
runServer()99     abstract void runServer() throws Exception;
100 
usage()101     static private void usage() {
102         System.out.println(
103             "Usage:  Server <type> [options]\n"
104                 + "     type:\n"
105                 + "             B1      Blocking/Single-threaded Server\n"
106                 + "             BN      Blocking/Multi-threaded Server\n"
107                 + "             BP      Blocking/Pooled-Thread Server\n"
108                 + "             N1      Nonblocking/Single-threaded Server\n"
109                 + "             N2      Nonblocking/Dual-threaded Server\n"
110                 + "\n"
111                 + "     options:\n"
112                 + "             -port port              port number\n"
113                 + "                 default:  " + PORT + "\n"
114                 + "             -backlog backlog        backlog\n"
115                 + "                 default:  " + BACKLOG + "\n"
116                 + "             -secure                 encrypt with SSL/TLS");
117         System.exit(1);
118     }
119 
120     /*
121      * Parse the arguments, decide what type of server to run,
122      * see if there are any defaults to change.
123      */
createServer(String args[])124     static private Server createServer(String args[]) throws Exception {
125         if (args.length < 1) {
126             usage();
127         }
128 
129         int port = PORT;
130         int backlog = BACKLOG;
131         boolean secure = SECURE;
132 
133         for (int i = 1; i < args.length; i++) {
134             if (args[i].equals("-port")) {
135                 checkArgs(i, args.length);
136                 port = Integer.valueOf(args[++i]);
137             } else if (args[i].equals("-backlog")) {
138                 checkArgs(i, args.length);
139                 backlog = Integer.valueOf(args[++i]);
140             } else if (args[i].equals("-secure")) {
141                 secure = true;
142             } else {
143                 usage();
144             }
145         }
146 
147         Server server = null;
148 
149         if (args[0].equals("B1")) {
150             server = new B1(port, backlog, secure);
151         } else if (args[0].equals("BN")) {
152             server = new BN(port, backlog, secure);
153         } else if (args[0].equals("BP")) {
154             server = new BP(port, backlog, secure);
155         } else if (args[0].equals("N1")) {
156             server = new N1(port, backlog, secure);
157         } else if (args[0].equals("N2")) {
158             server = new N2(port, backlog, secure);
159         }
160 
161         return server;
162     }
163 
checkArgs(int i, int len)164     static private void checkArgs(int i, int len) {
165         if ((i + 1) >= len) {
166            usage();
167         }
168     }
169 
main(String args[])170     static public void main(String args[]) throws Exception {
171         Server server = createServer(args);
172 
173         if (server == null) {
174             usage();
175         }
176 
177         System.out.println("Server started.");
178         server.runServer();
179     }
180 }
181