Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 package org.apache.xmlrpc.webserver;
00020
00021 import java.io.IOException;
00022 import java.io.InterruptedIOException;
00023 import java.net.BindException;
00024 import java.net.InetAddress;
00025 import java.net.ServerSocket;
00026 import java.net.Socket;
00027 import java.net.SocketException;
00028 import java.util.ArrayList;
00029 import java.util.List;
00030 import java.util.StringTokenizer;
00031
00032 import org.apache.xmlrpc.server.XmlRpcStreamServer;
00033 import org.apache.xmlrpc.util.ThreadPool;
00034
00035
00072 public class WebServer implements Runnable {
00073 private class AddressMatcher {
00074 private final int pattern[];
00075
00076 AddressMatcher(String pAddress) {
00077 try {
00078 pattern = new int[4];
00079 StringTokenizer st = new StringTokenizer(pAddress, ".");
00080 if (st.countTokens() != 4) {
00081 throw new IllegalArgumentException();
00082 }
00083 for (int i = 0; i < 4; i++) {
00084 String next = st.nextToken();
00085 if ("*".equals(next)) {
00086 pattern[i] = 256;
00087 } else {
00088
00089
00090
00091 pattern[i] = (byte) Integer.parseInt(next);
00092 }
00093 }
00094 } catch (Exception e) {
00095 throw new IllegalArgumentException("\"" + pAddress
00096 + "\" does not represent a valid IP address");
00097 }
00098 }
00099
00100 boolean matches(byte[] pAddress) {
00101 for (int i = 0; i < 4; i++) {
00102 if (pattern[i] > 255) {
00103 continue;
00104 }
00105 if (pattern[i] != pAddress[i]) {
00106 return false;
00107 }
00108 }
00109 return true;
00110 }
00111 }
00112
00113 protected ServerSocket serverSocket;
00114 private Thread listener;
00115 private ThreadPool pool;
00116 protected final List accept = new ArrayList();
00117 protected final List deny = new ArrayList();
00118 protected final XmlRpcStreamServer server = newXmlRpcStreamServer();
00119
00120 protected XmlRpcStreamServer newXmlRpcStreamServer(){
00121 return new ConnectionServer();
00122 }
00123
00124
00125 private InetAddress address;
00126 private int port;
00127
00128 private boolean paranoid;
00129
00130 static final String HTTP_11 = "HTTP/1.1";
00135 public WebServer(int pPort) {
00136 this(pPort, null);
00137 }
00138
00144 public WebServer(int pPort, InetAddress pAddr) {
00145 address = pAddr;
00146 port = pPort;
00147 }
00148
00162 protected ServerSocket createServerSocket(int pPort, int backlog, InetAddress addr)
00163 throws IOException {
00164 return new ServerSocket(pPort, backlog, addr);
00165 }
00166
00175 private synchronized void setupServerSocket(int backlog) throws IOException {
00176
00177
00178
00179
00180
00181 for (int i = 1; ; i++) {
00182 try {
00183 serverSocket = createServerSocket(port, backlog, address);
00184
00185 if (serverSocket.getSoTimeout() <= 0) {
00186 serverSocket.setSoTimeout(4096);
00187 }
00188 return;
00189 } catch (BindException e) {
00190 if (i == 10) {
00191 throw e;
00192 } else {
00193 long waitUntil = System.currentTimeMillis() + 1000;
00194 for (;;) {
00195 long l = waitUntil - System.currentTimeMillis();
00196 if (l > 0) {
00197 try {
00198 Thread.sleep(l);
00199 } catch (InterruptedException ex) {
00200 }
00201 } else {
00202 break;
00203 }
00204 }
00205 }
00206 }
00207 }
00208 }
00209
00217 public void start() throws IOException {
00218 setupServerSocket(50);
00219
00220
00221 if (listener == null) {
00222 listener = new Thread(this, "XML-RPC Weblistener");
00223
00224 listener.start();
00225 }
00226 }
00227
00234 public void setParanoid(boolean pParanoid) {
00235 paranoid = pParanoid;
00236 }
00237
00244 protected boolean isParanoid() {
00245 return paranoid;
00246 }
00247
00256 public void acceptClient(String pAddress) {
00257 accept.add(new AddressMatcher(pAddress));
00258 }
00259
00269 public void denyClient(String pAddress) {
00270 deny.add(new AddressMatcher(pAddress));
00271 }
00272
00280 protected boolean allowConnection(Socket s) {
00281 if (!paranoid) {
00282 return true;
00283 }
00284
00285 int l = deny.size();
00286 byte addr[] = s.getInetAddress().getAddress();
00287 for (int i = 0; i < l; i++) {
00288 AddressMatcher match = (AddressMatcher) deny.get(i);
00289 if (match.matches(addr))
00290 {
00291 return false;
00292 }
00293 }
00294 l = accept.size();
00295 for (int i = 0; i < l; i++) {
00296 AddressMatcher match = (AddressMatcher) accept.get(i);
00297 if (match.matches(addr)) {
00298 return true;
00299 }
00300 }
00301 return false;
00302 }
00303
00304 protected ThreadPool.Task newTask(WebServer pServer, XmlRpcStreamServer pXmlRpcServer,
00305 Socket pSocket) throws IOException {
00306 return new Connection(pServer, pXmlRpcServer, pSocket);
00307 }
00308
00321 public void run() {
00322 pool = newThreadPool();
00323 try {
00324 while (listener != null) {
00325 try {
00326 Socket socket = serverSocket.accept();
00327 try {
00328 socket.setTcpNoDelay(true);
00329 } catch (SocketException socketOptEx) {
00330 log(socketOptEx);
00331 }
00332
00333 try {
00334 if (allowConnection(socket)) {
00335
00336 socket.setSoTimeout(30000);
00337 final ThreadPool.Task task = newTask(this, server, socket);
00338 if (pool.startTask(task)) {
00339 socket = null;
00340 } else {
00341 log("Maximum load of " + pool.getMaxThreads()
00342 + " exceeded, rejecting client");
00343 }
00344 }
00345 } finally {
00346 if (socket != null) { try { socket.close(); } catch (Throwable ignore) {} }
00347 }
00348 } catch (InterruptedIOException checkState) {
00349
00350
00351 } catch (Throwable t) {
00352 log(t);
00353 }
00354 }
00355 } finally {
00356 if (serverSocket != null) {
00357 try {
00358 serverSocket.close();
00359 } catch (IOException e) {
00360 log(e);
00361 }
00362 }
00363
00364
00365 pool.shutdown();
00366 }
00367 }
00368
00369 protected ThreadPool newThreadPool() {
00370 return new ThreadPool(server.getMaxThreads(), "XML-RPC");
00371 }
00372
00380 public synchronized void shutdown() {
00381
00382 if (listener != null) {
00383 Thread l = listener;
00384 listener = null;
00385 l.interrupt();
00386 if (pool != null) {
00387 pool.shutdown();
00388 }
00389 }
00390 }
00391
00396 public int getPort() { return serverSocket.getLocalPort(); }
00397
00401 public void log(Throwable pError) {
00402 final String msg = pError.getMessage() == null ? pError.getClass().getName() : pError.getMessage();
00403 server.getErrorLogger().log(msg, pError);
00404 }
00405
00409 public void log(String pMessage) {
00410 server.getErrorLogger().log(pMessage);
00411 }
00412
00416 public XmlRpcStreamServer getXmlRpcServer() {
00417 return server;
00418 }
00419 }