jpayne@68: package server; jpayne@68: jpayne@68: import java.io.BufferedReader; jpayne@68: import java.io.IOException; jpayne@68: import java.io.InputStream; jpayne@68: import java.io.InputStreamReader; jpayne@68: import java.io.OutputStream; jpayne@68: import java.net.HttpURLConnection; jpayne@68: import java.net.InetSocketAddress; jpayne@68: import java.net.MalformedURLException; jpayne@68: import java.net.URL; jpayne@68: import java.net.URLConnection; jpayne@68: import java.util.ArrayList; jpayne@68: import java.util.Arrays; jpayne@68: import java.util.List; jpayne@68: import java.util.Map.Entry; jpayne@68: jpayne@68: import com.sun.net.httpserver.Headers; jpayne@68: import com.sun.net.httpserver.HttpExchange; jpayne@68: jpayne@68: import fileIO.ReadWrite; jpayne@68: import shared.Tools; jpayne@68: import structures.ByteBuilder; jpayne@68: import structures.StringNum; jpayne@68: jpayne@68: public class ServerTools { jpayne@68: jpayne@68: public static void main(String[] args){ jpayne@68: String address=args[0]; jpayne@68: int rounds=1; jpayne@68: String message=""; jpayne@68: if(args.length>1){rounds=Integer.parseInt(args[1]);} jpayne@68: if(args.length>2){message=args[2];} jpayne@68: byte[] messageBytes=message.getBytes(); jpayne@68: jpayne@68: long[] times=new long[rounds]; jpayne@68: StringNum response=null; jpayne@68: long prevTime=System.nanoTime(); jpayne@68: for(int i=0; i0; len=is.read(buffer)){ jpayne@68: bb.append(buffer, 0, len); jpayne@68: } jpayne@68: is.close(); jpayne@68: success=true; jpayne@68: } catch (MalformedURLException e) { jpayne@68: e.printStackTrace(); jpayne@68: bb.clear(); jpayne@68: Tools.pause(1000); jpayne@68: System.err.println("Retrying; attempt "+(i+1)+", URL "+address); jpayne@68: } catch (IOException e) { jpayne@68: e.printStackTrace(); jpayne@68: bb.clear(); jpayne@68: Tools.pause(1000); jpayne@68: System.err.println("Retrying; attempt "+(i+1)+", URL "+address); jpayne@68: } jpayne@68: } jpayne@68: return bb; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** Send a message to a remote URL, and return the response. jpayne@68: * Set message to null if there is no message. */ jpayne@68: public static StringNum sendAndReceive(byte[] message, String address){ jpayne@68: address=PercentEncoding.commonSymbolToCode(address); jpayne@68: URL url=null; jpayne@68: InputStream is=null; jpayne@68: HttpURLConnection connection=null; jpayne@68: OutputStream os=null; jpayne@68: try { jpayne@68: url=new URL(address); jpayne@68: connection=(HttpURLConnection) url.openConnection(); jpayne@68: connection.setDoOutput(true); jpayne@68: connection.setConnectTimeout(40000); //For testing jpayne@68: os=connection.getOutputStream(); jpayne@68: } catch (IOException e1) { jpayne@68: // System.err.println("A:\t"+address+" -> "+url+" -> "+connection+" -> "+os); jpayne@68: // TODO Auto-generated catch block jpayne@68: if(!suppressErrors){e1.printStackTrace();} jpayne@68: } jpayne@68: jpayne@68: if(os!=null){ jpayne@68: try { jpayne@68: //TODO: It may be useful to set a timeout here. jpayne@68: if(message!=null){os.write(message);} jpayne@68: } catch (IOException e) { jpayne@68: // System.err.println("B:\t"+connection+" -> "+os); jpayne@68: // TODO Auto-generated catch block jpayne@68: if(!suppressErrors){e.printStackTrace();} jpayne@68: } jpayne@68: try { jpayne@68: os.close(); jpayne@68: } catch (IOException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: String result=null; jpayne@68: int responseCode=1; jpayne@68: if(connection!=null){ jpayne@68: IOException noInputStream=null; jpayne@68: try { jpayne@68: is=connection.getInputStream(); jpayne@68: } catch (IOException e) { jpayne@68: noInputStream=e; jpayne@68: } jpayne@68: if(is==null){is=connection.getErrorStream();} jpayne@68: jpayne@68: try { jpayne@68: responseCode=connection.getResponseCode(); jpayne@68: if(!suppressErrors && (responseCode<200 || responseCode>299)){ jpayne@68: System.err.println("Error: Server returned response code "+responseCode); jpayne@68: } jpayne@68: } catch (IOException e) { jpayne@68: if(!suppressErrors) { jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: if(is!=null){ jpayne@68: result=readStream(is); jpayne@68: try { jpayne@68: // System.err.println("C:\t"+connection+" -> "+os+" -> "+is+" -> "+(result!=null)); jpayne@68: is.close(); jpayne@68: } catch (IOException e) { jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: }else if(noInputStream!=null && !suppressErrors){ jpayne@68: noInputStream.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: return new StringNum(result, responseCode); jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** Send a message to a remote URL, and return the response. jpayne@68: * Set message to null if there is no message. */ jpayne@68: public static StringNum sendAndReceiveFTP(byte[] message, String address){ jpayne@68: address=PercentEncoding.commonSymbolToCode(address); jpayne@68: URL url=null; jpayne@68: InputStream is=null; jpayne@68: URLConnection connection=null; jpayne@68: OutputStream os=null; jpayne@68: try { jpayne@68: url=new URL(address); jpayne@68: connection=url.openConnection(); jpayne@68: connection.setDoOutput(true); jpayne@68: connection.setConnectTimeout(40000); //For testing jpayne@68: os=connection.getOutputStream(); jpayne@68: } catch (IOException e1) { jpayne@68: // System.err.println("A:\t"+address+" -> "+url+" -> "+connection+" -> "+os); jpayne@68: // TODO Auto-generated catch block jpayne@68: if(!suppressErrors){e1.printStackTrace();} jpayne@68: } jpayne@68: jpayne@68: if(os!=null){ jpayne@68: try { jpayne@68: //TODO: It may be useful to set a timeout here. jpayne@68: if(message!=null){os.write(message);} jpayne@68: } catch (IOException e) { jpayne@68: // System.err.println("B:\t"+connection+" -> "+os); jpayne@68: // TODO Auto-generated catch block jpayne@68: if(!suppressErrors){e.printStackTrace();} jpayne@68: } jpayne@68: try { jpayne@68: os.close(); jpayne@68: } catch (IOException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: String result=null; jpayne@68: // int responseCode=1; jpayne@68: if(connection!=null){ jpayne@68: IOException noInputStream=null; jpayne@68: try { jpayne@68: is=connection.getInputStream(); jpayne@68: } catch (IOException e) { jpayne@68: noInputStream=e; jpayne@68: } jpayne@68: jpayne@68: // try { jpayne@68: //responseCode=connection.getResponseCode(); jpayne@68: // if(!suppressErrors && (responseCode<200 || responseCode>299)){ jpayne@68: // System.err.println("Error: Server returned response code "+responseCode); jpayne@68: // } jpayne@68: // } jpayne@68: // catch (IOException e) { jpayne@68: // if(!suppressErrors) { jpayne@68: // e.printStackTrace(); jpayne@68: // } jpayne@68: // } jpayne@68: jpayne@68: if(is!=null){ jpayne@68: result=readStream(is); jpayne@68: try { jpayne@68: // System.err.println("C:\t"+connection+" -> "+os+" -> "+is+" -> "+(result!=null)); jpayne@68: is.close(); jpayne@68: } catch (IOException e) { jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: }else if(noInputStream!=null && !suppressErrors){ jpayne@68: noInputStream.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: return new StringNum(result, 400); jpayne@68: } jpayne@68: jpayne@68: /** Read the body of an incoming HTTP session */ jpayne@68: public static String receive(HttpExchange t){ jpayne@68: InputStream is=t.getRequestBody(); jpayne@68: String s=readStream(is); jpayne@68: return s; jpayne@68: } jpayne@68: jpayne@68: /** Completely read an InputStream into a String */ jpayne@68: public static String readStream(InputStream is){ jpayne@68: if(is==null){return null;} jpayne@68: try { jpayne@68: byte[] buffer=new byte[256]; jpayne@68: int count=is.read(buffer); jpayne@68: int next=0; jpayne@68: while(count>-1){ jpayne@68: next+=count; jpayne@68: if(next>=buffer.length){ jpayne@68: buffer=Arrays.copyOf(buffer, buffer.length*2); jpayne@68: } jpayne@68: count=is.read(buffer, next, buffer.length-next); jpayne@68: } jpayne@68: is.close(); jpayne@68: return new String(buffer, 0, next); jpayne@68: } catch (IOException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: return null; jpayne@68: } jpayne@68: jpayne@68: /** Write to the body of an incoming HTTP session */ jpayne@68: public static boolean reply(String response, String type, HttpExchange t, boolean verbose, int code, boolean close){ jpayne@68: if(verbose){System.err.println("Sending: "+response);} jpayne@68: jpayne@68: return reply(response.getBytes(), type, t, false, code, close); jpayne@68: } jpayne@68: jpayne@68: /** Write to the body of an incoming HTTP session */ jpayne@68: public static boolean replyWithFile(String path, String type, HttpExchange t, boolean verbose, int code, boolean close){ jpayne@68: if(verbose){System.err.println("Sending: "+path);} jpayne@68: jpayne@68: byte[] response=null; jpayne@68: try { jpayne@68: response=ReadWrite.readRaw(path); jpayne@68: } catch (IOException e1) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e1.printStackTrace(); jpayne@68: response=new byte[0]; jpayne@68: code=400; //Node sure about this jpayne@68: } jpayne@68: jpayne@68: return reply(response, type, t, false, code, close); jpayne@68: } jpayne@68: jpayne@68: /** Write to the body of an incoming HTTP session */ jpayne@68: public static boolean reply(byte[] response, String type, HttpExchange t, boolean verbose, int code, boolean close){ jpayne@68: if(verbose){System.err.println("Sending: "+response);} jpayne@68: jpayne@68: { jpayne@68: Headers h = t.getResponseHeaders(); jpayne@68: // String type="text/plain"; jpayne@68: h.add("Content-Type", type); jpayne@68: } jpayne@68: try { jpayne@68: t.sendResponseHeaders(code, response.length); jpayne@68: OutputStream os = t.getResponseBody(); jpayne@68: os.write(response); jpayne@68: os.close(); jpayne@68: } catch (IOException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: if(close){t.close();} jpayne@68: return false; jpayne@68: } jpayne@68: if(close){t.close();} jpayne@68: return true; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** jpayne@68: * Wait for a set amount of time jpayne@68: * @param millis Time to wait jpayne@68: */ jpayne@68: public static void pause(long millis){ jpayne@68: String lock=new String("1"); jpayne@68: synchronized(lock){ jpayne@68: final long time=System.currentTimeMillis()+millis; jpayne@68: while(System.currentTimeMillis()> entry : reqh.entrySet()){ jpayne@68: // System.err.println(entry.getKey()+" -> "+entry.getValue()); jpayne@68: // } jpayne@68: } jpayne@68: return clientAddress; jpayne@68: } jpayne@68: jpayne@68: public static boolean isInternalQuery(HttpExchange t, String prefix, boolean allowLocalHost, boolean printIP, boolean printHeaders){ jpayne@68: jpayne@68: InetSocketAddress client=t.getRemoteAddress(); jpayne@68: InetSocketAddress server=t.getLocalAddress(); jpayne@68: jpayne@68: if(printIP){System.err.println(client+"\t"+server);} jpayne@68: jpayne@68: //This is for IPv4, class A. Probably extends outside of Berkeley. jpayne@68: String clientAddress=client.toString(); jpayne@68: String serverAddress=server.toString(); jpayne@68: jpayne@68: if(clientAddress.contains("127.0.0.1")){//TODO: contains versus startsWith? jpayne@68: Headers requestHeaders=t.getRequestHeaders(); jpayne@68: jpayne@68: if(printHeaders){ jpayne@68: Headers responseHeaders=t.getResponseHeaders(); jpayne@68: System.err.println("\nRequest: "); jpayne@68: for(Entry> entry : requestHeaders.entrySet()){ jpayne@68: System.err.println(entry.getKey()+" -> "+entry.getValue()); jpayne@68: } jpayne@68: System.err.println("\nResponse: "); jpayne@68: for(Entry> entry : responseHeaders.entrySet()){ jpayne@68: System.err.println(entry.getKey()+" -> "+entry.getValue()); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: final String xff=requestHeaders.getFirst("X-forwarded-for"); jpayne@68: if(xff!=null){ jpayne@68: if(xff.startsWith(prefix)){return true;} jpayne@68: clientAddress=xff; jpayne@68: }else{ jpayne@68: return allowLocalHost; jpayne@68: } jpayne@68: }else{ jpayne@68: if(clientAddress.startsWith(prefix)){return true;} jpayne@68: } jpayne@68: jpayne@68: //Makes sure they match up to the first delimiter jpayne@68: //TODO: This needs to be reviewed jpayne@68: for(int i=0, max=Tools.max(clientAddress.length(), serverAddress.length()); i listDirectory(String baseAddress, final int retries){ jpayne@68: // System.err.println("listDirectory '"+baseAddress+"'"); jpayne@68: while(baseAddress.endsWith("/")){baseAddress=baseAddress.substring(0, baseAddress.length()-1);} jpayne@68: String baseAddress2=baseAddress.substring(0, baseAddress.lastIndexOf('/')+1); jpayne@68: String address=baseAddress+";type=d"; jpayne@68: ArrayList list=new ArrayList(); jpayne@68: boolean success=false; jpayne@68: for(int i=Tools.min(0, retries); !success && i<=retries; i++) { jpayne@68: try { jpayne@68: // System.err.println("URL '"+address+"'"); jpayne@68: URL url=new URL(address); jpayne@68: URLConnection connection=url.openConnection(); jpayne@68: InputStream is=connection.getInputStream(); jpayne@68: BufferedReader br=new BufferedReader(new InputStreamReader(is)); jpayne@68: jpayne@68: String line=null; jpayne@68: while((line=br.readLine())!=null) { jpayne@68: list.add(baseAddress2+line); jpayne@68: } jpayne@68: jpayne@68: is.close(); jpayne@68: success=true; jpayne@68: } catch (IOException e) { jpayne@68: e.printStackTrace(); jpayne@68: if(i readFTPFile(String address) throws Exception{ jpayne@68: address=PercentEncoding.commonSymbolToCode(address); jpayne@68: URL url = new URL(address); jpayne@68: URLConnection conn = url.openConnection(); jpayne@68: jpayne@68: BufferedReader reader = new BufferedReader(new InputStreamReader( jpayne@68: conn.getInputStream())); jpayne@68: ArrayList list=new ArrayList(); jpayne@68: for(String s=reader.readLine(); s!=null; s=reader.readLine()){ jpayne@68: list.add(s); jpayne@68: } jpayne@68: return list; jpayne@68: } jpayne@68: jpayne@68: /** Don't print caught exceptions */ jpayne@68: public static boolean suppressErrors=false; jpayne@68: jpayne@68: }