/******************************************************************
*
* CyberHTTP for Java
*
* Copyright (C) Satoshi Konno 2002-2003
*
* File: HTTPServer.java
*
* Revision;
*
* 12/12/02 - first revision. 10/20/03 - Improved the HTTP server using
* multithreading. 08/27/04 - Changed accept() to set a default timeout,
* HTTP.DEFAULT_TIMEOUT, to the socket.
*
******************************************************************/
package com.guo.duoduo.airplayreceiver.http;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import com.guo.duoduo.airplayreceiver.utils.Debug;
import com.guo.duoduo.airplayreceiver.utils.ListenerList;
/**
*
* This class identifies an HTTP over TCP server<br>
* The server must be initialized iether by the
* {@link HTTPServer#open(InetAddress, int)} or the
* {@link HTTPServer#open(String, int)} method.<br>
* Optionally a set of {@link HTTPRequestListener} may be set<br>
* The server then can be started or stopped by the method
* {@link HTTPServer#start()} and {@link HTTPServer#stop()}
*
* @author Satoshi "skonno" Konno
* @author Stefano "Kismet" Lenzi
* @version 1.8
*
*/
public class HTTPServer implements Runnable
{
////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////
public final static String NAME = "CyberHTTP";
public final static String VERSION = "1.0";
public final static int DEFAULT_PORT = 80;
/**
* Default timeout connection for HTTP comunication
*
* @since 1.8
*/
public final static int DEFAULT_TIMEOUT = DEFAULT_PORT * 1000;
/**
* Store the current TCP timeout value The variable should be accessed by
* getter and setter metho
*/
protected int timeout = DEFAULT_TIMEOUT;
////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////
private ServerSocket serverSock = null;
////////////////////////////////////////////////
// ServerSocket
////////////////////////////////////////////////
private InetAddress bindAddr = null;
private int bindPort = 0;
private ListenerList httpRequestListenerList = new ListenerList();
private Thread httpServerThread = null;
public HTTPServer()
{
serverSock = null;
}
public static String getName()
{
String osName = System.getProperty("os.name");
String osVer = System.getProperty("os.version");
return osName + "/" + osVer + " " + NAME + "/" + VERSION;
}
public ServerSocket getServerSock()
{
return serverSock;
}
////////////////////////////////////////////////
// open/close
////////////////////////////////////////////////
public String getBindAddress()
{
if (bindAddr == null)
return "";
return bindAddr.toString();
}
public int getBindPort()
{
return bindPort;
}
/**
* Get the current socket timeout
*
* @since 1.8
*/
public synchronized int getTimeout()
{
return timeout;
}
/**
* Set the current socket timeout
*
* @param timeout new timeout
* @since 1.8
*/
public synchronized void setTimeout(int timeout)
{
this.timeout = timeout;
}
public boolean open(InetAddress addr, int port)
{
if (serverSock != null)
return true;
try
{
serverSock = new ServerSocket(bindPort, 0, bindAddr);
}
catch (IOException e)
{
return false;
}
return true;
}
public boolean open(String addr, int port)
{
if (serverSock != null)
return true;
try
{
bindAddr = InetAddress.getByName(addr);
bindPort = port;
serverSock = new ServerSocket(bindPort, 0, bindAddr);
serverSock.setReuseAddress(true);
}
catch (IOException e)
{
return false;
}
return true;
}
public boolean close()
{
if (serverSock == null)
return true;
try
{
serverSock.close();
serverSock = null;
bindAddr = null;
bindPort = 0;
}
catch (Exception e)
{
Debug.warning(e);
return false;
}
return true;
}
////////////////////////////////////////////////
// httpRequest
////////////////////////////////////////////////
public Socket accept()
{
if (serverSock == null)
return null;
try
{
Socket sock = serverSock.accept();
sock.setSoTimeout(getTimeout());
return sock;
}
catch (Exception e)
{
return null;
}
}
public boolean isOpened()
{
return (serverSock != null) ? true : false;
}
public void addRequestListener(HTTPRequestListener listener)
{
httpRequestListenerList.add(listener);
}
public void removeRequestListener(HTTPRequestListener listener)
{
httpRequestListenerList.remove(listener);
}
////////////////////////////////////////////////
// run
////////////////////////////////////////////////
public void performRequestListener(HTTPRequest httpReq)
{
int listenerSize = httpRequestListenerList.size();
for (int n = 0; n < listenerSize; n++)
{
HTTPRequestListener listener = (HTTPRequestListener) httpRequestListenerList
.get(n);
listener.httpRequestReceived(httpReq);
}
}
public void run()
{
if (isOpened() == false)
return;
Thread thisThread = Thread.currentThread();
while (httpServerThread == thisThread)
{
Thread.yield();
Socket sock;
try
{
Debug.message("accept ...");
sock = accept();
if (sock != null)
Debug.message("sock = " + sock.getRemoteSocketAddress());
}
catch (Exception e)
{
Debug.warning(e);
break;
}
HTTPServerThread httpServThread = new HTTPServerThread(this, sock);
httpServThread.start();
Debug.message("httpServThread ...");
}
}
public boolean start()
{
StringBuffer name = new StringBuffer("Cyber.HTTPServer/");
name.append(serverSock.getLocalSocketAddress());
httpServerThread = new Thread(this, name.toString());
httpServerThread.start();
return true;
}
public boolean stop()
{
httpServerThread = null;
return true;
}
}