[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r20837: {} added asocks subproject to android svn tree (in projects/android/trunk: . asocks asocks/src asocks/src/net asocks/src/net/sourceforge asocks/src/net/sourceforge/jsocks asocks/src/net/sourceforge/jsocks/socks asocks/src/net/sourceforge/jsocks/socks/server asocks/src/net/sourceforge/jsocks/test)
Author: n8fr8
Date: 2009-10-25 00:59:39 -0400 (Sun, 25 Oct 2009)
New Revision: 20837
Added:
projects/android/trunk/asocks/
projects/android/trunk/asocks/BUILD
projects/android/trunk/asocks/build.xml
projects/android/trunk/asocks/src/
projects/android/trunk/asocks/src/net/
projects/android/trunk/asocks/src/net/sourceforge/
projects/android/trunk/asocks/src/net/sourceforge/jsocks/
projects/android/trunk/asocks/src/net/sourceforge/jsocks/SOCKS.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.gif
projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.lnk
projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksServerException.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/index.html
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Authentication.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationException.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationNone.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/InetRange.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Proxy.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyMessage.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyServer.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Message.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Proxy.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5DatagramSocket.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Message.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Proxy.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksException.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksServerSocket.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksSocket.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPEncapsulation.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPRelayServer.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UserPasswordAuthentication.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/Ident.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/IdentAuthenticator.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticator.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticatorNone.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserPasswordAuthenticator.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserValidation.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/Echo.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksTest.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksUDPEcho.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestClient.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestServer.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestService.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UDPEcho.java
projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UPSOCKS.java
Log:
added asocks subproject to android svn tree
Added: projects/android/trunk/asocks/BUILD
===================================================================
--- projects/android/trunk/asocks/BUILD (rev 0)
+++ projects/android/trunk/asocks/BUILD 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,3 @@
+ant compile
+ant jar
+cp bin/jar/asocks.jar ../Orbot/libs
Added: projects/android/trunk/asocks/build.xml
===================================================================
--- projects/android/trunk/asocks/build.xml (rev 0)
+++ projects/android/trunk/asocks/build.xml 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,22 @@
+<project>
+
+ <target name="clean">
+ <delete dir="bin"/>
+ </target>
+
+ <target name="compile">
+ <mkdir dir="bin/classes"/>
+ <javac srcdir="src" destdir="bin/classes"/>
+ </target>
+
+ <target name="jar">
+ <mkdir dir="bin/jar"/>
+ <jar destfile="bin/jar/asocks.jar" basedir="bin/classes">
+ <manifest>
+ </manifest>
+ </jar>
+ </target>
+
+
+</project>
+
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SOCKS.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/SOCKS.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/SOCKS.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,257 @@
+package net.sourceforge.jsocks;
+
+import java.util.*;
+import java.io.*;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import net.*;
+import net.sourceforge.jsocks.socks.*;
+import net.sourceforge.jsocks.socks.server.*;
+
+public class SOCKS{
+
+ static public void usage(){
+ System.out.println(
+ "Usage: java SOCKS [inifile1 inifile2 ...]\n"+
+ "If none inifile is given, uses socks.properties.\n"
+ );
+ }
+
+ static public void main(String[] args){
+
+ String[] file_names;
+ int port=1080;
+ String logFile = null;
+ String host = null;
+
+ IdentAuthenticator auth = new IdentAuthenticator();
+ OutputStream log = null;
+ InetAddress localIP = null;
+
+ if(args.length == 0){
+ file_names = new String[1];
+ file_names[0] = "socks.properties";
+ }else{
+ file_names = args;
+ }
+
+
+ inform("Loading properties");
+ for(int i=0;i<file_names.length;++i){
+
+ inform("Reading file "+file_names[i]);
+
+ Properties pr = loadProperties(file_names[i]);
+ if(pr==null){
+ System.err.println("Loading of properties from "+
+ file_names[i]+"failed.");
+ usage();
+ return;
+ }
+ if(!addAuth(auth,pr)){
+ System.err.println("Error in file "+file_names[i]+".");
+ usage();
+ return;
+ }
+ //First file should contain all global settings,
+ // like port and host and log.
+ if(i==0){
+ String port_s = (String) pr.get("port");
+ if(port_s != null)
+ try{
+ port = Integer.parseInt(port_s);
+ }catch(NumberFormatException nfe){
+ System.err.println("Can't parse port: "+port_s);
+ return;
+ }
+
+ serverInit(pr);
+ logFile = (String) pr.get("log");
+ host = (String) pr.get("host");
+ }
+
+ //inform("Props:"+pr);
+ }
+
+ if(logFile!=null){
+ if(logFile.equals("-"))
+ log = System.out;
+ else
+ try{
+ log = new FileOutputStream(logFile);
+ }catch(IOException ioe){
+ System.err.println("Can't open log file "+logFile);
+ return;
+ }
+ }
+ if(host!=null)
+ try{
+ localIP = InetAddress.getByName(host);
+ }catch(UnknownHostException uhe){
+ System.err.println("Can't resolve local ip: "+host);
+ return;
+ }
+
+
+ inform("Using Ident Authentication scheme:\n"+auth+"\n");
+ ProxyServer server = new ProxyServer(auth);
+ server.start(port,5,localIP);
+ }
+
+ static Properties loadProperties(String file_name){
+
+ Properties pr = new Properties();
+
+ try{
+ InputStream fin = new FileInputStream(file_name);
+ pr.load(fin);
+ fin.close();
+ }catch(IOException ioe){
+ return null;
+ }
+ return pr;
+ }
+
+ static boolean addAuth(IdentAuthenticator ident,Properties pr){
+
+ InetRange irange;
+
+ String range = (String) pr.get("range");
+ if(range == null) return false;
+ irange = parseInetRange(range);
+
+
+ String users = (String) pr.get("users");
+
+ if(users == null){
+ ident.add(irange,null);
+ return true;
+ }
+
+ Hashtable uhash = new Hashtable();
+
+ StringTokenizer st = new StringTokenizer(users,";");
+ while(st.hasMoreTokens())
+ uhash.put(st.nextToken(),"");
+
+ ident.add(irange,uhash);
+ return true;
+ }
+
+ /**
+ Does server initialisation.
+ */
+ public static void serverInit(Properties props){
+ int val;
+ val = readInt(props,"iddleTimeout");
+ if(val>=0){
+ ProxyServer.setIddleTimeout(val);
+ inform("Setting iddle timeout to "+val+" ms.");
+ }
+ val = readInt(props,"acceptTimeout");
+ if(val>=0){
+ ProxyServer.setAcceptTimeout(val);
+ inform("Setting accept timeout to "+val+" ms.");
+ }
+ val = readInt(props,"udpTimeout");
+ if(val>=0){
+ ProxyServer.setUDPTimeout(val);
+ inform("Setting udp timeout to "+val+" ms.");
+ }
+
+ val = readInt(props,"datagramSize");
+ if(val>=0){
+ ProxyServer.setDatagramSize(val);
+ inform("Setting datagram size to "+val+" bytes.");
+ }
+
+ proxyInit(props);
+
+ }
+
+ /**
+ Initialises proxy, if any specified.
+ */
+ static void proxyInit(Properties props){
+ String proxy_list;
+ Proxy proxy = null;
+ StringTokenizer st;
+
+ proxy_list = (String) props.get("proxy");
+ if(proxy_list == null) return;
+
+ st = new StringTokenizer(proxy_list,";");
+ while(st.hasMoreTokens()){
+ String proxy_entry = st.nextToken();
+
+ Proxy p = Proxy.parseProxy(proxy_entry);
+
+ if(p == null)
+ exit("Can't parse proxy entry:"+proxy_entry);
+
+
+ inform("Adding Proxy:"+p);
+
+ if(proxy != null)
+ p.setChainProxy(proxy);
+
+ proxy = p;
+
+ }
+ if(proxy == null) return; //Empty list
+
+ String direct_hosts = (String) props.get("directHosts");
+ if(direct_hosts!=null){
+ InetRange ir = parseInetRange(direct_hosts);
+ inform("Setting direct hosts:"+ir);
+ proxy.setDirect(ir);
+ }
+
+
+ ProxyServer.setProxy(proxy);
+ }
+ /**
+ Inits range from the string of semicolon separated ranges.
+ */
+ static InetRange parseInetRange(String source){
+ InetRange irange = new InetRange();
+
+ StringTokenizer st = new StringTokenizer(source,";");
+ while(st.hasMoreTokens())
+ irange.add(st.nextToken());
+
+ return irange;
+ }
+
+ /**
+ Integer representaion of the property named name, or -1 if one
+ is not found.
+ */
+ static int readInt(Properties props,String name){
+ int result = -1;
+ String val = (String) props.get(name);
+ if(val==null) return -1;
+ StringTokenizer st = new StringTokenizer(val);
+ if(!st.hasMoreElements()) return -1;
+ try{
+ result = Integer.parseInt(st.nextToken());
+ }catch(NumberFormatException nfe){
+ inform("Bad value for "+name+":"+val);
+ }
+ return result;
+ }
+
+//Display functions
+///////////////////
+
+ public static void inform(String s){
+ System.out.println(s);
+ }
+
+ static void exit(String msg){
+ System.err.println("Error:"+msg);
+ System.err.println("Aborting operation");
+ System.exit(0);
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.gif
===================================================================
(Binary files differ)
Property changes on: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.gif
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,386 @@
+package net.sourceforge.jsocks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.DatagramPacket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import net.sourceforge.jsocks.socks.Proxy;
+import net.sourceforge.jsocks.socks.Socks5DatagramSocket;
+import net.sourceforge.jsocks.socks.Socks5Proxy;
+import net.sourceforge.jsocks.socks.SocksServerSocket;
+import net.sourceforge.jsocks.socks.SocksSocket;
+
+public class SocksEcho
+ implements
+ Runnable
+ {
+
+//Network related members
+ Proxy proxy=null;
+ int port;
+ String host;
+ Thread net_thread=null;
+ InputStream in=null;
+ OutputStream out=null;
+ Socket sock=null;
+ ServerSocket server_sock = null;
+ Socks5DatagramSocket udp_sock;
+
+ Object net_lock = new Object();
+ int mode=COMMAND_MODE;
+
+ //Possible mode states.
+ static final int LISTEN_MODE = 0;
+ static final int CONNECT_MODE = 1;
+ static final int UDP_MODE = 2;
+ static final int COMMAND_MODE = 3;
+ static final int ABORT_MODE = 4;
+
+ //Maximum datagram size
+ static final int MAX_DATAGRAM_SIZE = 1024;
+
+// Constructors
+////////////////////////////////////
+ public SocksEcho(){
+
+
+
+ }
+
+//Runnable interface
+///////////////////////////////
+
+public void run(){
+ boolean finished_OK = true;
+ try{
+ switch(mode){
+ case UDP_MODE:
+ startUDP();
+ doUDPPipe();
+ break;
+ case LISTEN_MODE:
+ doAccept();
+ doPipe();
+ break;
+ case CONNECT_MODE:
+ doConnect();
+ doPipe();
+ break;
+ default:
+ warn("Unexpected mode in run() method");
+ }
+
+ }catch(UnknownHostException uh_ex){
+ if(mode != ABORT_MODE){
+ finished_OK = false;
+ status("Host "+host+" has no DNS entry.");
+ uh_ex.printStackTrace();
+ }
+ }catch(IOException io_ex){
+ if(mode != ABORT_MODE){
+ finished_OK = false;
+ status(""+io_ex);
+ io_ex.printStackTrace();
+ }
+ }finally{
+ if(mode == ABORT_MODE) status("Connection closed");
+ else if(finished_OK) status("Connection closed by foreign host.");
+
+ onDisconnect();
+ }
+}
+
+//Private methods
+////////////////////////////////////////////////////////////////////////
+
+// GUI event handlers.
+//////////////////////////
+
+ private void onConnect(){
+ if(mode == CONNECT_MODE){
+ status("Diconnecting...");
+ abort_connection();
+ return;
+ }else if(mode != COMMAND_MODE)
+ return;
+
+// if(!readHost()) return;
+ // if(!readPort()) return;
+
+ if(proxy == null){
+ warn("Proxy is not set");
+ onProxy();
+ return;
+ }
+
+ startNetThread(CONNECT_MODE);
+ status("Connecting to "+host+":"+port+" ...");
+
+ }
+
+ private void onDisconnect(){
+ synchronized(net_lock){
+ mode = COMMAND_MODE;
+
+ server_sock = null;
+ sock = null;
+ out = null;
+ in = null;
+ net_thread = null;
+ }
+ }
+
+ private void onAccept(){
+ if(mode == LISTEN_MODE){
+ abort_connection();
+ return;
+ }else if(mode != COMMAND_MODE) return;
+
+ // if(!readHost()) return;
+ // if(!readPort()) port = 0;
+
+ if(proxy == null){
+ warn("Proxy is not set");
+ onProxy();
+ return;
+ }
+
+ startNetThread(LISTEN_MODE);
+
+ }
+
+ private void onUDP(){
+ if(mode == UDP_MODE){
+ abort_connection();
+ return;
+ }else if(mode == ABORT_MODE) return;
+
+ if(proxy == null){
+ warn("Proxy is not set");
+ onProxy();
+ return;
+ }
+
+ startNetThread(UDP_MODE);
+ }
+
+ private void onInput(){
+ String send_string = "";
+ switch(mode){
+ case ABORT_MODE: //Fall through
+ case COMMAND_MODE:
+ return;
+ case CONNECT_MODE://Fall through
+ case LISTEN_MODE:
+ synchronized(net_lock){
+ if(out == null) return;
+ send(send_string);
+ }
+ break;
+ case UDP_MODE:
+ // if(!readHost()) return;
+ // if(!readPort()) return;
+ sendUDP(send_string,host,port);
+ break;
+ default:
+ print("Unknown mode in onInput():"+mode);
+
+ }
+ print(send_string);
+ }
+
+ private void onClear(){
+
+ }
+ private void onProxy(){
+ Proxy p;
+ p = null;//socks_dialog.getProxy(proxy);
+ if(p != null) proxy = p;
+ if( proxy != null && proxy instanceof Socks5Proxy)
+ ((Socks5Proxy) proxy).resolveAddrLocally(false);
+ }
+ private void onQuit(){
+
+ System.exit(0);
+ }
+
+//Data retrieval functions
+//////////////////////////
+
+ /**
+ * Reads the port field, returns false if parsing fails.
+ */
+ private boolean readPort(int newPort){
+ try{
+ port = newPort;
+ }catch(NumberFormatException nfe){
+ warn("Port invalid!");
+ return false;
+ }
+ return true;
+ }
+ private boolean readHost(){
+ host = "";
+ host.trim();
+ if(host.length() < 1){
+ warn("Host is not set");
+ return false;
+ }
+ return true;
+ }
+
+//Display functions
+///////////////////
+
+ private void status(String status){
+
+ }
+ private void println(String s){
+
+ }
+ private void print(String s){
+
+ }
+ private void warn(String s){
+ status(s);
+ //System.err.println(s);
+ }
+
+//Network related functions
+////////////////////////////
+
+ private void startNetThread(int m){
+ mode = m;
+ net_thread = new Thread(this);
+ net_thread.start();
+ }
+
+ private void abort_connection(){
+ synchronized(net_lock){
+ if(mode == COMMAND_MODE) return;
+ mode = ABORT_MODE;
+ if(net_thread!=null){
+ try{
+ if(sock!=null) sock.close();
+ if(server_sock!=null) server_sock.close();
+ if(udp_sock!=null) udp_sock.close();
+ }catch(IOException ioe){
+ }
+ net_thread.interrupt();
+ net_thread = null;
+ }
+ }
+ }
+
+ private void doAccept() throws IOException{
+
+ println("Trying to accept from "+host);
+ status("Trying to accept from "+host);
+ println("Using proxy:"+proxy);
+ server_sock = new SocksServerSocket(proxy,host,port);
+
+ //server_sock.setSoTimeout(30000);
+
+ println("Listenning on: "+server_sock.getInetAddress()+
+ ":" +server_sock.getLocalPort());
+ sock = server_sock.accept();
+ println("Accepted from:"+sock.getInetAddress()+":"+
+ sock.getPort());
+
+ status("Accepted from:"+sock.getInetAddress().getHostAddress()
+ +":"+sock.getPort());
+
+ server_sock.close(); //Even though this doesn't do anything
+ }
+ private void doConnect() throws IOException{
+ println("Trying to connect to:"+host+":"+port);
+ println("Using proxy:"+proxy);
+ sock = new SocksSocket(proxy,host,port);
+ println("Connected to:"+sock.getInetAddress()+":"+port);
+ status("Connected to: "+sock.getInetAddress().getHostAddress()
+ +":" +port);
+ println("Via-Proxy:"+sock.getLocalAddress()+":"+
+ sock.getLocalPort());
+
+ }
+ private void doPipe() throws IOException{
+ out = sock.getOutputStream();
+ in = sock.getInputStream();
+
+ byte[] buf = new byte[1024];
+ int bytes_read;
+ while((bytes_read = in.read(buf)) > 0){
+ print(new String(buf,0,bytes_read));
+ }
+
+ }
+ private void startUDP() throws IOException{
+ udp_sock = new Socks5DatagramSocket(proxy,0,null);
+ println("UDP started on "+udp_sock.getLocalAddress()+":"+
+ udp_sock.getLocalPort());
+ status("UDP:"+udp_sock.getLocalAddress().getHostAddress()+":"
+ +udp_sock.getLocalPort());
+ }
+
+ private void doUDPPipe() throws IOException{
+ DatagramPacket dp = new DatagramPacket(new byte[MAX_DATAGRAM_SIZE],
+ MAX_DATAGRAM_SIZE);
+ while(true){
+ udp_sock.receive(dp);
+ print("UDP\n"+
+ "From:"+dp.getAddress()+":"+dp.getPort()+"\n"+
+ "\n"+
+ //Java 1.2
+ //new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
+ //Java 1.1
+ new String(dp.getData(),0,dp.getLength())+"\n"
+ );
+ dp.setLength(MAX_DATAGRAM_SIZE);
+ }
+ }
+
+ private void sendUDP(String message,String host,int port){
+ if(!udp_sock.isProxyAlive(100)){
+ status("Proxy closed connection");
+ abort_connection();
+ return;
+ }
+
+ try{
+ byte[] data = message.getBytes();
+ DatagramPacket dp = new DatagramPacket(data,data.length,null,port);
+ udp_sock.send(dp,host);
+ }catch(UnknownHostException uhe){
+ status("Host "+host+" has no DNS entry.");
+ }catch(IOException ioe){
+ status("IOException:"+ioe);
+ abort_connection();
+ }
+
+ }
+
+ private void send(String s){
+ try{
+ out.write(s.getBytes());
+ }catch(IOException io_ex){
+ println("IOException:"+io_ex);
+ abort_connection();
+ }
+ }
+
+
+
+
+
+
+// Main
+////////////////////////////////////
+ public static void main(String[] args){
+ SocksEcho socksecho = new SocksEcho();
+
+ }
+ }//end class
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.lnk
===================================================================
(Binary files differ)
Property changes on: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksEcho.lnk
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksServerException.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksServerException.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/SocksServerException.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,19 @@
+package net.sourceforge.jsocks;
+
+public class SocksServerException extends Exception {
+
+ String message;
+
+ public SocksServerException(Exception e) {
+ this.message = e.getMessage();
+ }
+
+ public SocksServerException(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/index.html
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/index.html (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/index.html 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,15 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Cache-Control" content="no-cache" />
+ <meta http-equiv="Pragma" content="no-cache" />
+ <title>Moma</title>
+
+<link href='include_homepage/styles/display_v4.css'
+ type='text/css' rel='stylesheet'></link>
+<link href='include_homepage/styles/themes/bright2.css' type='text/css' rel='stylesheet' /> <style type='text/css'>
+ </style>
+ <script type="text/javascript"
+ src="include_homepage/scripts/common_v2.js"></script>
+ <
\ No newline at end of file
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Authentication.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Authentication.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Authentication.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,34 @@
+package net.sourceforge.jsocks.socks;
+
+/**
+ The Authentication interface provides for performing method specific
+ authentication for SOCKS5 connections.
+*/
+public interface Authentication{
+ /**
+ This method is called when SOCKS5 server have selected a particular
+ authentication method, for whch an implementaion have been registered.
+
+ <p>
+ This method should return an array {inputstream,outputstream
+ [,UDPEncapsulation]}. The reason for that is that SOCKS5 protocol
+ allows to have method specific encapsulation of data on the socket for
+ purposes of integrity or security. And this encapsulation should be
+ performed by those streams returned from the method. It is also possible
+ to encapsulate datagrams. If authentication method supports such
+ encapsulation an instance of the UDPEncapsulation interface should be
+ returned as third element of the array, otherwise either null should be
+ returned as third element, or array should contain only 2 elements.
+
+ @param methodId Authentication method selected by the server.
+ @param proxySocket Socket used to conect to the proxy.
+ @return Two or three element array containing
+ Input/Output streams which should be used on this connection.
+ Third argument is optional and should contain an instance
+ of UDPEncapsulation. It should be provided if the authentication
+ method used requires any encapsulation to be done on the
+ datagrams.
+ */
+ Object[] doSocksAuthentication(int methodId,java.net.Socket proxySocket)
+ throws java.io.IOException;
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationException.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationException.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationException.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,92 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package net.sourceforge.jsocks.socks;
+
+/**
+ * Exception thrown by various socks classes to indicate errors
+ * with protocol or unsuccessful server responses.
+ *
+ * @author rayc@xxxxxxxxxx (Ray Colline)
+ */
+public class AuthenticationException extends Throwable {
+
+ private AuthErrorType errorType;
+ private String errorString;
+
+ /**
+ * Create an AuthenticationException with the specified type
+ *
+ * @param errorType an enum denoting what kind of auth error.
+ */
+ public AuthenticationException(AuthErrorType errorType) {
+ this.errorType = errorType;
+ this.errorString = errorType.toString();
+ }
+
+ /**
+ * Create an AuthenticationException with both the specified type and
+ * a free-form message
+ *
+ * @param errorType an enum denoting what kind of auth error.
+ * @param errorString a specific string detailing the error.
+ */
+ public AuthenticationException(AuthErrorType errorType,
+ String errorString) {
+ this.errorType = errorType;
+ this.errorString = errorString;
+ }
+
+ /**
+ * Get the error type associated with this exception.
+ *
+ * @return errorType the type associated with this exception.
+ */
+ public AuthErrorType getErrorType() {
+ return errorType;
+ }
+
+ /**
+ * Get human readable representation of this exception.
+ *
+ * @return String representation of this exception.
+ */
+ @Override
+ public String toString() {
+ return errorString;
+ }
+
+ /**
+ * Returns the message associated with this exception
+ *
+ * @return String the error string.
+ */
+ @Override
+ public String getMessage() {
+ return errorString;
+ }
+
+ /**
+ * List of Authentication error types.
+ *
+ * @author rayc@xxxxxxxxxx (Ray Colline)
+ */
+ public enum AuthErrorType {
+ MALFORMED_REQUEST,
+ PASSWORD_TOO_LONG;
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationNone.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationNone.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/AuthenticationNone.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,17 @@
+package net.sourceforge.jsocks.socks;
+
+/**
+ SOCKS5 none authentication. Dummy class does almost nothing.
+*/
+public class AuthenticationNone implements Authentication{
+
+ public Object[] doSocksAuthentication(int methodId,
+ java.net.Socket proxySocket)
+ throws java.io.IOException{
+
+ if(methodId!=0) return null;
+
+ return new Object[] { proxySocket.getInputStream(),
+ proxySocket.getOutputStream()};
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/InetRange.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/InetRange.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/InetRange.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,442 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+
+/**
+ * Class InetRange provides the means of defining the range of inetaddresses.
+ * It's used by Proxy class to store and look up addresses of machines, that
+ * should be contacted directly rather then through the proxy.
+ * <P>
+ * InetRange provides several methods to add either standalone addresses, or
+ * ranges (e.g. 100.200.300.0:100.200.300.255, which covers all addresses
+ * on on someones local network). It also provides methods for checking wether
+ * given address is in this range. Any number of ranges and standalone
+ * addresses can be added to the range.
+ */
+public class InetRange implements Cloneable{
+
+ Hashtable host_names;
+ Vector all;
+ Vector end_names;
+
+ boolean useSeparateThread = true;
+
+ /**
+ * Creates the empty range.
+ */
+ public InetRange(){
+ all = new Vector();
+ host_names = new Hashtable();
+ end_names = new Vector();
+ }
+
+ /**
+ * Adds another host or range to this range.
+ The String can be one of those:
+ <UL>
+ <li> Host name. eg.(Athena.myhost.com or 45.54.56.65)
+
+ <li> Range in the form .myhost.net.au <BR>
+ In which case anything that ends with .myhost.net.au will
+ be considered in the range.
+
+ <li> Range in the form ddd.ddd.ddd. <BR>
+ This will be treated as range ddd.ddd.ddd.0 to ddd.ddd.ddd.255.
+ It is not necessary to specify 3 first bytes you can use just
+ one or two. For example 130. will cover address between 130.0.0.0
+ and 13.255.255.255.
+
+ <li> Range in the form host_from[: \t\n\r\f]host_to. <br>
+ That is two hostnames or ips separated by either whitespace
+ or colon.
+ </UL>
+ */
+ public synchronized boolean add(String s){
+ if(s == null) return false;
+
+ s = s.trim();
+ if(s.length() == 0) return false;
+
+ Object[] entry;
+
+ if(s.charAt(s.length()-1) == '.'){
+ //thing like: 111.222.33.
+ //it is being treated as range 111.222.33.000 - 111.222.33.255
+
+ int[] addr = ip2intarray(s);
+ long from,to;
+ from = to = 0;
+
+ if(addr == null) return false;
+ for(int i = 0; i< 4;++i){
+ if(addr[i]>=0)
+ from += (((long)addr[i]) << 8*(3-i));
+ else{
+ to = from;
+ while(i<4)
+ to += 255l << 8*(3-i++);
+ break;
+ }
+ }
+ entry = new Object[] {s,null,new Long(from),new Long(to)};
+ all.addElement(entry);
+
+ }else if(s.charAt(0) == '.'){
+ //Thing like: .myhost.com
+
+ end_names.addElement(s);
+ all.addElement(new Object[]{s,null,null,null});
+ }else{
+ StringTokenizer tokens = new StringTokenizer(s," \t\r\n\f:");
+ if(tokens.countTokens() > 1){
+ entry = new Object[] {s,null,null,null};
+ resolve(entry,tokens.nextToken(),tokens.nextToken());
+ all.addElement(entry);
+ }else{
+ entry = new Object[] {s,null,null,null};
+ all.addElement(entry);
+ host_names.put(s,entry);
+ resolve(entry);
+ }
+
+ }
+
+ return true;
+ }
+
+ /**
+ * Adds another ip for this range.
+ @param ip IP os the host which should be added to this range.
+ */
+ public synchronized void add(InetAddress ip){
+ long from, to;
+ from = to = ip2long(ip);
+ all.addElement(new Object[]{ip.getHostName(),ip,new Long(from),
+ new Long(to)});
+ }
+
+ /**
+ * Adds another range of ips for this range.Any host with ip address
+ greater than or equal to the address of from and smaller than or equal
+ to the address of to will be included in the range.
+ @param from IP from where range starts(including).
+ @param to IP where range ends(including).
+ */
+ public synchronized void add(InetAddress from,InetAddress to){
+ all.addElement(new Object[]{from.getHostAddress()+":"+to.getHostAddress()
+ ,null,new Long(ip2long(from)),
+ new Long(ip2long(to))});
+ }
+
+ /**
+ * Checks wether the givan host is in the range. Attempts to resolve
+ host name if required.
+ @param host Host name to check.
+ @return true If host is in the range, false otherwise.
+ * @see InetRange#contains(String,boolean)
+ */
+ public synchronized boolean contains(String host){
+ return contains(host,true);
+ }
+
+ /**
+ * Checks wether the given host is in the range.
+ * <P>
+ * Algorithm: <BR>
+ * <ol>
+ * <li>Look up if the hostname is in the range (in the Hashtable).
+ * <li>Check if it ends with one of the speciefied endings.
+ * <li>Check if it is ip(eg.130.220.35.98). If it is check if it is
+ * in the range.
+ * <li>If attemptResolve is true, host is name, rather than ip, and
+ * all previous attempts failed, try to resolve the hostname, and
+ * check wether the ip associated with the host is in the range.It
+ * also repeats all previos steps with the hostname obtained from
+ * InetAddress, but the name is not allways the full name,it is
+ * quite likely to be the same. Well it was on my machine.
+ * </ol>
+ @param host Host name to check.
+ @param attemptResolve Wether to lookup ip address which corresponds
+ to the host,if required.
+ @return true If host is in the range, false otherwise.
+ */
+ public synchronized boolean contains(String host,boolean attemptResolve){
+ if(all.size() ==0) return false; //Empty range
+
+ host = host.trim();
+ if(host.length() == 0) return false;
+
+ if(checkHost(host)) return true;
+ if(checkHostEnding(host)) return true;
+
+ long l = host2long(host);
+ if(l >=0) return contains(l);
+
+ if(!attemptResolve) return false;
+
+ try{
+ InetAddress ip = InetAddress.getByName(host);
+ return contains(ip);
+ }catch(UnknownHostException uhe){
+
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks wether the given ip is in the range.
+ @param ip Address of the host to check.
+ @return true If host is in the range, false otherwise.
+ */
+ public synchronized boolean contains(InetAddress ip){
+ if(checkHostEnding(ip.getHostName())) return true;
+ if(checkHost(ip.getHostName())) return true;
+ return contains(ip2long(ip));
+ }
+ /**
+ Get all entries in the range as strings. <BR>
+ These strings can be used to delete entries from the range
+ with remove function.
+ @return Array of entries as strings.
+ @see InetRange#remove(String)
+ */
+ public synchronized String[] getAll(){
+ int size = all.size();
+ Object entry[];
+ String all_names[] = new String[size];
+
+ for(int i=0;i<size;++i){
+ entry = (Object[]) all.elementAt(i);
+ all_names[i] = (String) entry[0];
+ }
+ return all_names;
+ }
+ /**
+ Removes an entry from this range.<BR>
+ @param s Entry to remove.
+ @return true if successfull.
+ */
+ public synchronized boolean remove(String s){
+ Iterator iterator = all.iterator();
+
+ while(iterator.hasNext()){
+ Object[] entry = (Object[]) iterator.next();
+ if(s.equals(entry[0])){
+ all.removeElement(entry);
+ end_names.removeElement(s);
+ host_names.remove(s);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Get string representaion of this Range.*/
+ public String toString(){
+ String all[] = getAll();
+ if(all.length == 0) return "";
+
+ String s = all[0];
+ for(int i=1;i<all.length;++i)
+ s += "; "+all[i];
+ return s;
+ }
+
+ /** Creates a clone of this Object*/
+ public Object clone(){
+ InetRange new_range = new InetRange();
+ new_range.all = (Vector)all.clone();
+ new_range.end_names = (Vector) end_names.clone();
+ new_range.host_names = (Hashtable)host_names.clone();
+ return new_range;
+ }
+
+
+//Private methods
+/////////////////
+ /**
+ * Same as previous but used internally, to avoid
+ * unnecessary convertion of IPs, when checking subranges
+ */
+ private synchronized boolean contains(long ip){
+ Iterator iterator = all.iterator();
+ while(iterator.hasNext()){
+ Object[] obj = (Object[]) iterator.next();
+ Long from = obj[2]==null?null:(Long)obj[2];
+ Long to = obj[3]==null?null:(Long)obj[3];
+ if(from != null && from.longValue()<= ip
+ && to.longValue() >= ip) return true;
+
+ }
+ return false;
+ }
+
+ private boolean checkHost(String host){
+ return host_names.containsKey(host);
+ }
+ private boolean checkHostEnding(String host){
+ Iterator iterator = end_names.iterator();
+ while(iterator.hasNext()){
+ if(host.endsWith((String) iterator.next())) return true;
+ }
+ return false;
+ }
+ private void resolve(Object[] entry){
+ //First check if it's in the form ddd.ddd.ddd.ddd.
+ long ip = host2long((String) entry[0]);
+ if(ip >= 0){
+ entry[2] = entry[3] = new Long(ip);
+ }else{
+ InetRangeResolver res = new InetRangeResolver(entry);
+ res.resolve(useSeparateThread);
+ }
+ }
+ private void resolve(Object[] entry,String from,String to){
+ long f,t;
+ if((f=host2long(from))>= 0 && (t=host2long(to)) >= 0){
+ entry[2] = new Long(f);
+ entry[3] = new Long(t);
+ }else{
+ InetRangeResolver res = new InetRangeResolver(entry,from,to);
+ res.resolve(useSeparateThread);
+ }
+ }
+
+
+
+//Class methods
+///////////////
+
+ //Converts ipv4 to long value(unsigned int)
+ ///////////////////////////////////////////
+ static long ip2long(InetAddress ip){
+ long l=0;
+ byte[] addr = ip.getAddress();
+
+ if(addr.length ==4){ //IPV4
+ for(int i=0;i<4;++i)
+ l += (((long)addr[i] &0xFF) << 8*(3-i));
+ }else{ //IPV6
+ return 0; //Have no idea how to deal with those
+ }
+ return l;
+ }
+
+
+ long host2long(String host){
+ long ip=0;
+
+ //check if it's ddd.ddd.ddd.ddd
+ if(!Character.isDigit(host.charAt(0))) return -1;
+
+ int[] addr = ip2intarray(host);
+ if(addr == null) return -1;
+
+ for(int i=0;i<addr.length;++i)
+ ip += ((long)(addr[i]>=0 ? addr[i] : 0)) << 8*(3-i);
+
+ return ip;
+ }
+
+ static int[] ip2intarray(String host){
+ int[] address = {-1,-1,-1,-1};
+ int i=0;
+ StringTokenizer tokens = new StringTokenizer(host,".");
+ if(tokens.countTokens() > 4) return null;
+ while(tokens.hasMoreTokens()){
+ try{
+ address[i++] = Integer.parseInt(tokens.nextToken()) & 0xFF;
+ }catch(NumberFormatException nfe){
+ return null;
+ }
+
+ }
+ return address;
+ }
+
+
+/*
+//* This was the test main function
+//**********************************
+
+ public static void main(String args[])throws UnknownHostException{
+ int i;
+
+ InetRange ir = new InetRange();
+
+
+ for(i=0;i<args.length;++i){
+ System.out.println("Adding:" + args[i]);
+ ir.add(args[i]);
+ }
+
+ String host;
+ java.io.DataInputStream din = new java.io.DataInputStream(System.in);
+ try{
+ host = din.readLine();
+ while(host!=null){
+ if(ir.contains(host)){
+ System.out.println("Range contains ip:"+host);
+ }else{
+ System.out.println(host+" is not in the range");
+ }
+ host = din.readLine();
+ }
+ }catch(java.io.IOException io_ex){
+ io_ex.printStackTrace();
+ }
+ }
+********************/
+
+}
+
+
+class InetRangeResolver implements Runnable{
+
+ Object[] entry;
+
+ String from, to;
+
+ InetRangeResolver(Object[] entry){
+ this.entry = entry;
+ from = to = null;
+ }
+ InetRangeResolver(Object[] entry,String from,String to){
+ this.entry = entry;
+ this.from = from;
+ this.to = to;
+ }
+ public final void resolve(){
+ resolve(true);
+ }
+ public final void resolve(boolean inSeparateThread){
+ if(inSeparateThread){
+ Thread t = new Thread(this);
+ t.start();
+ }else
+ run();
+
+ }
+ public void run(){
+ try{
+ if(from == null){
+ InetAddress ip = InetAddress.getByName((String) entry[0]);
+ entry[1] = ip;
+ Long l = new Long(InetRange.ip2long(ip));
+ entry[2] = entry[3] = l;
+ }else{
+ InetAddress f = InetAddress.getByName(from);
+ InetAddress t = InetAddress.getByName(to);
+ entry[2] = new Long(InetRange.ip2long(f));
+ entry[3] = new Long(InetRange.ip2long(t));
+
+ }
+ }catch(UnknownHostException uhe){
+ //System.err.println("Resolve failed for "+from+','+to+','+entry[0]);
+ }
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Proxy.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Proxy.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Proxy.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,491 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+
+/**
+ Abstract class Proxy, base for classes Socks4Proxy and Socks5Proxy.
+ Defines methods for specifying default proxy, to be
+ used by all classes of this package.
+*/
+
+public abstract class Proxy{
+
+//Data members
+ protected InetRange directHosts = new InetRange();
+
+ protected InetAddress proxyIP = null;
+ protected String proxyHost = null;
+ protected int proxyPort;
+ protected Socket proxySocket = null;
+
+ protected InputStream in;
+ protected OutputStream out;
+
+ protected int version;
+
+ protected Proxy chainProxy = null;
+
+
+//Protected static/class variables
+ protected static Proxy defaultProxy = null;
+
+//Constructors
+//====================
+ Proxy(Proxy chainProxy,
+ String proxyHost,int proxyPort)throws UnknownHostException{
+ this.chainProxy = chainProxy;
+ this.proxyHost = proxyHost;
+
+ if(chainProxy == null)
+ this.proxyIP = InetAddress.getByName(proxyHost);
+
+ this.proxyPort = proxyPort;
+ }
+
+
+ Proxy(String proxyHost,int proxyPort)throws UnknownHostException{
+ this(null,proxyHost,proxyPort);
+ }
+
+ Proxy(Proxy chainProxy,InetAddress proxyIP,int proxyPort){
+ this.chainProxy = chainProxy;
+ this.proxyIP = proxyIP;
+ this.proxyPort = proxyPort;
+ }
+
+ Proxy(InetAddress proxyIP,int proxyPort){
+ this(null,proxyIP,proxyPort);
+ }
+
+ Proxy(Proxy p){
+ this.proxyIP = p.proxyIP;
+ this.proxyPort = p.proxyPort;
+ this.version = p.version;
+ this.directHosts = p.directHosts;
+ }
+
+//Public instance methods
+//========================
+
+ /**
+ Get the port on which proxy server is running.
+ * @return Proxy port.
+ */
+ public int getPort(){
+ return proxyPort;
+ }
+ /**
+ Get the ip address of the proxy server host.
+ * @return Proxy InetAddress.
+ */
+ public InetAddress getInetAddress(){
+ return proxyIP;
+ }
+ /**
+ * Adds given ip to the list of direct addresses.
+ * This machine will be accessed without using proxy.
+ */
+ public void addDirect(InetAddress ip){
+ directHosts.add(ip);
+ }
+ /**
+ * Adds host to the list of direct addresses.
+ * This machine will be accessed without using proxy.
+ */
+ public boolean addDirect(String host){
+ return directHosts.add(host);
+ }
+ /**
+ * Adds given range of addresses to the lsit of direct addresses,
+ * machines within this range will be accessed without using proxy.
+ */
+ public void addDirect(InetAddress from,InetAddress to){
+ directHosts.add(from,to);
+ }
+ /**
+ * Sets given InetRange as the list of direct address, previous
+ * list will be discarded, any changes done previously with
+ * addDirect(Inetaddress) will be lost.
+ * The machines in this range will be accessed without using proxy.
+ * @param ir InetRange which should be used to look up direct addresses.
+ * @see InetRange
+ */
+ public void setDirect(InetRange ir){
+ directHosts = ir;
+ }
+
+ /**
+ Get the list of direct hosts.
+ * @return Current range of direct address as InetRange object.
+ * @see InetRange
+ */
+ public InetRange getDirect(){
+ return directHosts;
+ }
+ /**
+ Check wether the given host is on the list of direct address.
+ @param host Host name to check.
+ * @return true if the given host is specified as the direct addresses.
+ */
+ public boolean isDirect(String host){
+ return directHosts.contains(host);
+ }
+ /**
+ Check wether the given host is on the list of direct addresses.
+ @param host Host address to check.
+ * @return true if the given host is specified as the direct address.
+ */
+ public boolean isDirect(InetAddress host){
+ return directHosts.contains(host);
+ }
+ /**
+ Set the proxy which should be used to connect to given proxy.
+ @param chainProxy Proxy to use to connect to this proxy.
+ */
+ public void setChainProxy(Proxy chainProxy){
+ this.chainProxy = chainProxy;
+ }
+
+ /**
+ Get proxy which is used to connect to this proxy.
+ @return Proxy which is used to connect to this proxy, or null
+ if proxy is to be contacted directly.
+ */
+ public Proxy getChainProxy(){
+ return chainProxy;
+ }
+
+ /**
+ Get string representation of this proxy.
+ * @returns string in the form:proxyHost:proxyPort \t Version versionNumber
+ */
+ public String toString(){
+ return (""+proxyIP.getHostName()+":"+proxyPort+"\tVersion "+version);
+ }
+
+
+//Public Static(Class) Methods
+//==============================
+
+ /**
+ * Sets SOCKS4 proxy as default.
+ @param hostName Host name on which SOCKS4 server is running.
+ @param port Port on which SOCKS4 server is running.
+ @param user Username to use for communications with proxy.
+ */
+ public static void setDefaultProxy(String hostName,int port,String user)
+ throws UnknownHostException{
+ defaultProxy = new Socks4Proxy(hostName,port,user);
+ }
+
+ /**
+ * Sets SOCKS4 proxy as default.
+ @param ipAddress Host address on which SOCKS4 server is running.
+ @param port Port on which SOCKS4 server is running.
+ @param user Username to use for communications with proxy.
+ */
+ public static void setDefaultProxy(InetAddress ipAddress,int port,
+ String user){
+ defaultProxy = new Socks4Proxy(ipAddress,port,user);
+ }
+ /**
+ * Sets SOCKS5 proxy as default.
+ * Default proxy only supports no-authentication.
+ @param hostName Host name on which SOCKS5 server is running.
+ @param port Port on which SOCKS5 server is running.
+ */
+ public static void setDefaultProxy(String hostName,int port)
+ throws UnknownHostException{
+ defaultProxy = new Socks5Proxy(hostName,port);
+ }
+ /**
+ * Sets SOCKS5 proxy as default.
+ * Default proxy only supports no-authentication.
+ @param ipAddress Host address on which SOCKS5 server is running.
+ @param port Port on which SOCKS5 server is running.
+ */
+ public static void setDefaultProxy(InetAddress ipAddress,int port){
+ defaultProxy = new Socks5Proxy(ipAddress,port);
+ }
+ /**
+ * Sets default proxy.
+ @param p Proxy to use as default proxy.
+ */
+ public static void setDefaultProxy(Proxy p){
+ defaultProxy = p;
+ }
+
+ /**
+ Get current default proxy.
+ * @return Current default proxy, or null if none is set.
+ */
+ public static Proxy getDefaultProxy(){
+ return defaultProxy;
+ }
+
+ /**
+ Parses strings in the form: host[:port:user:password], and creates
+ proxy from information obtained from parsing.
+ <p>
+ Defaults: port = 1080.<br>
+ If user specified but not password, creates Socks4Proxy, if user
+ not specified creates Socks5Proxy, if both user and password are
+ speciefied creates Socks5Proxy with user/password authentication.
+ @param proxy_entry String in the form host[:port:user:password]
+ @return Proxy created from the string, null if entry was somehow
+ invalid(host unknown for example, or empty string)
+ */
+ public static Proxy parseProxy(String proxy_entry){
+
+ String proxy_host;
+ int proxy_port = 1080;
+ String proxy_user = null;
+ String proxy_password = null;
+ Proxy proxy;
+
+ java.util.StringTokenizer st = new java.util.StringTokenizer(
+ proxy_entry,":");
+ if(st.countTokens() < 1) return null;
+
+ proxy_host = st.nextToken();
+ if(st.hasMoreTokens())
+ try{
+ proxy_port = Integer.parseInt(st.nextToken().trim());
+ }catch(NumberFormatException nfe){}
+
+ if(st.hasMoreTokens())
+ proxy_user = st.nextToken();
+
+ if(st.hasMoreTokens())
+ proxy_password = st.nextToken();
+
+ try{
+ if(proxy_user == null)
+ proxy = new Socks5Proxy(proxy_host,proxy_port);
+ else if(proxy_password == null)
+ proxy = new Socks4Proxy(proxy_host,proxy_port,proxy_user);
+ else{
+ proxy = new Socks5Proxy(proxy_host,proxy_port);
+ UserPasswordAuthentication upa = new UserPasswordAuthentication(
+ proxy_user, proxy_password);
+
+ ((Socks5Proxy)proxy).setAuthenticationMethod(upa.METHOD_ID,upa);
+ }
+ }catch(UnknownHostException uhe){
+ return null;
+ }
+
+ return proxy;
+ }
+
+
+//Protected Methods
+//=================
+
+ protected void startSession()throws SocksException{
+ try{
+ if(chainProxy == null)
+ proxySocket = new Socket(proxyIP,proxyPort);
+ else if(proxyIP != null)
+ proxySocket = new SocksSocket(chainProxy,proxyIP,proxyPort);
+ else
+ proxySocket = new SocksSocket(chainProxy,proxyHost,proxyPort);
+
+ in = proxySocket.getInputStream();
+ out = proxySocket.getOutputStream();
+ }catch(SocksException se){
+ throw se;
+ }catch(IOException io_ex){
+ throw new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex);
+ }
+ }
+
+ protected abstract Proxy copy();
+ protected abstract ProxyMessage formMessage(int cmd,InetAddress ip,int port);
+ protected abstract ProxyMessage formMessage(int cmd,String host,int port)
+ throws UnknownHostException;
+ protected abstract ProxyMessage formMessage(InputStream in)
+ throws SocksException,
+ IOException;
+
+
+ protected ProxyMessage connect(InetAddress ip,int port)
+ throws SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_CONNECT,
+ ip,port);
+ return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ }
+ protected ProxyMessage connect(String host,int port)
+ throws UnknownHostException,SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_CONNECT,
+ host,port);
+ return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ }
+
+ protected ProxyMessage bind(InetAddress ip,int port)
+ throws SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_BIND,
+ ip,port);
+ return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ }
+ protected ProxyMessage bind(String host,int port)
+ throws UnknownHostException,SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_BIND,
+ host,port);
+ return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ }
+
+ protected ProxyMessage accept()
+ throws IOException,SocksException{
+ ProxyMessage msg;
+ try{
+ msg = formMessage(in);
+ }catch(InterruptedIOException iioe){
+ throw iioe;
+ }catch(IOException io_ex){
+ endSession();
+ throw new SocksException(SOCKS_PROXY_IO_ERROR,"While Trying accept:"
+ +io_ex);
+ }
+ return msg;
+ }
+
+ protected ProxyMessage udpAssociate(InetAddress ip,int port)
+ throws SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
+ ip,port);
+ if(request != null)
+ return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ //Only get here if request was null
+ endSession();
+ throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
+ "This version of proxy does not support UDP associate, use version 5");
+ }
+ protected ProxyMessage udpAssociate(String host,int port)
+ throws UnknownHostException,SocksException{
+ try{
+ startSession();
+ ProxyMessage request = formMessage(SOCKS_CMD_UDP_ASSOCIATE,
+ host,port);
+ if(request != null) return exchange(request);
+ }catch(SocksException se){
+ endSession();
+ throw se;
+ }
+ //Only get here if request was null
+ endSession();
+ throw new SocksException(SOCKS_METHOD_NOTSUPPORTED,
+ "This version of proxy does not support UDP associate, use version 5");
+ }
+
+
+ protected void endSession(){
+ try{
+ if(proxySocket!=null) proxySocket.close();
+ proxySocket = null;
+ }catch(IOException io_ex){
+ }
+ }
+
+ /**
+ *Sends the request to SOCKS server
+ */
+ protected void sendMsg(ProxyMessage msg)throws SocksException,
+ IOException{
+ msg.write(out);
+ }
+
+ /**
+ * Reads the reply from the SOCKS server
+ */
+ protected ProxyMessage readMsg()throws SocksException,
+ IOException{
+ return formMessage(in);
+ }
+ /**
+ *Sends the request reads reply and returns it
+ *throws exception if something wrong with IO
+ *or the reply code is not zero
+ */
+ protected ProxyMessage exchange(ProxyMessage request)
+ throws SocksException{
+ ProxyMessage reply;
+ try{
+ request.write(out);
+ reply = formMessage(in);
+ }catch(SocksException s_ex){
+ throw s_ex;
+ }catch(IOException ioe){
+ throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+ioe));
+ }
+ return reply;
+ }
+
+
+//Private methods
+//===============
+
+
+//Constants
+
+ public static final int SOCKS_SUCCESS =0;
+ public static final int SOCKS_FAILURE =1;
+ public static final int SOCKS_NOT_ALLOWED_BY_RULESET =2;
+ public static final int SOCKS_BADNETWORK =3;
+ public static final int SOCKS_HOST_UNREACHABLE =4;
+ public static final int SOCKS_CONNECTION_REFUSED =5;
+ public static final int SOCKS_TTL_EXPIRE =6;
+ public static final int SOCKS_CMD_NOT_SUPPORTED =7;
+ public static final int SOCKS_ADDR_NOT_SUPPORTED =8;
+
+ public static final int SOCKS_NO_PROXY =1<<16;
+ public static final int SOCKS_PROXY_NO_CONNECT =2<<16;
+ public static final int SOCKS_PROXY_IO_ERROR =3<<16;
+ public static final int SOCKS_AUTH_NOT_SUPPORTED =4<<16;
+ public static final int SOCKS_AUTH_FAILURE =5<<16;
+ public static final int SOCKS_JUST_ERROR =6<<16;
+
+ public static final int SOCKS_DIRECT_FAILED =7<<16;
+ public static final int SOCKS_METHOD_NOTSUPPORTED =8<<16;
+
+
+ static final int SOCKS_CMD_CONNECT =0x1;
+ static final int SOCKS_CMD_BIND =0x2;
+ static final int SOCKS_CMD_UDP_ASSOCIATE =0x3;
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyMessage.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyMessage.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyMessage.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,119 @@
+package net.sourceforge.jsocks.socks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.DataInputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ Abstract class which describes SOCKS4/5 response/request.
+*/
+public abstract class ProxyMessage{
+ /** Host as an IP address */
+ public InetAddress ip=null;
+ /** SOCKS version, or version of the response for SOCKS4*/
+ public int version;
+ /** Port field of the request/response*/
+ public int port;
+ /** Request/response code as an int*/
+ public int command;
+ /** Host as string.*/
+ public String host=null;
+ /** User field for SOCKS4 request messages*/
+ public String user=null;
+ /** Connection ID */
+ private String connectionId = "N/A";
+
+ ProxyMessage(int command,InetAddress ip,int port){
+ this.command = command;
+ this.ip = ip;
+ this.port = port;
+ }
+
+ ProxyMessage(){
+ }
+
+
+ /**
+ Initialises Message from the stream. Reads server response from
+ given stream.
+ @param in Input stream to read response from.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
+ if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ public abstract void read(InputStream in)
+ throws SocksException,
+ IOException;
+
+
+ /**
+ Initialises Message from the stream. Reads server response or client
+ request from given stream.
+
+ @param in Input stream to read response from.
+ @param clinetMode If true read server response, else read client request.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
+ reading in client mode, or if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ public abstract void read(InputStream in,boolean client_mode)
+ throws SocksException,
+ IOException;
+
+
+ /**
+ Writes the message to the stream.
+ @param out Output stream to which message should be written.
+ */
+ public abstract void write(OutputStream out)throws SocksException,
+ IOException;
+
+ /**
+ Get the Address field of this message as InetAddress object.
+ @return Host address or null, if one can't be determined.
+ */
+ public InetAddress getInetAddress() throws UnknownHostException{
+ return ip;
+ }
+
+
+ /**
+ Get string representaion of this message.
+ @return string representation of this message.
+ */
+ public String toString(){
+ return
+ "Proxy Message:\n"+
+ "Version:"+ version+"\n"+
+ "Command:"+ command+"\n"+
+ "IP: "+ ip+"\n"+
+ "Port: "+ port+"\n"+
+ "User: "+ user+"\n" ;
+ }
+
+ public String getConnectionId() {
+ return connectionId;
+ }
+
+ public void setConnectionId(String connectionId) {
+ this.connectionId = connectionId;
+ }
+
+//Package methods
+//////////////////
+
+ static final String bytes2IPV4(byte[] addr,int offset){
+ String hostName = ""+(addr[offset] & 0xFF);
+ for(int i = offset+1;i<offset+4;++i)
+ hostName+="."+(addr[i] & 0xFF);
+ return hostName;
+ }
+
+ static final String bytes2IPV6(byte[] addr,int offset){
+ //Have no idea how they look like!
+ return null;
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyServer.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyServer.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/ProxyServer.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,569 @@
+package net.sourceforge.jsocks.socks;
+
+import net.*;
+import net.sourceforge.jsocks.socks.server.ServerAuthenticator;
+
+
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.NoRouteToHostException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Random;
+import java.io.*;
+
+/**
+ SOCKS4 and SOCKS5 proxy, handles both protocols simultaniously.
+ Implements all SOCKS commands, including UDP relaying.
+ <p>
+ In order to use it you will need to implement ServerAuthenticator
+ interface. There is an implementation of this interface which does
+ no authentication ServerAuthenticatorNone, but it is very dangerous
+ to use, as it will give access to your local network to anybody
+ in the world. One should never use this authentication scheme unless
+ one have pretty good reason to do so.
+ There is a couple of other authentication schemes in socks.server package.
+ @see socks.server.ServerAuthenticator
+*/
+public class ProxyServer implements Runnable{
+
+ ServerAuthenticator auth;
+ ProxyMessage msg = null;
+
+ Socket sock=null,remote_sock=null;
+ ServerSocket ss=null;
+ UDPRelayServer relayServer = null;
+ InputStream in,remote_in;
+ OutputStream out,remote_out;
+
+ int mode;
+ static final int START_MODE = 0;
+ static final int ACCEPT_MODE = 1;
+ static final int PIPE_MODE = 2;
+ static final int ABORT_MODE = 3;
+
+ static final int BUF_SIZE = 8192;
+
+ Thread pipe_thread1,pipe_thread2;
+ long lastReadTime;
+
+ static int iddleTimeout = 180000; //3 minutes
+ static int acceptTimeout = 180000; //3 minutes
+
+
+ static Proxy proxy;
+
+ private String connectionId;
+
+
+//Public Constructors
+/////////////////////
+
+ /**
+ Creates a proxy server with given Authentication scheme.
+ @param auth Authentication scheme to be used.
+ */
+ public ProxyServer(ServerAuthenticator auth){
+ this.auth = auth;
+ this.connectionId = newConnectionId();
+ }
+
+//Other constructors
+////////////////////
+
+ ProxyServer(ServerAuthenticator auth,Socket s, String connectionId){
+ this.auth = auth;
+ this.sock = s;
+ this.connectionId = connectionId;
+ mode = START_MODE;
+ }
+
+//Public methods
+/////////////////
+
+ /**
+ Set proxy.
+ <p>
+ Allows Proxy chaining so that one Proxy server is connected to another
+ and so on. If proxy supports SOCKSv4, then only some SOCKSv5 requests
+ can be handled, UDP would not work, however CONNECT and BIND will be
+ translated.
+
+ @param p Proxy which should be used to handle user requests.
+ */
+ public static void setProxy(Proxy p){
+ proxy =p;
+ UDPRelayServer.proxy = proxy;
+ }
+
+ /**
+ Get proxy.
+ @return Proxy wich is used to handle user requests.
+ */
+ public static Proxy getProxy(){
+ return proxy;
+ }
+
+ /**
+ Sets the timeout for connections, how long shoud server wait
+ for data to arrive before dropping the connection.<br>
+ Zero timeout implies infinity.<br>
+ Default timeout is 3 minutes.
+ */
+ public static void setIddleTimeout(int timeout){
+ iddleTimeout = timeout;
+ }
+ /**
+ Sets the timeout for BIND command, how long the server should
+ wait for the incoming connection.<br>
+ Zero timeout implies infinity.<br>
+ Default timeout is 3 minutes.
+ */
+ public static void setAcceptTimeout(int timeout){
+ acceptTimeout = timeout;
+ }
+
+ /**
+ Sets the timeout for UDPRelay server.<br>
+ Zero timeout implies infinity.<br>
+ Default timeout is 3 minutes.
+ */
+ public static void setUDPTimeout(int timeout){
+ UDPRelayServer.setTimeout(timeout);
+ }
+
+ /**
+ Sets the size of the datagrams used in the UDPRelayServer.<br>
+ Default size is 64K, a bit more than maximum possible size of the
+ datagram.
+ */
+ public static void setDatagramSize(int size){
+ UDPRelayServer.setDatagramSize(size);
+ }
+
+
+ /**
+ Start the Proxy server at given port.<br>
+ This methods blocks.
+ */
+ public void start(int port){
+ start(port,5,null);
+ }
+
+ /**
+ Create a server with the specified port, listen backlog, and local
+ IP address to bind to. The localIP argument can be used on a multi-homed
+ host for a ServerSocket that will only accept connect requests to one of
+ its addresses. If localIP is null, it will default accepting connections
+ on any/all local addresses. The port must be between 0 and 65535,
+ inclusive. <br>
+ This methods blocks.
+ */
+ public void start(int port,int backlog,InetAddress localIP){
+ try{
+ ss = new ServerSocket(port,backlog,localIP);
+ while(true){
+ Socket s = ss.accept();
+ String connectionId = newConnectionId();
+ ProxyServer ps = new ProxyServer(auth,s, connectionId);
+ (new Thread(ps)).start();
+ }
+ }catch(IOException ioe){
+ ioe.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates new unique ID for this connection.
+ *
+ * @return a random-enough ID.
+ */
+ private String newConnectionId() {
+ // return "[" + RandomStringUtils.randomAlphanumeric(4) + "]";
+ return "[" + Math.random()*new java.util.Date().getTime() + "]";
+ }
+
+ /**
+ Stop server operation.It would be wise to interrupt thread running the
+ server afterwards.
+ */
+ public void stop(){
+ try{
+ if(ss != null) ss.close();
+ }catch(IOException ioe){
+ }
+ }
+
+//Runnable interface
+////////////////////
+ public void run(){
+ switch(mode){
+ case START_MODE:
+ try{
+ startSession();
+ }catch(IOException ioe){
+ handleException(ioe);
+ ioe.printStackTrace();
+ }finally{
+ abort();
+ if(auth!=null) auth.endSession();
+ }
+ break;
+ case ACCEPT_MODE:
+ try{
+ doAccept();
+ mode = PIPE_MODE;
+ pipe_thread1.interrupt(); //Tell other thread that connection have
+ //been accepted.
+ pipe(remote_in,out);
+ }catch(IOException ioe){
+ //log("Accept exception:"+ioe);
+ handleException(ioe);
+ }finally{
+ abort();
+ }
+ break;
+ case PIPE_MODE:
+ try{
+ pipe(remote_in,out);
+ }catch(IOException ioe){
+ }finally{
+ abort();
+ }
+ break;
+ case ABORT_MODE:
+ break;
+ default:
+ }
+ }
+
+//Private methods
+/////////////////
+ private void startSession() throws IOException{
+ sock.setSoTimeout(iddleTimeout);
+
+ try{
+ auth = auth.startSession(sock);
+ }catch(IOException ioe){
+ auth = null;
+ return;
+ }
+
+ if(auth == null){ //Authentication failed
+ return;
+ }
+
+ in = auth.getInputStream();
+ out = auth.getOutputStream();
+
+ msg = readMsg(in);
+ // Set the connection ID in the message.
+ msg.setConnectionId(connectionId);
+ handleRequest(msg);
+ }
+
+ private void handleRequest(ProxyMessage msg)
+ throws IOException{
+ if(!auth.checkRequest(msg)) {
+ ProxyMessage response = new Socks5Message(
+ Proxy.SOCKS_NOT_ALLOWED_BY_RULESET);
+ response.write(out);
+ abort();
+ throw new SocksException(Proxy.SOCKS_NOT_ALLOWED_BY_RULESET);
+ }
+
+ if(msg.ip == null){
+ if(msg instanceof Socks5Message){
+ msg.ip = InetAddress.getByName(msg.host);
+ }else
+ throw new SocksException(Proxy.SOCKS_FAILURE);
+ }
+
+ switch(msg.command){
+ case Proxy.SOCKS_CMD_CONNECT:
+ onConnect(msg);
+ break;
+ case Proxy.SOCKS_CMD_BIND:
+ onBind(msg);
+ break;
+ case Proxy.SOCKS_CMD_UDP_ASSOCIATE:
+ onUDP(msg);
+ break;
+ default:
+ throw new SocksException(Proxy.SOCKS_CMD_NOT_SUPPORTED);
+ }
+ }
+
+ private void handleException(IOException ioe){
+ //If we couldn't read the request, return;
+ if(msg == null) return;
+ //If have been aborted by other thread
+ if(mode == ABORT_MODE) return;
+ //If the request was successfully completed, but exception happened later
+ if(mode == PIPE_MODE) return;
+
+ int error_code = Proxy.SOCKS_FAILURE;
+
+ if(ioe instanceof SocksException)
+ error_code = ((SocksException)ioe).errCode;
+ else if(ioe instanceof NoRouteToHostException)
+ error_code = Proxy.SOCKS_HOST_UNREACHABLE;
+ else if(ioe instanceof ConnectException)
+ error_code = Proxy.SOCKS_CONNECTION_REFUSED;
+ else if(ioe instanceof InterruptedIOException)
+ error_code = Proxy.SOCKS_TTL_EXPIRE;
+
+ if(error_code > Proxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){
+ error_code = Proxy.SOCKS_FAILURE;
+ }
+
+ sendErrorMessage(error_code);
+ }
+
+ private void onConnect(ProxyMessage msg) throws IOException{
+ Socket s;
+ ProxyMessage response = null;
+
+ if(proxy == null)
+ s = new Socket(msg.ip,msg.port);
+ else
+ s = new SocksSocket(proxy,msg.ip,msg.port);
+
+
+ if(msg instanceof Socks5Message){
+ response = new Socks5Message(Proxy.SOCKS_SUCCESS,
+ s.getLocalAddress(),
+ s.getLocalPort());
+ }else{
+ response = new Socks4Message(Socks4Message.REPLY_OK,
+ s.getLocalAddress(),s.getLocalPort());
+
+ }
+ response.write(out);
+ startPipe(s);
+ }
+
+ private void onBind(ProxyMessage msg) throws IOException{
+ ProxyMessage response = null;
+
+ if(proxy == null)
+ ss = new ServerSocket(0);
+ else
+ ss = new SocksServerSocket(proxy, msg.ip, msg.port);
+
+ ss.setSoTimeout(acceptTimeout);
+
+
+ if(msg.version == 5)
+ response = new Socks5Message(Proxy.SOCKS_SUCCESS,ss.getInetAddress(),
+ ss.getLocalPort());
+ else
+ response = new Socks4Message(Socks4Message.REPLY_OK,
+ ss.getInetAddress(),
+ ss.getLocalPort());
+ response.write(out);
+
+ mode = ACCEPT_MODE;
+
+ pipe_thread1 = Thread.currentThread();
+ pipe_thread2 = new Thread(this);
+ pipe_thread2.start();
+
+ //Make timeout infinit.
+ sock.setSoTimeout(0);
+ int eof=0;
+
+ try{
+ while((eof=in.read())>=0){
+ if(mode != ACCEPT_MODE){
+ if(mode != PIPE_MODE) return;//Accept failed
+
+ remote_out.write(eof);
+ break;
+ }
+ }
+ }catch(EOFException eofe){
+ //System.out.println("EOF exception");
+ return;//Connection closed while we were trying to accept.
+ }catch(InterruptedIOException iioe){
+ //Accept thread interrupted us.
+ //System.out.println("Interrupted");
+ if(mode != PIPE_MODE)
+ return;//If accept thread was not successfull return.
+ }finally{
+ //System.out.println("Finnaly!");
+ }
+
+ if(eof < 0)//Connection closed while we were trying to accept;
+ return;
+
+ //Do not restore timeout, instead timeout is set on the
+ //remote socket. It does not make any difference.
+
+ pipe(in,remote_out);
+ }
+
+ private void onUDP(ProxyMessage msg) throws IOException{
+ if(msg.ip.getHostAddress().equals("0.0.0.0"))
+ msg.ip = sock.getInetAddress();
+ relayServer = new UDPRelayServer(msg.ip,msg.port,
+ Thread.currentThread(),sock,auth);
+
+ ProxyMessage response;
+
+ response = new Socks5Message(Proxy.SOCKS_SUCCESS,
+ relayServer.relayIP,relayServer.relayPort);
+
+ response.write(out);
+
+ relayServer.start();
+
+ //Make timeout infinit.
+ sock.setSoTimeout(0);
+ try{
+ while(in.read()>=0) /*do nothing*/;
+ }catch(EOFException eofe){
+ }
+ }
+
+//Private methods
+//////////////////
+
+ private void doAccept() throws IOException{
+ Socket s;
+ long startTime = System.currentTimeMillis();
+
+ while(true){
+ s = ss.accept();
+ if(s.getInetAddress().equals(msg.ip)){
+ //got the connection from the right host
+ //Close listenning socket.
+ ss.close();
+ break;
+ }else if(ss instanceof SocksServerSocket){
+ //We can't accept more then one connection
+ s.close();
+ ss.close();
+ throw new SocksException(Proxy.SOCKS_FAILURE);
+ }else{
+ if(acceptTimeout!=0){ //If timeout is not infinit
+ int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()-
+ startTime);
+ if(newTimeout <= 0) throw new InterruptedIOException(
+ "In doAccept()");
+ ss.setSoTimeout(newTimeout);
+ }
+ s.close(); //Drop all connections from other hosts
+ }
+ }
+
+ //Accepted connection
+ remote_sock = s;
+ remote_in = s.getInputStream();
+ remote_out = s.getOutputStream();
+
+ //Set timeout
+ remote_sock.setSoTimeout(iddleTimeout);
+
+
+ ProxyMessage response;
+
+ if(msg.version == 5)
+ response = new Socks5Message(Proxy.SOCKS_SUCCESS, s.getInetAddress(),
+ s.getPort());
+ else
+ response = new Socks4Message(Socks4Message.REPLY_OK,
+ s.getInetAddress(), s.getPort());
+ response.write(out);
+ }
+
+ private ProxyMessage readMsg(InputStream in) throws IOException{
+ PushbackInputStream push_in;
+ if(in instanceof PushbackInputStream)
+ push_in = (PushbackInputStream) in;
+ else
+ push_in = new PushbackInputStream(in);
+
+ int version = push_in.read();
+ push_in.unread(version);
+
+
+ ProxyMessage msg;
+
+ if(version == 5){
+ msg = new Socks5Message(push_in,false);
+ }else if(version == 4){
+ msg = new Socks4Message(push_in,false);
+ }else{
+ throw new SocksException(Proxy.SOCKS_FAILURE);
+ }
+ return msg;
+ }
+
+ private void startPipe(Socket s){
+ mode = PIPE_MODE;
+ remote_sock = s;
+ try{
+ remote_in = s.getInputStream();
+ remote_out = s.getOutputStream();
+ pipe_thread1 = Thread.currentThread();
+ pipe_thread2 = new Thread(this);
+ pipe_thread2.start();
+ pipe(in,remote_out);
+ }catch(IOException ioe){
+ }
+ }
+
+ private void sendErrorMessage(int error_code){
+ ProxyMessage err_msg;
+ if(msg instanceof Socks4Message)
+ err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED);
+ else
+ err_msg = new Socks5Message(error_code);
+ try{
+ err_msg.write(out);
+ }catch(IOException ioe){}
+ }
+
+ private synchronized void abort(){
+ if(mode == ABORT_MODE) return;
+ mode = ABORT_MODE;
+ try{
+ if(remote_sock != null) remote_sock.close();
+ if(sock != null) sock.close();
+ if(relayServer!=null) relayServer.stop();
+ if(ss!=null) ss.close();
+ if(pipe_thread1 != null) pipe_thread1.interrupt();
+ if(pipe_thread2 != null) pipe_thread2.interrupt();
+ }catch(IOException ioe){}
+ }
+
+ private void pipe(InputStream in,OutputStream out) throws IOException{
+ lastReadTime = System.currentTimeMillis();
+ byte[] buf = new byte[BUF_SIZE];
+ int len = 0;
+ while(len >= 0){
+ try{
+ if(len!=0){
+ out.write(buf,0,len);
+ out.flush();
+ }
+ len= in.read(buf);
+ lastReadTime = System.currentTimeMillis();
+ }catch(InterruptedIOException iioe){
+ if(iddleTimeout == 0) return;//Other thread interrupted us.
+ long timeSinceRead = System.currentTimeMillis() - lastReadTime;
+ if(timeSinceRead >= iddleTimeout - 1000) //-1s for adjustment.
+ return;
+ len = 0;
+
+ }
+ }
+ }
+ static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"};
+
+ static final String command2String(int cmd){
+ if(cmd > 0 && cmd < 4) return command_names[cmd-1];
+ else return "Unknown Command "+cmd;
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Message.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Message.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Message.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,161 @@
+package net.sourceforge.jsocks.socks;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import net.*;
+
+/**
+ SOCKS4 Reply/Request message.
+*/
+
+class Socks4Message extends ProxyMessage{
+
+ private byte[] msgBytes;
+ private int msgLength;
+
+ /**
+ * Server failed reply, cmd command for failed request
+ */
+ public Socks4Message(int cmd){
+ super(cmd,null,0);
+ this.user = null;
+
+ msgLength = 2;
+ msgBytes = new byte[2];
+
+ msgBytes[0] = (byte) 0;
+ msgBytes[1] = (byte) command;
+ }
+
+ /**
+ * Server successfull reply
+ */
+ public Socks4Message(int cmd,InetAddress ip,int port){
+ this(0,cmd,ip,port,null);
+ }
+
+ /**
+ * Client request
+ */
+ public Socks4Message(int cmd,InetAddress ip,int port,String user){
+ this(SOCKS_VERSION,cmd,ip,port,user);
+ }
+
+ /**
+ * Most general constructor
+ */
+ public Socks4Message(int version, int cmd,
+ InetAddress ip,int port,String user){
+ super(cmd,ip,port);
+ this.user = user;
+ this.version = version;
+
+ msgLength = user == null?8:9+user.length();
+ msgBytes = new byte[msgLength];
+
+ msgBytes[0] = (byte) version;
+ msgBytes[1] = (byte) command;
+ msgBytes[2] = (byte) (port >> 8);
+ msgBytes[3] = (byte) port;
+
+ byte[] addr;
+
+ if(ip != null)
+ addr = ip.getAddress();
+ else{
+ addr = new byte[4];
+ addr[0]=addr[1]=addr[2]=addr[3]=0;
+ }
+ System.arraycopy(addr,0,msgBytes,4,4);
+
+ if(user != null){
+ byte[] buf = user.getBytes();
+ System.arraycopy(buf,0,msgBytes,8,buf.length);
+ msgBytes[msgBytes.length -1 ] = 0;
+ }
+ }
+
+ /**
+ *Initialise from the stream
+ *If clientMode is true attempts to read a server response
+ *otherwise reads a client request
+ *see read for more detail
+ */
+ public Socks4Message(InputStream in, boolean clientMode) throws IOException{
+ msgBytes = null;
+ read(in,clientMode);
+ }
+
+ public void read(InputStream in) throws IOException{
+ read(in,true);
+ }
+
+ public void read(InputStream in, boolean clientMode) throws IOException{
+ DataInputStream d_in = new DataInputStream(in);
+ version= d_in.readUnsignedByte();
+ command = d_in.readUnsignedByte();
+ if(clientMode && command != REPLY_OK){
+ String errMsg;
+ if(command >REPLY_OK && command < REPLY_BAD_IDENTD)
+ errMsg = replyMessage[command-REPLY_OK];
+ else
+ errMsg = "Unknown Reply Code";
+ throw new SocksException(command,errMsg);
+ }
+ port = d_in.readUnsignedShort();
+ byte[] addr = new byte[4];
+ d_in.readFully(addr);
+ ip=bytes2IP(addr);
+ host = ip.getHostName();
+ if(!clientMode){
+ int b = in.read();
+ //Hope there are no idiots with user name bigger than this
+ byte[] userBytes = new byte[256];
+ int i = 0;
+ for(i =0;i<userBytes.length && b>0;++i){
+ userBytes[i] = (byte) b;
+ b = in.read();
+ }
+ user = new String(userBytes,0,i);
+ }
+ }
+ public void write(OutputStream out) throws IOException{
+ if(msgBytes == null){
+ Socks4Message msg = new Socks4Message(version,command,ip,port,user);
+ msgBytes = msg.msgBytes;
+ msgLength = msg.msgLength;
+ }
+ out.write(msgBytes);
+ }
+
+ //Class methods
+ static InetAddress bytes2IP(byte[] addr){
+ String s = bytes2IPV4(addr,0);
+ try{
+ return InetAddress.getByName(s);
+ }catch(UnknownHostException uh_ex){
+ return null;
+ }
+ }
+
+ //Constants
+
+ static final String[] replyMessage ={
+ "Request Granted",
+ "Request Rejected or Failed",
+ "Failed request, can't connect to Identd",
+ "Failed request, bad user name"};
+
+ static final int SOCKS_VERSION = 4;
+
+ public final static int REQUEST_CONNECT = 1;
+ public final static int REQUEST_BIND = 2;
+
+ public final static int REPLY_OK = 90;
+ public final static int REPLY_REJECTED = 91;
+ public final static int REPLY_NO_CONNECT = 92;
+ public final static int REPLY_BAD_IDENTD = 93;
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Proxy.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Proxy.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks4Proxy.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,123 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+
+/**
+ Proxy which describes SOCKS4 proxy.
+*/
+
+public class Socks4Proxy extends Proxy implements Cloneable{
+
+//Data members
+ String user;
+
+//Public Constructors
+//====================
+
+ /**
+ Creates the SOCKS4 proxy
+ @param p Proxy to use to connect to this proxy, allows proxy chaining.
+ @param proxyHost Address of the proxy server.
+ @param proxyPort Port of the proxy server
+ @param user User name to use for identification purposes.
+ @throws UnknownHostException If proxyHost can't be resolved.
+ */
+ public Socks4Proxy(Proxy p,String proxyHost,int proxyPort,String user)
+ throws UnknownHostException{
+ super(p,proxyHost,proxyPort);
+ this.user = new String(user);
+ version = 4;
+ }
+
+ /**
+ Creates the SOCKS4 proxy
+ @param proxyHost Address of the proxy server.
+ @param proxyPort Port of the proxy server
+ @param user User name to use for identification purposes.
+ @throws UnknownHostException If proxyHost can't be resolved.
+ */
+ public Socks4Proxy(String proxyHost,int proxyPort,String user)
+ throws UnknownHostException{
+ this(null,proxyHost,proxyPort,user);
+ }
+
+ /**
+ Creates the SOCKS4 proxy
+ @param p Proxy to use to connect to this proxy, allows proxy chaining.
+ @param proxyIP Address of the proxy server.
+ @param proxyPort Port of the proxy server
+ @param user User name to use for identification purposes.
+ */
+ public Socks4Proxy(Proxy p,InetAddress proxyIP,int proxyPort,String user){
+ super(p,proxyIP,proxyPort);
+ this.user = new String(user);
+ version = 4;
+ }
+
+ /**
+ Creates the SOCKS4 proxy
+ @param proxyIP Address of the proxy server.
+ @param proxyPort Port of the proxy server
+ @param user User name to use for identification purposes.
+ */
+ public Socks4Proxy(InetAddress proxyIP,int proxyPort,String user){
+ this(null,proxyIP,proxyPort,user);
+ }
+
+//Public instance methods
+//========================
+
+ /**
+ * Creates a clone of this proxy. Changes made to the clone should not
+ * affect this object.
+ */
+ public Object clone(){
+ Socks4Proxy newProxy = new Socks4Proxy(proxyIP,proxyPort,user);
+ newProxy.directHosts = (InetRange)directHosts.clone();
+ newProxy.chainProxy = chainProxy;
+ return newProxy;
+ }
+
+
+//Public Static(Class) Methods
+//==============================
+
+
+//Protected Methods
+//=================
+
+ protected Proxy copy(){
+ Socks4Proxy copy = new Socks4Proxy(proxyIP,proxyPort,user);
+ copy.directHosts = this.directHosts;
+ copy.chainProxy = chainProxy;
+ return copy;
+ }
+
+ protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){
+ switch(cmd){
+ case SOCKS_CMD_CONNECT:
+ cmd = Socks4Message.REQUEST_CONNECT;
+ break;
+ case SOCKS_CMD_BIND:
+ cmd = Socks4Message.REQUEST_BIND;
+ break;
+ default:
+ return null;
+ }
+ return new Socks4Message(cmd,ip,port,user);
+ }
+ protected ProxyMessage formMessage(int cmd,String host,int port)
+ throws UnknownHostException{
+ return formMessage(cmd,InetAddress.getByName(host),port);
+ }
+ protected ProxyMessage formMessage(InputStream in)
+ throws SocksException,
+ IOException{
+ return new Socks4Message(in,true);
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5DatagramSocket.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5DatagramSocket.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5DatagramSocket.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,492 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.io.*;
+
+import net.*;
+
+/**
+ Datagram socket to interract through the firewall.<BR>
+ Can be used same way as the normal DatagramSocket. One should
+ be carefull though with the datagram sizes used, as additional data
+ is present in both incomming and outgoing datagrams.
+ <p>
+ SOCKS5 protocol allows to send host address as either:
+ <ul>
+ <li> IPV4, normal 4 byte address. (10 bytes header size)
+ <li> IPV6, version 6 ip address (not supported by Java as for now).
+ 22 bytes header size.
+ <li> Host name,(7+length of the host name bytes header size).
+ </ul>
+ As with other Socks equivalents, direct addresses are handled
+ transparently, that is data will be send directly when required
+ by the proxy settings.
+ <p>
+ <b>NOTE:</b><br>
+ Unlike other SOCKS Sockets, it <b>does not</b> support proxy chaining,
+ and will throw an exception if proxy has a chain proxy attached. The
+ reason for that is not my laziness, but rather the restrictions of
+ the SOCKSv5 protocol. Basicaly SOCKSv5 proxy server, needs to know from
+ which host:port datagrams will be send for association, and returns address
+ to which datagrams should be send by the client, but it does not
+ inform client from which host:port it is going to send datagrams, in fact
+ there is even no guarantee they will be send at all and from the same address
+ each time.
+
+ */
+public class Socks5DatagramSocket extends DatagramSocket{
+
+ InetAddress relayIP;
+ int relayPort;
+ Socks5Proxy proxy;
+ private boolean server_mode = false;
+ UDPEncapsulation encapsulation;
+
+
+ /**
+ Construct Datagram socket for communication over SOCKS5 proxy
+ server. This constructor uses default proxy, the one set with
+ Proxy.setDefaultProxy() method. If default proxy is not set or
+ it is set to version4 proxy, which does not support datagram
+ forwarding, throws SocksException.
+
+ */
+ public Socks5DatagramSocket() throws SocksException,
+ IOException{
+ this(Proxy.defaultProxy,0,null);
+ }
+ /**
+ Construct Datagram socket for communication over SOCKS5 proxy
+ server. And binds it to the specified local port.
+ This constructor uses default proxy, the one set with
+ Proxy.setDefaultProxy() method. If default proxy is not set or
+ it is set to version4 proxy, which does not support datagram
+ forwarding, throws SocksException.
+ */
+ public Socks5DatagramSocket(int port) throws SocksException,
+ IOException{
+ this(Proxy.defaultProxy,port,null);
+ }
+ /**
+ Construct Datagram socket for communication over SOCKS5 proxy
+ server. And binds it to the specified local port and address.
+ This constructor uses default proxy, the one set with
+ Proxy.setDefaultProxy() method. If default proxy is not set or
+ it is set to version4 proxy, which does not support datagram
+ forwarding, throws SocksException.
+ */
+ public Socks5DatagramSocket(int port,InetAddress ip) throws SocksException,
+ IOException{
+ this(Proxy.defaultProxy,port,ip);
+ }
+
+ /**
+ Constructs datagram socket for communication over specified proxy.
+ And binds it to the given local address and port. Address of null
+ and port of 0, signify any availabale port/address.
+ Might throw SocksException, if:
+ <ol>
+ <li> Given version of proxy does not support UDP_ASSOCIATE.
+ <li> Proxy can't be reached.
+ <li> Authorization fails.
+ <li> Proxy does not want to perform udp forwarding, for any reason.
+ </ol>
+ Might throw IOException if binding dtagram socket to given address/port
+ fails.
+ See java.net.DatagramSocket for more details.
+ */
+ public Socks5DatagramSocket(Proxy p,int port,InetAddress ip)
+ throws SocksException,
+ IOException{
+ super(port,ip);
+ if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
+ if(!(p instanceof Socks5Proxy))
+ throw new SocksException(-1,"Datagram Socket needs Proxy version 5");
+
+ if(p.chainProxy != null)
+ throw new SocksException(Proxy.SOCKS_JUST_ERROR,
+ "Datagram Sockets do not support proxy chaining.");
+
+ proxy =(Socks5Proxy) p.copy();
+
+ ProxyMessage msg = proxy.udpAssociate(super.getLocalAddress(),
+ super.getLocalPort());
+ relayIP = msg.ip;
+ if(relayIP.getHostAddress().equals("0.0.0.0")) relayIP = proxy.proxyIP;
+ relayPort = msg.port;
+
+ encapsulation = proxy.udp_encapsulation;
+
+ //debug("Datagram Socket:"+getLocalAddress()+":"+getLocalPort()+"\n");
+ //debug("Socks5Datagram: "+relayIP+":"+relayPort+"\n");
+ }
+
+ /**
+ Used by UDPRelayServer.
+ */
+ Socks5DatagramSocket(boolean server_mode,UDPEncapsulation encapsulation,
+ InetAddress relayIP,int relayPort)
+ throws IOException{
+ super();
+ this.server_mode = server_mode;
+ this.relayIP = relayIP;
+ this.relayPort = relayPort;
+ this.encapsulation = encapsulation;
+ this.proxy = null;
+ }
+
+ /**
+ Sends the Datagram either through the proxy or directly depending
+ on current proxy settings and destination address. <BR>
+
+ <B> NOTE: </B> DatagramPacket size should be at least 10 bytes less
+ than the systems limit.
+
+ <P>
+ See documentation on java.net.DatagramSocket
+ for full details on how to use this method.
+ @param dp Datagram to send.
+ @throws IOException If error happens with I/O.
+ */
+ public void send(DatagramPacket dp) throws IOException{
+ //If the host should be accessed directly, send it as is.
+ if(!server_mode && proxy.isDirect(dp.getAddress())){
+ super.send(dp);
+ //debug("Sending directly:");
+ return;
+ }
+
+ byte[] head = formHeader(dp.getAddress(),dp.getPort());
+ byte[] buf = new byte[head.length + dp.getLength()];
+ byte[] data = dp.getData();
+ //Merge head and data
+ System.arraycopy(head,0,buf,0,head.length);
+ //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength());
+ System.arraycopy(data,0,buf,head.length,dp.getLength());
+
+ if(encapsulation != null)
+ buf = encapsulation.udpEncapsulate(buf,true);
+
+ super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort));
+ }
+ /**
+ This method allows to send datagram packets with address type DOMAINNAME.
+ SOCKS5 allows to specify host as names rather than ip addresses.Using
+ this method one can send udp datagrams through the proxy, without having
+ to know the ip address of the destination host.
+ <p>
+ If proxy specified for that socket has an option resolveAddrLocally set
+ to true host will be resolved, and the datagram will be send with address
+ type IPV4, if resolve fails, UnknownHostException is thrown.
+ @param dp Datagram to send, it should contain valid port and data
+ @param host Host name to which datagram should be send.
+ @throws IOException If error happens with I/O, or the host can't be
+ resolved when proxy settings say that hosts should be resolved locally.
+ @see Socks5Proxy#resolveAddrLocally(boolean)
+ */
+ public void send(DatagramPacket dp, String host) throws IOException{
+ if(proxy.isDirect(host)){
+ dp.setAddress(InetAddress.getByName(host));
+ super.send(dp);
+ return;
+ }
+
+ if(((Socks5Proxy)proxy).resolveAddrLocally){
+ dp.setAddress(InetAddress.getByName(host));
+ }
+
+ byte[] head = formHeader(host,dp.getPort());
+ byte[] buf = new byte[head.length + dp.getLength()];
+ byte[] data = dp.getData();
+ //Merge head and data
+ System.arraycopy(head,0,buf,0,head.length);
+ //System.arraycopy(data,dp.getOffset(),buf,head.length,dp.getLength());
+ System.arraycopy(data,0,buf,head.length,dp.getLength());
+
+ if(encapsulation != null)
+ buf = encapsulation.udpEncapsulate(buf,true);
+
+ super.send(new DatagramPacket(buf,buf.length,relayIP,relayPort));
+ }
+
+ /**
+ * Receives udp packet. If packet have arrived from the proxy relay server,
+ * it is processed and address and port of the packet are set to the
+ * address and port of sending host.<BR>
+ * If the packet arrived from anywhere else it is not changed.<br>
+ * <B> NOTE: </B> DatagramPacket size should be at least 10 bytes bigger
+ * than the largest packet you expect (this is for IPV4 addresses).
+ * For hostnames and IPV6 it is even more.
+ @param dp Datagram in which all relevent information will be copied.
+ */
+ public void receive(DatagramPacket dp) throws IOException{
+ super.receive(dp);
+
+ if(server_mode){
+ //Drop all datagrams not from relayIP/relayPort
+ int init_length = dp.getLength();
+ int initTimeout = getSoTimeout();
+ long startTime = System.currentTimeMillis();
+
+ while(!relayIP.equals(dp.getAddress()) ||
+ relayPort != dp.getPort()){
+
+ //Restore datagram size
+ dp.setLength(init_length);
+
+ //If there is a non-infinit timeout on this socket
+ //Make sure that it happens no matter how often unexpected
+ //packets arrive.
+ if(initTimeout != 0){
+ int newTimeout = initTimeout - (int)(System.currentTimeMillis() -
+ startTime);
+ if(newTimeout <= 0) throw new InterruptedIOException(
+ "In Socks5DatagramSocket->receive()");
+ setSoTimeout(newTimeout);
+ }
+
+ super.receive(dp);
+ }
+
+ //Restore timeout settings
+ if(initTimeout != 0) setSoTimeout(initTimeout);
+
+ }else if(!relayIP.equals(dp.getAddress()) ||
+ relayPort != dp.getPort())
+ return; // Recieved direct packet
+ //If the datagram is not from the relay server, return it it as is.
+
+ byte[] data;
+ data = dp.getData();
+
+ if(encapsulation != null)
+ data = encapsulation.udpEncapsulate(data,false);
+
+ int offset = 0; //Java 1.1
+ //int offset = dp.getOffset(); //Java 1.2
+
+ ByteArrayInputStream bIn = new ByteArrayInputStream(data,offset,
+ dp.getLength());
+
+
+ ProxyMessage msg = new Socks5Message(bIn);
+ dp.setPort(msg.port);
+ dp.setAddress(msg.getInetAddress());
+
+ //what wasn't read by the Message is the data
+ int data_length = bIn.available();
+ //Shift data to the left
+ System.arraycopy(data,offset+dp.getLength()-data_length,
+ data,offset,data_length);
+
+
+ dp.setLength(data_length);
+ }
+
+ /**
+ * Returns port assigned by the proxy, to which datagrams are relayed.
+ * It is not the same port to which other party should send datagrams.
+ @return Port assigned by socks server to which datagrams are send
+ for association.
+ */
+ public int getLocalPort(){
+ if(server_mode) return super.getLocalPort();
+ return relayPort;
+ }
+ /**
+ * Address assigned by the proxy, to which datagrams are send for relay.
+ * It is not necesseraly the same address, to which other party should send
+ * datagrams.
+ @return Address to which datagrams are send for association.
+ */
+ public InetAddress getLocalAddress(){
+ if(server_mode) return super.getLocalAddress();
+ return relayIP;
+ }
+
+ /**
+ * Closes datagram socket, and proxy connection.
+ */
+ public void close(){
+ if(!server_mode) proxy.endSession();
+ super.close();
+ }
+
+ /**
+ This method checks wether proxy still runs udp forwarding service
+ for this socket.
+ <p>
+ This methods checks wether the primary connection to proxy server
+ is active. If it is, chances are that proxy continues to forward
+ datagrams being send from this socket. If it was closed, most likely
+ datagrams are no longer being forwarded by the server.
+ <p>
+ Proxy might decide to stop forwarding datagrams, in which case it
+ should close primary connection. This method allows to check, wether
+ this have been done.
+ <p>
+ You can specify timeout for which we should be checking EOF condition
+ on the primary connection. Timeout is in milliseconds. Specifying 0 as
+ timeout implies infinity, in which case method will block, until
+ connection to proxy is closed or an error happens, and then return false.
+ <p>
+ One possible scenario is to call isProxyactive(0) in separate thread,
+ and once it returned notify other threads about this event.
+
+ @param timeout For how long this method should block, before returning.
+ @return true if connection to proxy is active, false if eof or error
+ condition have been encountered on the connection.
+ */
+ public boolean isProxyAlive(int timeout){
+ if(server_mode) return false;
+ if(proxy != null){
+ try{
+ proxy.proxySocket.setSoTimeout(timeout);
+
+ int eof = proxy.in.read();
+ if(eof < 0) return false; // EOF encountered.
+ else return true; // This really should not happen
+
+ }catch(InterruptedIOException iioe){
+ return true; // read timed out.
+ }catch(IOException ioe){
+ return false;
+ }
+ }
+ return false;
+ }
+
+//PRIVATE METHODS
+//////////////////
+
+
+ private byte[] formHeader(InetAddress ip, int port){
+ Socks5Message request = new Socks5Message(0,ip,port);
+ request.data[0] = 0;
+ return request.data;
+ }
+
+
+ private byte[] formHeader(String host,int port){
+ Socks5Message request = new Socks5Message(0,host,port);
+ request.data[0] = 0;
+ return request.data;
+ }
+
+
+/*======================================================================
+
+//Mainly Test functions
+//////////////////////
+
+ private String bytes2String(byte[] b){
+ String s="";
+ char[] hex_digit = { '0','1','2','3','4','5','6','7','8','9',
+ 'A','B','C','D','E','F'};
+ for(int i=0;i<b.length;++i){
+ int i1 = (b[i] & 0xF0) >> 4;
+ int i2 = b[i] & 0xF;
+ s+=hex_digit[i1];
+ s+=hex_digit[i2];
+ s+=" ";
+ }
+ return s;
+ }
+ private static final void debug(String s){
+ if(DEBUG)
+ System.out.print(s);
+ }
+
+ private static final boolean DEBUG = true;
+
+
+ public static void usage(){
+ System.err.print(
+ "Usage: java Socks.SocksDatagramSocket host port [socksHost socksPort]\n");
+ }
+
+ static final int defaultProxyPort = 1080; //Default Port
+ static final String defaultProxyHost = "www-proxy"; //Default proxy
+
+ public static void main(String args[]){
+ int port;
+ String host;
+ int proxyPort;
+ String proxyHost;
+ InetAddress ip;
+
+ if(args.length > 1 && args.length < 5){
+ try{
+
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+
+ proxyPort =(args.length > 3)? Integer.parseInt(args[3])
+ : defaultProxyPort;
+
+ host = args[0];
+ ip = InetAddress.getByName(host);
+
+ proxyHost =(args.length > 2)? args[2]
+ : defaultProxyHost;
+
+ Proxy.setDefaultProxy(proxyHost,proxyPort);
+ Proxy p = Proxy.getDefaultProxy();
+ p.addDirect("lux");
+
+
+ DatagramSocket ds = new Socks5DatagramSocket();
+
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ String s;
+
+ System.out.print("Enter line:");
+ s = in.readLine();
+
+ while(s != null){
+ byte[] data = (s+"\r\n").getBytes();
+ DatagramPacket dp = new DatagramPacket(data,0,data.length,
+ ip,port);
+ System.out.println("Sending to: "+ip+":"+port);
+ ds.send(dp);
+ dp = new DatagramPacket(new byte[1024],1024);
+
+ System.out.println("Trying to recieve on port:"+
+ ds.getLocalPort());
+ ds.receive(dp);
+ System.out.print("Recieved:\n"+
+ "From:"+dp.getAddress()+":"+dp.getPort()+
+ "\n\n"+
+ new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
+ );
+ System.out.print("Enter line:");
+ s = in.readLine();
+
+ }
+ ds.close();
+ System.exit(1);
+
+ }catch(SocksException s_ex){
+ System.err.println("SocksException:"+s_ex);
+ s_ex.printStackTrace();
+ System.exit(1);
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+ }catch(NumberFormatException num_ex){
+ usage();
+ num_ex.printStackTrace();
+ System.exit(1);
+ }
+
+ }else{
+ usage();
+ }
+ }
+*/
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Message.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Message.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Message.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,292 @@
+package net.sourceforge.jsocks.socks;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.DataInputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ SOCKS5 request/response message.
+*/
+
+class Socks5Message extends ProxyMessage{
+ /** Address type of given message*/
+ public int addrType;
+
+ byte[] data;
+
+ /**
+ Server error response.
+ @param cmd Error code.
+ */
+ public Socks5Message(int cmd){
+ super(cmd,null,0);
+ data = new byte[3];
+ data[0] = SOCKS_VERSION; //Version.
+ data[1] = (byte)cmd; //Reply code for some kind of failure.
+ data[2] = 0; //Reserved byte.
+ }
+
+ /**
+ Construct client request or server response.
+ @param cmd - Request/Response code.
+ @param ip - IP field.
+ @paarm port - port field.
+ */
+ public Socks5Message(int cmd,InetAddress ip,int port){
+ super(cmd,ip,port);
+ this.host = ip==null?"0.0.0.0":ip.getHostName();
+ this.version = SOCKS_VERSION;
+
+ byte[] addr;
+
+ if(ip == null){
+ addr = new byte[4];
+ addr[0]=addr[1]=addr[2]=addr[3]=0;
+ }else
+ addr = ip.getAddress();
+
+ addrType = addr.length == 4 ? SOCKS_ATYP_IPV4
+ : SOCKS_ATYP_IPV6;
+
+ data = new byte[6+addr.length];
+ data[0] = (byte) SOCKS_VERSION; //Version
+ data[1] = (byte) command; //Command
+ data[2] = (byte) 0; //Reserved byte
+ data[3] = (byte) addrType; //Address type
+
+ //Put Address
+ System.arraycopy(addr,0,data,4,addr.length);
+ //Put port
+ data[data.length-2] = (byte)(port>>8);
+ data[data.length-1] = (byte)(port);
+ }
+
+
+ /**
+ Construct client request or server response.
+ @param cmd - Request/Response code.
+ @param hostName - IP field as hostName, uses ADDR_TYPE of HOSTNAME.
+ @paarm port - port field.
+ */
+ public Socks5Message(int cmd,String hostName,int port){
+ super(cmd,null,port);
+ this.host = hostName;
+ this.version = SOCKS_VERSION;
+
+ //System.out.println("Doing ATYP_DOMAINNAME");
+
+ addrType = SOCKS_ATYP_DOMAINNAME;
+ byte addr[] = hostName.getBytes();
+
+ data =new byte[7+addr.length];
+ data[0] = (byte) SOCKS_VERSION; //Version
+ data[1] = (byte) command; //Command
+ data[2] = (byte) 0; //Reserved byte
+ data[3] = (byte) SOCKS_ATYP_DOMAINNAME; //Address type
+ data[4] = (byte) addr.length; //Length of the address
+
+ //Put Address
+ System.arraycopy(addr,0,data,5,addr.length);
+ //Put port
+ data[data.length-2] = (byte)(port >>8);
+ data[data.length-1] = (byte)(port);
+ }
+
+ /**
+ Initialises Message from the stream. Reads server response from
+ given stream.
+ @param in Input stream to read response from.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
+ if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ public Socks5Message(InputStream in) throws SocksException,
+ IOException{
+ this(in,true);
+ }
+
+ /**
+ Initializes Message from the stream. Reads server response or client
+ request from given stream.
+
+ @param in Input stream to read response from.
+ @param clientMode If true read server response, else read client request.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
+ reading in client mode, or if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ public Socks5Message(InputStream in,boolean clientMode)throws SocksException,
+ IOException{
+ read(in,clientMode);
+ }
+
+
+ /**
+ Initialises Message from the stream. Reads server response from
+ given stream.
+ @param in Input stream to read response from.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0), or
+ if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ public void read(InputStream in) throws SocksException,
+ IOException{
+ read(in,true);
+ }
+
+
+ /**
+ Initializes Message from the stream. Reads server response or client
+ request from given stream.
+
+ @param in Input stream to read response from.
+ @param clientMode If true read server response, else read client request.
+ @throws SocksException If server response code is not SOCKS_SUCCESS(0) and
+ reading in client mode, or if any error with protocol occurs.
+ @throws IOException If any error happens with I/O.
+ */
+ @Override
+ public void read(InputStream in,boolean clientMode) throws SocksException,
+ IOException{
+ data = null;
+ ip = null;
+
+ DataInputStream di = new DataInputStream(in);
+
+ version = di.readUnsignedByte();
+ command = di.readUnsignedByte();
+ if(clientMode && command != 0)
+ throw new SocksException(command);
+
+ int reserved = di.readUnsignedByte();
+ addrType = di.readUnsignedByte();
+
+ byte addr[];
+
+ switch(addrType){
+ case SOCKS_ATYP_IPV4:
+ addr = new byte[4];
+ di.readFully(addr);
+ host = bytes2IPV4(addr,0);
+ break;
+ case SOCKS_ATYP_IPV6:
+ addr = new byte[SOCKS_IPV6_LENGTH];//I believe it is 16 bytes,huge!
+ di.readFully(addr);
+ host = bytes2IPV6(addr,0);
+ break;
+ case SOCKS_ATYP_DOMAINNAME:
+ //System.out.println("Reading ATYP_DOMAINNAME");
+ addr = new byte[di.readUnsignedByte()];//Next byte shows the length
+ di.readFully(addr);
+ host = new String(addr);
+ break;
+ default:
+ throw(new SocksException(Proxy.SOCKS_JUST_ERROR));
+ }
+
+ port = di.readUnsignedShort();
+
+ if(addrType != SOCKS_ATYP_DOMAINNAME && doResolveIP){
+ try{
+ ip = InetAddress.getByName(host);
+ }catch(UnknownHostException uh_ex){
+ }
+ }
+ }
+
+ /**
+ Writes the message to the stream.
+ @param out Output stream to which message should be written.
+ */
+ public void write(OutputStream out)throws SocksException,
+ IOException{
+ if(data == null){
+ Socks5Message msg;
+
+ if(addrType == SOCKS_ATYP_DOMAINNAME)
+ msg = new Socks5Message(command,host,port);
+ else{
+ if(ip == null){
+ try{
+ ip = InetAddress.getByName(host);
+ }catch(UnknownHostException uh_ex){
+ throw new SocksException(Proxy.SOCKS_JUST_ERROR);
+ }
+ }
+ msg = new Socks5Message(command,ip,port);
+ }
+ data = msg.data;
+ }
+ out.write(data);
+ }
+
+ /**
+ Returns IP field of the message as IP, if the message was created
+ with ATYP of HOSTNAME, it will attempt to resolve the hostname,
+ which might fail.
+ @throws UnknownHostException if host can't be resolved.
+ */
+ public InetAddress getInetAddress() throws UnknownHostException{
+ if(ip!=null) return ip;
+
+ return (ip=InetAddress.getByName(host));
+ }
+
+ /**
+ Returns string representation of the message.
+ */
+ public String toString(){
+ String s=
+ "Socks5Message:"+"\n"+
+ "VN "+version+"\n"+
+ "CMD "+command+"\n"+
+ "ATYP "+addrType+"\n"+
+ "ADDR "+host+"\n"+
+ "PORT "+port+"\n";
+ return s;
+ }
+
+
+ /**
+ *Wether to resolve hostIP returned from SOCKS server
+ *that is wether to create InetAddress object from the
+ *hostName string
+ */
+ static public boolean resolveIP(){ return doResolveIP;}
+
+ /**
+ *Wether to resolve hostIP returned from SOCKS server
+ *that is wether to create InetAddress object from the
+ *hostName string
+ *@param doResolve Wether to resolve hostIP from SOCKS server.
+ *@return Previous value.
+ */
+ static public boolean resolveIP(boolean doResolve){
+ boolean old = doResolveIP;
+ doResolveIP = doResolve;
+ return old;
+ }
+
+ /*
+ private static final void debug(String s){
+ if(DEBUG)
+ System.out.print(s);
+ }
+ private static final boolean DEBUG = false;
+ */
+
+ //SOCKS5 constants
+ public static final int SOCKS_VERSION =5;
+
+ public static final int SOCKS_ATYP_IPV4 =0x1; //Where is 2??
+ public static final int SOCKS_ATYP_DOMAINNAME =0x3; //!!!!rfc1928
+ public static final int SOCKS_ATYP_IPV6 =0x4;
+
+ public static final int SOCKS_IPV6_LENGTH =16;
+
+ static boolean doResolveIP = true;
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Proxy.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Proxy.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/Socks5Proxy.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,253 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.io.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+
+import net.*;
+
+/**
+ SOCKS5 Proxy.
+*/
+
+public class Socks5Proxy extends Proxy implements Cloneable{
+
+//Data members
+ private Hashtable authMethods = new Hashtable();
+ private int selectedMethod;
+
+ boolean resolveAddrLocally = true;
+ UDPEncapsulation udp_encapsulation=null;
+
+
+//Public Constructors
+//====================
+
+ /**
+ Creates SOCKS5 proxy.
+ @param p Proxy to use to connect to this proxy, allows proxy chaining.
+ @param proxyHost Host on which a Proxy server runs.
+ @param proxyPort Port on which a Proxy server listens for connections.
+ @throws UnknownHostException If proxyHost can't be resolved.
+ */
+ public Socks5Proxy(Proxy p,String proxyHost,int proxyPort)
+ throws UnknownHostException{
+ super(p,proxyHost,proxyPort);
+ version = 5;
+ setAuthenticationMethod(0,new AuthenticationNone());
+ }
+
+ /**
+ Creates SOCKS5 proxy.
+ @param proxyHost Host on which a Proxy server runs.
+ @param proxyPort Port on which a Proxy server listens for connections.
+ @throws UnknownHostException If proxyHost can't be resolved.
+ */
+ public Socks5Proxy(String proxyHost,int proxyPort)
+ throws UnknownHostException{
+ this(null,proxyHost,proxyPort);
+ }
+
+
+ /**
+ Creates SOCKS5 proxy.
+ @param p Proxy to use to connect to this proxy, allows proxy chaining.
+ @param proxyIP Host on which a Proxy server runs.
+ @param proxyPort Port on which a Proxy server listens for connections.
+ */
+ public Socks5Proxy(Proxy p,InetAddress proxyIP,int proxyPort){
+ super(p,proxyIP,proxyPort);
+ version = 5;
+ setAuthenticationMethod(0,new AuthenticationNone());
+ }
+
+ /**
+ Creates SOCKS5 proxy.
+ @param proxyIP Host on which a Proxy server runs.
+ @param proxyPort Port on which a Proxy server listens for connections.
+ */
+ public Socks5Proxy(InetAddress proxyIP,int proxyPort){
+ this(null,proxyIP,proxyPort);
+ }
+
+//Public instance methods
+//========================
+
+
+ /**
+ * Wether to resolve address locally or to let proxy do so.
+ <p>
+ SOCKS5 protocol allows to send host names rather then IPs in the
+ requests, this option controls wether the hostnames should be send
+ to the proxy server as names, or should they be resolved locally.
+ @param doResolve Wether to perform resolution locally.
+ @return Previous settings.
+ */
+ public boolean resolveAddrLocally(boolean doResolve){
+ boolean old = resolveAddrLocally;
+ resolveAddrLocally = doResolve;
+ return old;
+ }
+ /**
+ Get current setting on how the addresses should be handled.
+ @return Current setting for address resolution.
+ @see Socks5Proxy#resolveAddrLocally(boolean doResolve)
+ */
+ public boolean resolveAddrLocally(){
+ return resolveAddrLocally;
+ }
+
+ /**
+ Adds another authentication method.
+ @param methodId Authentication method id, see rfc1928
+ @param method Implementation of Authentication
+ @see Authentication
+ */
+ public boolean setAuthenticationMethod(int methodId,
+ Authentication method){
+ if(methodId<0 || methodId > 255)
+ return false;
+ if(method == null){
+ //Want to remove a particular method
+ return (authMethods.remove(new Integer(methodId)) != null);
+ }else{//Add the method, or rewrite old one
+ authMethods.put(new Integer(methodId),method);
+ }
+ return true;
+ }
+
+ /**
+ Get authentication method, which corresponds to given method id
+ @param methodId Authentication method id.
+ @return Implementation for given method or null, if one was not set.
+ */
+ public Authentication getAuthenticationMethod(int methodId){
+ Object method = authMethods.get(new Integer(methodId));
+ if(method == null) return null;
+ return (Authentication)method;
+ }
+
+ /**
+ Creates a clone of this Proxy.
+ */
+ public Object clone(){
+ Socks5Proxy newProxy = new Socks5Proxy(proxyIP,proxyPort);
+ newProxy.authMethods = (Hashtable) this.authMethods.clone();
+ newProxy.directHosts = (InetRange)directHosts.clone();
+ newProxy.resolveAddrLocally = resolveAddrLocally;
+ newProxy.chainProxy = chainProxy;
+ return newProxy;
+ }
+
+//Public Static(Class) Methods
+//==============================
+
+
+//Protected Methods
+//=================
+
+ protected Proxy copy(){
+ Socks5Proxy copy = new Socks5Proxy(proxyIP,proxyPort);
+ copy.authMethods = this.authMethods; //same Hash, no copy
+ copy.directHosts = this.directHosts;
+ copy.chainProxy = this.chainProxy;
+ copy.resolveAddrLocally = this.resolveAddrLocally;
+ return copy;
+ }
+ /**
+ *
+ *
+ */
+ protected void startSession()throws SocksException{
+ super.startSession();
+ Authentication auth;
+ Socket ps = proxySocket; //The name is too long
+
+ try{
+ byte nMethods = (byte) authMethods.size(); //Number of methods
+
+ byte[] buf = new byte[2+nMethods]; //2 is for VER,NMETHODS
+ buf[0] = (byte) version;
+ buf[1] = nMethods; //Number of methods
+ int i=2;
+
+ Enumeration ids = authMethods.keys();
+ while(ids.hasMoreElements())
+ buf[i++] = (byte)((Integer)ids.nextElement()).intValue();
+
+ out.write(buf);
+ out.flush();
+
+ int versionNumber = in.read();
+ selectedMethod = in.read();
+
+ if(versionNumber < 0 || selectedMethod < 0){
+ //EOF condition was reached
+ endSession();
+ throw(new SocksException(SOCKS_PROXY_IO_ERROR,
+ "Connection to proxy lost."));
+ }
+ if(versionNumber < version){
+ //What should we do??
+ }
+ if(selectedMethod == 0xFF){ //No method selected
+ ps.close();
+ throw ( new SocksException(SOCKS_AUTH_NOT_SUPPORTED));
+ }
+
+ auth = getAuthenticationMethod(selectedMethod);
+ if(auth == null){
+ //This shouldn't happen, unless method was removed by other
+ //thread, or the server stuffed up
+ throw(new SocksException(SOCKS_JUST_ERROR,
+ "Speciefied Authentication not found!"));
+ }
+ Object[] in_out = auth.doSocksAuthentication(selectedMethod,ps);
+ if(in_out == null){
+ //Authentication failed by some reason
+ throw(new SocksException(SOCKS_AUTH_FAILURE));
+ }
+ //Most authentication methods are expected to return
+ //simply the input/output streams associated with
+ //the socket. However if the auth. method requires
+ //some kind of encryption/decryption being done on the
+ //connection it should provide classes to handle I/O.
+
+ in = (InputStream) in_out[0];
+ out = (OutputStream) in_out[1];
+ if(in_out.length > 2)
+ udp_encapsulation = (UDPEncapsulation) in_out[2];
+
+ }catch(SocksException s_ex){
+ throw s_ex;
+ }catch(UnknownHostException uh_ex){
+ throw(new SocksException(SOCKS_PROXY_NO_CONNECT));
+ }catch(SocketException so_ex){
+ throw(new SocksException(SOCKS_PROXY_NO_CONNECT));
+ }catch(IOException io_ex){
+ //System.err.println(io_ex);
+ throw(new SocksException(SOCKS_PROXY_IO_ERROR,""+io_ex));
+ }
+ }
+
+ protected ProxyMessage formMessage(int cmd,InetAddress ip,int port){
+ return new Socks5Message(cmd,ip,port);
+ }
+ protected ProxyMessage formMessage(int cmd,String host,int port)
+ throws UnknownHostException{
+ if(resolveAddrLocally)
+ return formMessage(cmd,InetAddress.getByName(host),port);
+ else
+ return new Socks5Message(cmd,host,port);
+ }
+ protected ProxyMessage formMessage(InputStream in)
+ throws SocksException,
+ IOException{
+ return new Socks5Message(in);
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksException.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksException.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksException.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,78 @@
+package net.sourceforge.jsocks.socks;
+
+/**
+ Exception thrown by various socks classes to indicate errors
+ with protocol or unsuccessful server responses.
+*/
+public class SocksException extends java.io.IOException{
+ /**
+ Construct a SocksException with given error code.
+ <p>
+ Tries to look up message which corresponds to this error code.
+ @param errCode Error code for this exception.
+ */
+ public SocksException(int errCode){
+ this.errCode = errCode;
+ if((errCode >> 16) == 0){
+ //Server reply error message
+ errString = errCode <= serverReplyMessage.length ?
+ serverReplyMessage[errCode] :
+ UNASSIGNED_ERROR_MESSAGE;
+ }else{
+ //Local error
+ errCode = (errCode >> 16) -1;
+ errString = errCode <= localErrorMessage.length ?
+ localErrorMessage[errCode] :
+ UNASSIGNED_ERROR_MESSAGE;
+ }
+ }
+ /**
+ Constructs a SocksException with given error code and message.
+ @param errCode Error code.
+ @param errString Error Message.
+ */
+ public SocksException(int errCode,String errString){
+ this.errCode = errCode;
+ this.errString = errString;
+ }
+ /**
+ Get the error code associated with this exception.
+ @return Error code associated with this exception.
+ */
+ public int getErrorCode(){
+ return errCode;
+ }
+ /**
+ Get human readable representation of this exception.
+ @return String represntation of this exception.
+ */
+ public String toString(){
+ return errString;
+ }
+
+ static final String UNASSIGNED_ERROR_MESSAGE =
+ "Unknown error message";
+ static final String serverReplyMessage[] = {
+ "Succeeded",
+ "General SOCKS server failure",
+ "Connection not allowed by ruleset",
+ "Network unreachable",
+ "Host unreachable",
+ "Connection refused",
+ "TTL expired",
+ "Command not supported",
+ "Address type not supported" };
+
+ static final String localErrorMessage[] ={
+ "SOCKS server not specified",
+ "Unable to contact SOCKS server",
+ "IO error",
+ "None of Authentication methods are supported",
+ "Authentication failed",
+ "General SOCKS fault" };
+
+ String errString;
+ int errCode;
+
+}//End of SocksException class
+
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksServerSocket.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksServerSocket.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksServerSocket.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,213 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+
+/**
+ SocksServerSocket allows to accept connections from one particular
+ host through the SOCKS4 or SOCKS5 proxy.
+*/
+public class SocksServerSocket extends ServerSocket{
+ //Data members
+ protected Proxy proxy;
+ protected String localHost;
+ protected InetAddress localIP;
+ protected int localPort;
+
+ boolean doing_direct = false;
+ InetAddress remoteAddr;
+
+ /**
+ * Creates ServerSocket capable of accepting one connection
+ * through the firewall, uses default Proxy.
+ *@param host Host from which the connection should be recieved.
+ *@param port Port number of the primary connection.
+ */
+ public SocksServerSocket(String host,int port)
+ throws SocksException,UnknownHostException,IOException{
+ this(Proxy.defaultProxy,host,port);
+ }
+ /**
+ *Creates ServerSocket capable of accepting one connection
+ *through the firewall, uses given proxy.
+ *@param p Proxy object to use.
+ *@param host Host from which the connection should be recieved.
+ *@param port Port number of the primary connection.
+ */
+ public SocksServerSocket(Proxy p,String host,int port)
+ throws SocksException,UnknownHostException,IOException{
+
+
+ super(0);
+ if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
+ //proxy=p;
+ proxy = p.copy();
+ if(proxy.isDirect(host)){
+ remoteAddr = InetAddress.getByName(host);
+ proxy = null;
+ doDirect();
+ }else{
+ processReply(proxy.bind(host,port));
+ }
+ }
+
+ /**
+ * Creates ServerSocket capable of accepting one connection
+ * through the firewall, uses default Proxy.
+ *@param ip Host from which the connection should be recieved.
+ *@param port Port number of the primary connection.
+ */
+ public SocksServerSocket(InetAddress ip, int port) throws SocksException,
+ IOException{
+ this(Proxy.defaultProxy,ip,port);
+ }
+
+ /**
+ *Creates ServerSocket capable of accepting one connection
+ *through the firewall, uses given proxy.
+ *@param p Proxy object to use.
+ *@param ip Host from which the connection should be recieved.
+ *@param port Port number of the primary connection.
+ */
+ public SocksServerSocket(Proxy p,InetAddress ip, int port)
+ throws SocksException,IOException{
+ super(0);
+
+ if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
+ this.proxy = p.copy();
+
+ if(proxy.isDirect(ip)){
+ remoteAddr = ip;
+ doDirect();
+ }else{
+ processReply(proxy.bind(ip,port));
+ }
+ }
+
+
+ /**
+ * Accepts the incoming connection.
+ */
+ public Socket accept() throws IOException{
+ Socket s;
+
+ if(!doing_direct){
+ if(proxy == null) return null;
+
+ ProxyMessage msg = proxy.accept();
+ s = msg.ip == null? new SocksSocket(msg.host,msg.port,proxy)
+ : new SocksSocket(msg.ip,msg.port,proxy);
+ //Set timeout back to 0
+ proxy.proxySocket.setSoTimeout(0);
+ }else{ //Direct Connection
+
+ //Mimic the proxy behaviour,
+ //only accept connections from the speciefed host.
+ while(true){
+ s = super.accept();
+ if(s.getInetAddress().equals(remoteAddr)){
+ //got the connection from the right host
+ //Close listenning socket.
+ break;
+ }else
+ s.close(); //Drop all connections from other hosts
+ }
+
+ }
+ proxy = null;
+ //Return accepted socket
+ return s;
+ }
+
+ /**
+ * Closes the connection to proxy if socket have not been accepted, if
+ * the direct connection is used, closes direct ServerSocket. If the
+ * client socket have been allready accepted, does nothing.
+ */
+ public void close() throws IOException{
+ super.close();
+ if(proxy != null) proxy.endSession();
+ proxy = null;
+ }
+
+ /**
+ Get the name of the host proxy is using to listen for incoming
+ connection.
+ <P>
+ Usefull when address is returned by proxy as the hostname.
+ @return the hostname of the address proxy is using to listen
+ for incoming connection.
+ */
+ public String getHost(){
+ return localHost;
+ }
+
+ /**
+ * Get address assigned by proxy to listen for incomming
+ * connections, or the local machine address if doing direct
+ * connection.
+ */
+ public InetAddress getInetAddress(){
+ if(localIP == null){
+ try{
+ localIP = InetAddress.getByName(localHost);
+ }catch(UnknownHostException e){
+ return null;
+ }
+ }
+ return localIP;
+ }
+
+ /**
+ * Get port assigned by proxy to listen for incoming connections, or
+ the port chosen by local system, if accepting directly.
+ */
+ public int getLocalPort(){
+ return localPort;
+ }
+
+ /**
+ Set Timeout.
+
+ @param timeout Amount of time in milliseconds, accept should wait for
+ incoming connection before failing with exception.
+ Zero timeout implies infinity.
+ */
+ public void setSoTimeout(int timeout) throws SocketException{
+ super.setSoTimeout(timeout);
+ if(!doing_direct) proxy.proxySocket.setSoTimeout(timeout);
+ }
+
+
+//Private Methods
+//////////////////
+
+ private void processReply(ProxyMessage reply)throws SocksException{
+ localPort = reply.port;
+ /*
+ * If the server have assigned same host as it was contacted on
+ * it might return an address of all zeros
+ */
+ if(reply.host.equals("0.0.0.0")){
+ localIP = proxy.proxyIP;
+ localHost = localIP.getHostName();
+ }else{
+ localHost = reply.host;
+ localIP = reply.ip;
+ }
+ }
+
+ private void doDirect(){
+ doing_direct = true;
+ localPort = super.getLocalPort();
+ localIP = super.getInetAddress();
+ localHost = localIP.getHostName();
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksSocket.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksSocket.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/SocksSocket.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,337 @@
+package net.sourceforge.jsocks.socks;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+
+/**
+ * SocksSocket tryies to look very similar to normal Socket,
+ * while allowing connections through the SOCKS4 or 5 proxy.
+ * To use this class you will have to identify proxy you need
+ * to use, Proxy class allows you to set default proxy, which
+ * will be used by all Socks aware sockets. You can also create
+ * either Socks4Proxy or Socks5Proxy, and use them by passing to the
+ * appropriate constructors.
+ * <P>
+ * Using Socks package can be as easy as that:
+ *
+ * <pre><tt>
+ *
+ * import Socks.*;
+ * ....
+ *
+ * try{
+ * //Specify SOCKS5 proxy
+ * Proxy.setDefaultProxy("socks-proxy",1080);
+ *
+ * //OR you still use SOCKS4
+ * //Code below uses SOCKS4 proxy
+ * //Proxy.setDefaultProxy("socks-proxy",1080,userName);
+ *
+ * Socket s = SocksSocket("some.host.of.mine",13);
+ * readTimeFromSock(s);
+ * }catch(SocksException sock_ex){
+ * //Usually it will turn in more or less meaningfull message
+ * System.err.println("SocksException:"+sock_ex);
+ * }
+ *
+ * </tt></pre>
+ *<P>
+ * However if the need exist for more control, like resolving addresses
+ * remotely, or using some non-trivial authentication schemes, it can be done.
+ */
+
+public class SocksSocket extends Socket{
+ //Data members
+ protected Proxy proxy;
+ protected String localHost, remoteHost;
+ protected InetAddress localIP, remoteIP;
+ protected int localPort,remotePort;
+
+ private Socket directSock = null;
+
+ /**
+ * Tryies to connect to given host and port
+ * using default proxy. If no default proxy speciefied
+ * it throws SocksException with error code SOCKS_NO_PROXY.
+ @param host Machine to connect to.
+ @param port Port to which to connect.
+ * @see SocksSocket#SocksSocket(Proxy,String,int)
+ * @see Socks5Proxy#resolveAddrLocally
+ */
+ public SocksSocket(String host,int port)
+ throws SocksException,UnknownHostException{
+ this(Proxy.defaultProxy,host,port);
+ }
+ /**
+ * Connects to host port using given proxy server.
+ @param p Proxy to use.
+ @param host Machine to connect to.
+ @param port Port to which to connect.
+ @throws UnknownHostException
+ If one of the following happens:
+ <ol>
+
+ <li> Proxy settings say that address should be resolved locally, but
+ this fails.
+ <li> Proxy settings say that the host should be contacted directly but
+ host name can't be resolved.
+ </ol>
+ @throws SocksException
+ If one of the following happens:
+ <ul>
+ <li> Proxy is is null.
+ <li> Proxy settings say that the host should be contacted directly but
+ this fails.
+ <li> Socks Server can't be contacted.
+ <li> Authentication fails.
+ <li> Connection is not allowed by the SOCKS proxy.
+ <li> SOCKS proxy can't establish the connection.
+ <li> Any IO error occured.
+ <li> Any protocol error occured.
+ </ul>
+ @throws IOexception if anything is wrong with I/O.
+ @see Socks5Proxy#resolveAddrLocally
+ */
+ public SocksSocket(Proxy p,String host,int port)
+ throws SocksException,UnknownHostException{
+
+
+ if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
+ //proxy=p;
+ proxy = p.copy();
+ remoteHost = host;
+ remotePort = port;
+ if(proxy.isDirect(host)){
+ remoteIP = InetAddress.getByName(host);
+ doDirect();
+ }
+ else
+ processReply(proxy.connect(host,port));
+ }
+
+
+ /**
+ * Tryies to connect to given ip and port
+ * using default proxy. If no default proxy speciefied
+ * it throws SocksException with error code SOCKS_NO_PROXY.
+ @param ip Machine to connect to.
+ @param port Port to which to connect.
+ * @see SocksSocket#SocksSocket(Proxy,String,int)
+ */
+ public SocksSocket(InetAddress ip, int port) throws SocksException{
+ this(Proxy.defaultProxy,ip,port);
+ }
+
+ /**
+ Connects to given ip and port using given Proxy server.
+ @param p Proxy to use.
+ @param ip Machine to connect to.
+ @param port Port to which to connect.
+
+ */
+ public SocksSocket(Proxy p,InetAddress ip, int port) throws SocksException{
+ if(p == null) throw new SocksException(Proxy.SOCKS_NO_PROXY);
+ this.proxy = p.copy();
+ this.remoteIP = ip;
+ this.remotePort = port;
+ this.remoteHost = ip.getHostName();
+ if(proxy.isDirect(remoteIP))
+ doDirect();
+ else
+ processReply(proxy.connect(ip,port));
+ }
+
+
+ /**
+ * These 2 constructors are used by the SocksServerSocket.
+ * This socket simply overrides remoteHost, remotePort
+ */
+ protected SocksSocket(String host,int port,Proxy proxy){
+ this.remotePort = port;
+ this.proxy = proxy;
+ this.localIP = proxy.proxySocket.getLocalAddress();
+ this.localPort = proxy.proxySocket.getLocalPort();
+ this.remoteHost = host;
+ }
+ protected SocksSocket(InetAddress ip,int port,Proxy proxy){
+ remoteIP = ip;
+ remotePort = port;
+ this.proxy = proxy;
+ this.localIP = proxy.proxySocket.getLocalAddress();
+ this.localPort = proxy.proxySocket.getLocalPort();
+ remoteHost = remoteIP.getHostName();
+ }
+
+ /**
+ * Same as Socket
+ */
+ public void close() throws IOException{
+ if(proxy!= null)proxy.endSession();
+ proxy = null;
+ }
+ /**
+ * Same as Socket
+ */
+ public InputStream getInputStream(){
+ return proxy.in;
+ }
+ /**
+ * Same as Socket
+ */
+ public OutputStream getOutputStream(){
+ return proxy.out;
+ }
+ /**
+ * Same as Socket
+ */
+ public int getPort(){
+ return remotePort;
+ }
+ /**
+ * Returns remote host name, it is usefull in cases when addresses
+ * are resolved by proxy, and we can't create InetAddress object.
+ @return The name of the host this socket is connected to.
+ */
+ public String getHost(){
+ return remoteHost;
+ }
+ /**
+ * Get remote host as InetAddress object, might return null if
+ * addresses are resolved by proxy, and it is not possible to resolve
+ * it locally
+ @return Ip address of the host this socket is connected to, or null
+ if address was returned by the proxy as DOMAINNAME and can't be
+ resolved locally.
+ */
+ public InetAddress getInetAddress(){
+ if(remoteIP == null){
+ try{
+ remoteIP = InetAddress.getByName(remoteHost);
+ }catch(UnknownHostException e){
+ return null;
+ }
+ }
+ return remoteIP;
+ }
+
+ /**
+ * Get the port assigned by the proxy for the socket, not
+ * the port on locall machine as in Socket.
+ @return Port of the socket used on the proxy server.
+ */
+ public int getLocalPort(){
+ return localPort;
+ }
+
+ /**
+ * Get address assigned by proxy to make a remote connection,
+ * it might be different from the host specified for the proxy.
+ * Can return null if socks server returned this address as hostname
+ * and it can't be resolved locally, use getLocalHost() then.
+ @return Address proxy is using to make a connection.
+ */
+ public InetAddress getLocalAddress(){
+ if(localIP == null){
+ try{
+ localIP = InetAddress.getByName(localHost);
+ }catch(UnknownHostException e){
+ return null;
+ }
+ }
+ return localIP;
+ }
+ /**
+ Get name of the host, proxy has assigned to make a remote connection
+ for this socket. This method is usefull when proxy have returned
+ address as hostname, and we can't resolve it on this machine.
+ @return The name of the host proxy is using to make a connection.
+ */
+ public String getLocalHost(){
+ return localHost;
+ }
+
+ /**
+ Same as socket.
+ */
+ public void setSoLinger(boolean on,int val) throws SocketException{
+ proxy.proxySocket.setSoLinger(on,val);
+ }
+ /**
+ Same as socket.
+ */
+ public int getSoLinger(int timeout) throws SocketException{
+ return proxy.proxySocket.getSoLinger();
+ }
+ /**
+ Same as socket.
+ */
+ public void setSoTimeout(int timeout) throws SocketException{
+ proxy.proxySocket.setSoTimeout(timeout);
+ }
+ /**
+ Same as socket.
+ */
+ public int getSoTimeout(int timeout) throws SocketException{
+ return proxy.proxySocket.getSoTimeout();
+ }
+ /**
+ Same as socket.
+ */
+ public void setTcpNoDelay(boolean on) throws SocketException{
+ proxy.proxySocket.setTcpNoDelay(on);
+ }
+ /**
+ Same as socket.
+ */
+ public boolean getTcpNoDelay() throws SocketException{
+ return proxy.proxySocket.getTcpNoDelay();
+ }
+
+ /**
+ Get string representation of the socket.
+ */
+ public String toString(){
+ if(directSock!=null) return "Direct connection:"+directSock;
+ return ("Proxy:"+proxy+";"+"addr:"+remoteHost+",port:"+remotePort
+ +",localport:"+localPort);
+
+ }
+
+//Private Methods
+//////////////////
+
+ private void processReply(ProxyMessage reply)throws SocksException{
+ localPort = reply.port;
+ /*
+ * If the server have assigned same host as it was contacted on
+ * it might return an address of all zeros
+ */
+ if(reply.host.equals("0.0.0.0")){
+ localIP = proxy.proxyIP;
+ localHost = localIP.getHostName();
+ }else{
+ localHost = reply.host;
+ localIP = reply.ip;
+ }
+ }
+ private void doDirect()throws SocksException{
+ try{
+ //System.out.println("IP:"+remoteIP+":"+remotePort);
+ directSock = new Socket(remoteIP,remotePort);
+ proxy.out = directSock.getOutputStream();
+ proxy.in = directSock.getInputStream();
+ proxy.proxySocket = directSock;
+ localIP = directSock.getLocalAddress();
+ localPort = directSock.getLocalPort();
+ }catch(IOException io_ex){
+ throw new SocksException(Proxy.SOCKS_DIRECT_FAILED,
+ "Direct connect failed:"+io_ex);
+ }
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPEncapsulation.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPEncapsulation.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPEncapsulation.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,30 @@
+package net.sourceforge.jsocks.socks;
+
+/**
+ This interface provides for datagram encapsulation for SOCKSv5 protocol.
+ <p>
+ SOCKSv5 allows for datagrams to be encapsulated for purposes of integrity
+ and/or authenticity. How it should be done is aggreed during the
+ authentication stage, and is authentication dependent. This interface is
+ provided to allow this encapsulation.
+ @see Authentication
+*/
+public interface UDPEncapsulation{
+
+ /**
+ This method should provide any authentication depended transformation
+ on datagrams being send from/to the client.
+
+ @param data Datagram data (including any SOCKS related bytes), to be
+ encapsulated/decapsulated.
+ @param out Wether the data is being send out. If true method should
+ encapsulate/encrypt data, otherwise it should decapsulate/
+ decrypt data.
+ @throw IOException if for some reason data can be transformed correctly.
+ @return Should return byte array containing data after transformation.
+ It is possible to return same array as input, if transformation
+ only involves bit mangling, and no additional data is being
+ added or removed.
+ */
+ byte[] udpEncapsulate(byte[] data, boolean out) throws java.io.IOException;
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPRelayServer.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPRelayServer.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UDPRelayServer.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,217 @@
+package net.sourceforge.jsocks.socks;
+
+import net.*;
+import net.sourceforge.jsocks.socks.server.*;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.io.*;
+
+/**
+ UDP Relay server, used by ProxyServer to perform udp forwarding.
+*/
+class UDPRelayServer implements Runnable{
+
+
+ DatagramSocket client_sock;
+ DatagramSocket remote_sock;
+
+ Socket controlConnection;
+
+ int relayPort;
+ InetAddress relayIP;
+
+ Thread pipe_thread1,pipe_thread2;
+ Thread master_thread;
+
+ ServerAuthenticator auth;
+
+ long lastReadTime;
+
+ // private static final Logger LOG = Logger.getLogger(UDPRelayServer.class);
+
+ static Proxy proxy = null;
+ static int datagramSize = 0xFFFF;//64K, a bit more than max udp size
+ static int iddleTimeout = 180000;//3 minutes
+
+
+ /**
+ Constructs UDP relay server to communicate with client
+ on given ip and port.
+ @param clientIP Address of the client from whom datagrams
+ will be recieved and to whom they will be forwarded.
+ @param clientPort Clients port.
+ @param master_thread Thread which will be interrupted, when
+ UDP relay server stoppes for some reason.
+ @param controlConnection Socket which will be closed, before
+ interrupting the master thread, it is introduced due to a bug
+ in windows JVM which does not throw InterruptedIOException in
+ threads which block in I/O operation.
+ */
+ public UDPRelayServer(InetAddress clientIP,int clientPort,
+ Thread master_thread,
+ Socket controlConnection,
+ ServerAuthenticator auth)
+ throws IOException{
+ this.master_thread = master_thread;
+ this.controlConnection = controlConnection;
+ this.auth = auth;
+
+ client_sock = new Socks5DatagramSocket(true,auth.getUdpEncapsulation(),
+ clientIP,clientPort);
+ relayPort = client_sock.getLocalPort();
+ relayIP = client_sock.getLocalAddress();
+
+ if(relayIP.getHostAddress().equals("0.0.0.0"))
+ relayIP = InetAddress.getLocalHost();
+
+ if(proxy == null)
+ remote_sock = new DatagramSocket();
+ else
+ remote_sock = new Socks5DatagramSocket(proxy,0,null);
+ }
+
+
+//Public methods
+/////////////////
+
+
+ /**
+ Sets the timeout for UDPRelay server.<br>
+ Zero timeout implies infinity.<br>
+ Default timeout is 3 minutes.
+ */
+
+ static public void setTimeout(int timeout){
+ iddleTimeout = timeout;
+ }
+
+
+ /**
+ Sets the size of the datagrams used in the UDPRelayServer.<br>
+ Default size is 64K, a bit more than maximum possible size of the
+ datagram.
+ */
+ static public void setDatagramSize(int size){
+ datagramSize = size;
+ }
+
+ /**
+ Port to which client should send datagram for association.
+ */
+ public int getRelayPort(){
+ return relayPort;
+ }
+ /**
+ IP address to which client should send datagrams for association.
+ */
+ public InetAddress getRelayIP(){
+ return relayIP;
+ }
+
+ /**
+ Starts udp relay server.
+ Spawns two threads of execution and returns.
+ */
+ public void start() throws IOException{
+ remote_sock.setSoTimeout(iddleTimeout);
+ client_sock.setSoTimeout(iddleTimeout);
+
+ log("Starting UDP relay server on "+relayIP+":"+relayPort);
+ log("Remote socket "+remote_sock.getLocalAddress()+":"+
+ remote_sock.getLocalPort());
+
+ pipe_thread1 = new Thread(this,"pipe1");
+ pipe_thread2 = new Thread(this,"pipe2");
+
+ lastReadTime = System.currentTimeMillis();
+
+ pipe_thread1.start();
+ pipe_thread2.start();
+ }
+
+ /**
+ Stops Relay server.
+ <p>
+ Does not close control connection, does not interrupt master_thread.
+ */
+ public synchronized void stop(){
+ master_thread = null;
+ controlConnection = null;
+ abort();
+ }
+
+//Runnable interface
+////////////////////
+ public void run(){
+ try{
+ if(Thread.currentThread().getName().equals("pipe1"))
+ pipe(remote_sock,client_sock,false);
+ else
+ pipe(client_sock,remote_sock,true);
+ }catch(IOException ioe){
+ }finally{
+ abort();
+ log("UDP Pipe thread "+Thread.currentThread().getName()+" stopped.");
+ }
+
+ }
+
+//Private methods
+/////////////////
+ private synchronized void abort(){
+ if(pipe_thread1 == null) return;
+
+ log("Aborting UDP Relay Server");
+
+ remote_sock.close();
+ client_sock.close();
+
+ if(controlConnection != null)
+ try{ controlConnection.close();} catch(IOException ioe){}
+
+ if(master_thread!=null) master_thread.interrupt();
+
+ pipe_thread1.interrupt();
+ pipe_thread2.interrupt();
+
+ pipe_thread1 = null;
+ }
+
+
+ static private void log(String s){
+
+ }
+
+ private void pipe(DatagramSocket from,DatagramSocket to,boolean out)
+ throws IOException{
+ byte[] data = new byte[datagramSize];
+ DatagramPacket dp = new DatagramPacket(data,data.length);
+
+ while(true){
+ try{
+ from.receive(dp);
+ lastReadTime = System.currentTimeMillis();
+
+ if(auth.checkRequest(dp,out))
+ to.send(dp);
+
+ }catch(UnknownHostException uhe){
+ log("Dropping datagram for unknown host");
+ }catch(InterruptedIOException iioe){
+ //log("Interrupted: "+iioe);
+ //If we were interrupted by other thread.
+ if(iddleTimeout == 0) return;
+
+ //If last datagram was received, long time ago, return.
+ long timeSinceRead = System.currentTimeMillis() - lastReadTime;
+ if(timeSinceRead >= iddleTimeout -100) //-100 for adjustment
+ return;
+ }
+ dp.setLength(data.length);
+ }
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UserPasswordAuthentication.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UserPasswordAuthentication.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/UserPasswordAuthentication.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,75 @@
+package net.sourceforge.jsocks.socks;
+
+/**
+ SOCKS5 User Password authentication scheme.
+*/
+public class UserPasswordAuthentication implements Authentication{
+
+ /**SOCKS ID for User/Password authentication method*/
+ public final static int METHOD_ID = 2;
+
+ String userName, password;
+ byte[] request;
+
+ /**
+ Create an instance of UserPasswordAuthentication.
+ @param userName User Name to send to SOCKS server.
+ @param password Password to send to SOCKS server.
+ */
+ public UserPasswordAuthentication(String userName,String password){
+ this.userName = userName;
+ this.password = password;
+ formRequest();
+ }
+ /** Get the user name.
+ @return User name.
+ */
+ public String getUser(){
+ return userName;
+ }
+ /** Get password
+ @return Password
+ */
+ public String getPassword(){
+ return password;
+ }
+ /**
+ Does User/Password authentication as defined in rfc1929.
+ @return An array containnig in, out streams, or null if authentication
+ fails.
+ */
+ public Object[] doSocksAuthentication(int methodId,
+ java.net.Socket proxySocket)
+ throws java.io.IOException{
+
+ if(methodId != METHOD_ID) return null;
+
+ java.io.InputStream in = proxySocket.getInputStream();
+ java.io.OutputStream out = proxySocket.getOutputStream();
+
+ out.write(request);
+ int version = in.read();
+ if(version < 0) return null; //Server closed connection
+ int status = in.read();
+ if(status != 0) return null; //Server closed connection, or auth failed.
+
+ return new Object[] {in,out};
+ }
+
+//Private methods
+//////////////////
+
+/** Convert UserName password in to binary form, ready to be send to server*/
+ private void formRequest(){
+ byte[] user_bytes = userName.getBytes();
+ byte[] password_bytes = password.getBytes();
+
+ request = new byte[3+user_bytes.length+password_bytes.length];
+ request[0] = (byte) 1;
+ request[1] = (byte) user_bytes.length;
+ System.arraycopy(user_bytes,0,request,2,user_bytes.length);
+ request[2+user_bytes.length] = (byte) password_bytes.length;
+ System.arraycopy(password_bytes,0,
+ request,3+user_bytes.length,password_bytes.length);
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/Ident.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/Ident.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/Ident.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,161 @@
+package net.sourceforge.jsocks.socks.server;
+
+import java.net.ConnectException;
+import java.net.Socket;
+import java.io.*;
+import java.util.StringTokenizer;
+
+import net.*;
+
+/**
+ Class Ident provides means to obtain user name of the owner of the socket
+ on remote machine, providing remote machine runs identd daemon.
+ <p>
+ To use it:
+ <tt><pre>
+ Socket s = ss.accept();
+ Ident id = new Ident(s);
+ if(id.successful) goUseUser(id.userName);
+ else handleIdentError(id.errorCode,id.errorMessage)
+ </pre></tt>
+*/
+public class Ident{
+
+ /** Error Message can be null.*/
+ public String errorMessage;
+ /** Host type as returned by daemon, can be null, if error happened*/
+ public String hostType;
+ /** User name as returned by the identd daemon, or null, if it failed*/
+ public String userName;
+
+ /** If this is true then userName and hostType contain valid values.
+ Else errorCode contain the error code, and errorMessage contains
+ the corresponding message.
+ */
+ public boolean successful;
+ /** Error code*/
+ public int errorCode;
+ /** Identd on port 113 can't be contacted*/
+ public static final int ERR_NO_CONNECT = 1;
+ /** Connection timed out*/
+ public static final int ERR_TIMEOUT = 2;
+ /** Identd daemon responded with ERROR, in this case errorMessage
+ contains the string explanation, as send by the daemon.
+ */
+ public static final int ERR_PROTOCOL = 3;
+ /**
+ When parsing server response protocol error happened.
+ */
+ public static final int ERR_PROTOCOL_INCORRECT = 4;
+
+
+ /** Maximum amount of time we should wait before dropping the
+ connection to identd server.Setting it to 0 implies infinit
+ timeout.
+ */
+ public static final int connectionTimeout = 10000;
+
+
+ /**
+ Constructor tries to connect to Identd daemon on the host of the
+ given socket, and retrieve user name of the owner of given socket
+ connection on remote machine. After constructor returns public
+ fields are initialised to whatever the server returned.
+ <p>
+ If user name was successfully retrieved successful is set to true,
+ and userName and hostType are set to whatever server returned. If
+ however for some reason user name was not obtained, successful is set
+ to false and errorCode contains the code explaining the reason of
+ failure, and errorMessage contains human readable explanation.
+ <p>
+ Constructor may block, for a while.
+ @param s Socket whose ownership on remote end should be obtained.
+ */
+ public Ident(Socket s ){
+ Socket sock = null;
+ successful = false; //We are pessimistic
+
+ try{
+ sock = new Socket(s.getInetAddress(),113);
+ sock.setSoTimeout(connectionTimeout);
+ byte[] request = (""+s.getPort()+" , "+
+ s.getLocalPort()+"\r\n").getBytes();
+
+ sock.getOutputStream().write(request);
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(sock.getInputStream()));
+
+ parseResponse(in.readLine());
+
+ }catch(InterruptedIOException iioe){
+ errorCode = ERR_TIMEOUT;
+ errorMessage = "Connection to identd timed out.";
+ }catch(ConnectException ce){
+ errorCode = ERR_NO_CONNECT;
+ errorMessage = "Connection to identd server failed.";
+
+ }catch(IOException ioe){
+ errorCode = ERR_NO_CONNECT;
+ errorMessage = ""+ioe;
+ }finally{
+ try{ if(sock!=null) sock.close();}catch(IOException ioe){};
+ }
+ }
+
+ private void parseResponse(String response){
+ if(response == null){
+ errorCode = ERR_PROTOCOL_INCORRECT;
+ errorMessage = "Identd server closed connection.";
+ return;
+ }
+
+ StringTokenizer st = new StringTokenizer(response,":");
+ if(st.countTokens() < 3){
+ errorCode = ERR_PROTOCOL_INCORRECT;
+ errorMessage = "Can't parse server response.";
+ return;
+ }
+
+ st.nextToken(); //Discard first token, it's basically what we have send
+ String command = st.nextToken().trim().toUpperCase();
+
+ if(command.equals("USERID") && st.countTokens() >= 2){
+ successful = true;
+ hostType = st.nextToken().trim();
+ userName = st.nextToken("").substring(1);//Get all that is left
+ }else if(command.equals("ERROR")){
+ errorCode = ERR_PROTOCOL;
+ errorMessage = st.nextToken();
+ }else{
+ errorCode = ERR_PROTOCOL_INCORRECT;
+ System.out.println("Opa!");
+ errorMessage = "Can't parse server response.";
+ }
+
+
+ }
+
+///////////////////////////////////////////////
+//USED for Testing
+/*
+ public static void main(String[] args) throws IOException{
+
+ Socket s = null;
+ s = new Socket("gp101-16", 1391);
+
+ Ident id = new Ident(s);
+ if(id.successful){
+ System.out.println("User: "+id.userName);
+ System.out.println("HostType: "+id.hostType);
+ }else{
+ System.out.println("ErrorCode: "+id.errorCode);
+ System.out.println("ErrorMessage: "+id.errorMessage);
+
+ }
+
+ if(s!= null) s.close();
+ }
+//*/
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/IdentAuthenticator.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/IdentAuthenticator.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/IdentAuthenticator.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,153 @@
+package net.sourceforge.jsocks.socks.server;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.io.*;
+
+import net.*;
+import net.sourceforge.jsocks.socks.InetRange;
+import net.sourceforge.jsocks.socks.ProxyMessage;
+
+/**
+ An implementation of socks.ServerAuthentication which provides
+ simple authentication based on the host from which the connection
+ is made and the name of the user on the remote machine, as reported
+ by identd daemon on the remote machine.
+ <p>
+ It can also be used to provide authentication based only on the contacting
+ host address.
+*/
+
+public class IdentAuthenticator extends ServerAuthenticatorNone{
+ /** Vector of InetRanges */
+ Vector hosts;
+
+ /** Vector of user hashes*/
+ Vector users;
+
+ String user;
+
+
+ /**
+ Constructs empty IdentAuthenticator.
+ */
+ public IdentAuthenticator(){
+ hosts = new Vector();
+ users = new Vector();
+ }
+ /**
+ Used to create instances returned from startSession.
+ @param in Input stream.
+ @param out OutputStream.
+ @param user Username associated with this connection,could be
+ null if name was not required.
+ */
+ IdentAuthenticator(InputStream in,OutputStream out, String user){
+ super(in,out);
+ this.user = user;
+ }
+
+ /**
+ Adds range of addresses from which connection is allowed. Hashtable
+ users should contain user names as keys and anything as values
+ (value is not used and will be ignored).
+ @param hostRange Range of ip addresses from which connection is allowed.
+ @param users Hashtable of users for whom connection is allowed, or null
+ to indicate that anybody is allowed to connect from the hosts within given
+ range.
+ */
+ public synchronized void add(InetRange hostRange,Hashtable users){
+ this.hosts.addElement(hostRange);
+ this.users.addElement(users);
+ }
+
+ /**
+ Grants permission only to those users, who connect from one of the
+ hosts registered with add(InetRange,Hashtable) and whose names, as
+ reported by identd daemon, are listed for the host the connection
+ came from.
+ */
+ public ServerAuthenticator startSession(Socket s)
+ throws IOException{
+
+ int ind = getRangeIndex(s.getInetAddress());
+ String user = null;
+
+ //System.out.println("getRangeReturned:"+ind);
+
+ if(ind < 0) return null; //Host is not on the list.
+
+ ServerAuthenticatorNone auth = (ServerAuthenticatorNone)
+ super.startSession(s);
+
+ //System.out.println("super.startSession() returned:"+auth);
+ if(auth == null) return null;
+
+ //do the authentication
+
+ Hashtable user_names = (Hashtable) users.elementAt(ind);
+
+ if(user_names != null){ //If need to do authentication
+ Ident ident;
+ ident = new Ident(s);
+ //If can't obtain user name, fail
+ if(!ident.successful) return null;
+ //If user name is not listed for this address, fail
+ if(!user_names.containsKey(ident.userName)) return null;
+ user = ident.userName;
+ }
+ return new IdentAuthenticator(auth.in,auth.out,user);
+
+ }
+ /**
+ For SOCKS5 requests allways returns true. For SOCKS4 requests
+ checks wether the user name supplied in the request corresponds
+ to the name obtained from the ident daemon.
+ */
+ public boolean checkRequest(ProxyMessage msg,java.net.Socket s){
+ //If it's version 5 request, or if anybody is permitted, return true;
+ if(msg.version == 5 || user == null)
+ return true;
+
+ if(msg.version != 4) return false; //Who knows?
+
+ return user.equals(msg.user);
+ }
+
+ /** Get String representaion of the IdentAuthenticator.*/
+ public String toString(){
+ String s = "";
+
+ for(int i=0;i<hosts.size();++i)
+ s += "Range:"+hosts.elementAt(i)+"\nUsers:"+userNames(i)+"\n";
+ return s;
+ }
+
+//Private Methods
+//////////////////
+ private int getRangeIndex(InetAddress ip){
+ int index = 0;
+ Iterator iterator = hosts.iterator();
+ while(iterator.hasNext()){
+ InetRange ir = (InetRange) iterator.next();
+ if(ir.contains(ip)) return index;
+ index++;
+ }
+ return -1; //Not found
+ }
+
+ private String userNames(int i){
+ if(users.elementAt(i) == null) return "Everybody is permitted.";
+ Iterator iterator = ((Hashtable)users.elementAt(i)).keySet().iterator();
+ if(!iterator.hasNext()) return "";
+ String s = iterator.next().toString();
+ while(iterator.hasNext())
+ s += "; "+iterator.next();
+
+ return s;
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticator.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticator.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticator.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,120 @@
+package net.sourceforge.jsocks.socks.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.DatagramPacket;
+
+import net.sourceforge.jsocks.socks.ProxyMessage;
+import net.sourceforge.jsocks.socks.UDPEncapsulation;
+
+/**
+ Classes implementing this interface should provide socks server with
+ authentication and authorization of users.
+**/
+public interface ServerAuthenticator{
+
+ /**
+ This method is called when a new connection accepted by the server.
+ <p>
+ At this point no data have been extracted from the connection. It is
+ responsibility of this method to ensure that the next byte in the
+ stream after this method have been called is the first byte of the
+ socks request message. For SOCKSv4 there is no authentication data and
+ the first byte in the stream is part of the request. With SOCKSv5 however
+ there is an authentication data first. It is expected that implementaions
+ will process this authentication data.
+ <p>
+ If authentication was successful an instance of ServerAuthentication
+ should be returned, it later will be used by the server to perform
+ authorization and some other things. If authentication fails null should
+ be returned, or an exception may be thrown.
+
+ @param s Accepted Socket.
+ @return An instance of ServerAuthenticator to be used for this connection
+ or null
+ */
+ ServerAuthenticator startSession(Socket s) throws IOException;
+
+ /**
+ This method should return input stream which should be used on the
+ accepted socket.
+ <p>
+ SOCKSv5 allows to have multiple authentication methods, and these methods
+ might require some kind of transformations being made on the data.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+ */
+ InputStream getInputStream();
+ /**
+ This method should return output stream to use to write to the accepted
+ socket.
+ <p>
+ SOCKSv5 allows to have multiple authentication methods, and these methods
+ might require some kind of transformations being made on the data.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+ */
+ OutputStream getOutputStream();
+
+ /**
+ This method should return UDPEncapsulation, which should be used
+ on the datagrams being send in/out.
+ <p>
+ If no transformation should be done on the datagrams, this method
+ should return null.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+ */
+
+ UDPEncapsulation getUdpEncapsulation();
+
+ /**
+ This method is called when a request have been read.
+ <p>
+ Implementation should decide wether to grant request or not. Returning
+ true implies granting the request, false means request should be rejected.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+ @param msg Request message.
+ @return true to grant request, false to reject it.
+ */
+ boolean checkRequest(ProxyMessage msg);
+
+ /**
+ This method is called when datagram is received by the server.
+ <p>
+ Implementaions should decide wether it should be forwarded or dropped.
+ It is expecteed that implementation will use datagram address and port
+ information to make a decision, as well as anything else. Address and
+ port of the datagram are always correspond to remote machine. It is
+ either destination or source address. If out is true address is destination
+ address, else it is a source address, address of the machine from which
+ datagram have been received for the client.
+ <p>
+ Implementaions should return true if the datagram is to be forwarded, and
+ false if the datagram should be dropped.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+
+ @param out If true the datagram is being send out(from the client),
+ otherwise it is an incoming datagram.
+ @return True to forward datagram false drop it silently.
+ */
+ boolean checkRequest(DatagramPacket dp, boolean out);
+
+ /**
+ This method is called when session is completed. Either due to normal
+ termination or due to any error condition.
+ <p>
+ This method is called on the object returned from the startSession
+ function.
+ */
+ void endSession();
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticatorNone.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticatorNone.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/ServerAuthenticatorNone.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,172 @@
+package net.sourceforge.jsocks.socks.server;
+
+import net.sourceforge.jsocks.socks.ProxyMessage;
+import net.sourceforge.jsocks.socks.UDPEncapsulation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.net.Socket;
+
+/**
+ An implementation of ServerAuthenticator, which does <b>not</b> do
+ any authentication.
+<P>
+<FONT size="+3" color ="FF0000"> Warning!!</font><br> Should not be
+used on machines which are not behind the firewall.
+<p>
+It is only provided to make implementing other authentication schemes
+easier.<br>
+For Example: <tt><pre>
+ class MyAuth extends socks.server.ServerAuthenticator{
+ ...
+ public ServerAuthenticator startSession(java.net.Socket s){
+ if(!checkHost(s.getInetAddress()) return null;
+ return super.startSession(s);
+ }
+
+ boolean checkHost(java.net.Inetaddress addr){
+ boolean allow;
+ //Do it somehow
+ return allow;
+ }
+ }
+</pre></tt>
+*/
+public class ServerAuthenticatorNone implements ServerAuthenticator{
+
+ static final byte[] socks5response = {5,0};
+
+ InputStream in;
+ OutputStream out;
+
+ /**
+ Creates new instance of the ServerAuthenticatorNone.
+ */
+ public ServerAuthenticatorNone(){
+ this.in = null;
+ this.out = null;
+ }
+ /**
+ Constructs new ServerAuthenticatorNone object suitable for returning
+ from the startSession function.
+ @param in Input stream to return from getInputStream method.
+ @param out Output stream to return from getOutputStream method.
+ */
+ public ServerAuthenticatorNone(InputStream in, OutputStream out){
+ this.in = in;
+ this.out = out;
+ }
+ /**
+ Grants access to everyone.Removes authentication related bytes from
+ the stream, when a SOCKS5 connection is being made, selects an
+ authentication NONE.
+ */
+ public ServerAuthenticator startSession(Socket s)
+ throws IOException{
+
+ PushbackInputStream in = new PushbackInputStream(s.getInputStream());
+ OutputStream out = s.getOutputStream();
+
+ int version = in.read();
+ if(version == 5){
+ if(!selectSocks5Authentication(in,out,0))
+ return null;
+ }else if(version == 4){
+ //Else it is the request message allready, version 4
+ in.unread(version);
+ }else
+ return null;
+
+
+ return new ServerAuthenticatorNone(in,out);
+ }
+
+ /**
+ Get input stream.
+ @return Input stream speciefied in the constructor.
+ */
+ public InputStream getInputStream(){
+ return in;
+ }
+ /**
+ Get output stream.
+ @return Output stream speciefied in the constructor.
+ */
+ public OutputStream getOutputStream(){
+ return out;
+ }
+ /**
+ Allways returns null.
+ @return null
+ */
+ public UDPEncapsulation getUdpEncapsulation(){
+ return null;
+ }
+
+ /**
+ * Checks the request. For this stub always return true.
+ *
+ * @returns true if request is OK or false if its not.
+ */
+ public boolean checkRequest(ProxyMessage msg) {
+ return true;
+ }
+
+ /**
+ * Checks the request. For this stub always return true.
+ */
+ public boolean checkRequest(java.net.DatagramPacket dp, boolean out){
+ return true;
+ }
+
+ /**
+ Does nothing.
+ */
+ public void endSession(){
+ }
+
+ /**
+ Convinience routine for selecting SOCKSv5 authentication.
+ <p>
+ This method reads in authentication methods that client supports,
+ checks wether it supports given method. If it does, the notification
+ method is written back to client, that this method have been chosen
+ for authentication. If given method was not found, authentication
+ failure message is send to client ([5,FF]).
+ @param in Input stream, version byte should be removed from the stream
+ before calling this method.
+ @param out Output stream.
+ @param methodId Method which should be selected.
+ @return true if methodId was found, false otherwise.
+ */
+ static public boolean selectSocks5Authentication(InputStream in,
+ OutputStream out,
+ int methodId)
+ throws IOException{
+
+ int num_methods = in.read();
+ if (num_methods <= 0) return false;
+ byte method_ids[] = new byte[num_methods];
+ byte response[] = new byte[2];
+ boolean found = false;
+
+ response[0] = (byte) 5; //SOCKS version
+ response[1] = (byte) 0xFF; //Not found, we are pessimistic
+
+ int bread = 0; //bytes read so far
+ while(bread < num_methods)
+ bread += in.read(method_ids,bread,num_methods-bread);
+
+ for(int i=0;i<num_methods;++i)
+ if(method_ids[i] == methodId){
+ found = true;
+ response[1] = (byte) methodId;
+ break;
+ }
+
+ out.write(response);
+ return found;
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserPasswordAuthenticator.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserPasswordAuthenticator.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserPasswordAuthenticator.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,73 @@
+package net.sourceforge.jsocks.socks.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ This class implements SOCKS5 User/Password authentication scheme as
+ defined in rfc1929,the server side of it.
+*/
+public class UserPasswordAuthenticator extends ServerAuthenticatorNone{
+
+ static final int METHOD_ID = 2;
+
+ UserValidation validator;
+
+ /**
+ Construct a new UserPasswordAuthentication object, with given
+ UserVlaidation scheme.
+
+ @param validator UserValidation to use for validating users.
+ */
+ public UserPasswordAuthenticator(UserValidation validator){
+ this.validator = validator;
+ }
+
+ @Override
+ public ServerAuthenticator startSession(Socket s) throws IOException{
+ InputStream in = s.getInputStream();
+ OutputStream out = s.getOutputStream();
+
+ if(in.read() != 5) return null; //Drop non version 5 messages.
+
+ if(!selectSocks5Authentication(in,out,METHOD_ID))
+ return null;
+ if(!doUserPasswordAuthentication(s,in,out))
+ return null;
+
+ return new ServerAuthenticatorNone(in,out);
+ }
+
+
+//Private Methods
+//////////////////
+
+ private boolean doUserPasswordAuthentication(Socket s,
+ InputStream in,
+ OutputStream out)
+ throws IOException{
+ int version = in.read();
+ if(version != 1) return false;
+ int ulen = in.read();
+ if(ulen < 0) return false;
+ byte[] user = new byte[ulen];
+ in.read(user);
+ int plen = in.read();
+ if(plen < 0) return false;
+ byte[] password = new byte[plen];
+ in.read(password);
+
+ if(validator.isUserValid(new String(user), new String(password),s)){
+ //System.out.println("user valid");
+ out.write(new byte[]{1,0});
+ }else{
+ //System.out.println("user invalid");
+ out.write(new byte[]{1,1});
+ return false;
+ }
+
+ return true;
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserValidation.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserValidation.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/socks/server/UserValidation.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,21 @@
+package net.sourceforge.jsocks.socks.server;
+
+/**
+ Interface which provides for user validation, based on user name
+ password and where it connects from.
+*/
+public interface UserValidation{
+ /**
+ Implementations of this interface are expected to use some or all
+ of the information provided plus any information they can extract
+ from other sources to decide wether given user should be allowed
+ access to SOCKS server, or whatever you use it for.
+
+ @return true to indicate user is valid, false otherwise.
+ @param username User whom implementation should validate.
+ @param password Password this user provided.
+ @param connection Socket which user used to connect to the server.
+ */
+ boolean isUserValid(String username,String password,
+ java.net.Socket connection);
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/Echo.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/Echo.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/Echo.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,125 @@
+package net.sourceforge.jsocks.test;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+
+/** Plain SOCKS unaware echo client.*/
+
+public class Echo implements Runnable{
+
+ private int port;
+ private InetAddress peerIp;
+
+ private Socket ss;
+ private InputStream in;
+ private OutputStream out;
+
+ private static final int BUF_SIZE = 1024;
+
+
+ public Echo(String host,int port,String peerHost,int peerPort)
+ throws IOException,UnknownHostException{
+ this.peerIp = InetAddress.getByName(peerHost);
+ this.port = port;
+
+ ss = new Socket(host, port,peerIp,peerPort);
+ out = ss.getOutputStream();
+ in = ss.getInputStream();
+ System.out.println("Connected...");
+ System.out.println("TO: "+host+":"+port);
+ System.out.println("LocalAddress: "+ss.getLocalAddress().getHostAddress()
+ +":"+ss.getLocalPort());
+
+ }
+ public Echo(String host,int port)
+ throws IOException,UnknownHostException{
+
+ System.out.println("Connecting...");
+ ss = new Socket(host, port);
+ out = ss.getOutputStream();
+ in = ss.getInputStream();
+ System.out.println("TO: "+host+":"+port);
+ System.out.println("LocalAddress: "+ss.getLocalAddress().getHostAddress()
+ +":"+ss.getLocalPort());
+
+ }
+
+
+ public void send(String s) throws IOException{
+ //System.out.println("Sending:"+s);
+ out.write(s.getBytes());
+ }
+
+ public void run(){
+ byte[] buf = new byte[1024];
+ int bytes_read;
+ try{
+ while((bytes_read = in.read(buf)) > 0){
+ System.out.write(buf,0,bytes_read);
+ System.out.flush();
+ }
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ }
+ }
+
+ public static void usage(){
+ System.err.print(
+ "Usage: java Echo host port [peerHost peerPort]\n");
+ }
+
+
+ public static void main(String args[]){
+ int port;
+ String host,peerHost;
+ int peerPort;
+ Echo echo = null;
+
+ if(args.length > 1){
+ try{
+
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+
+ if(args.length ==4){
+ peerHost = args[2];
+ peerPort =Integer.parseInt(args[3]);
+ echo = new Echo(host,port,peerHost,peerPort);
+ }else{
+ echo = new Echo(host,port);
+ }
+
+ Thread thread = new Thread(echo);
+ thread.start();
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ String s;
+
+ s = in.readLine();
+ Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+ while(s != null){
+ echo.send(s+"\r\n");
+ s = in.readLine();
+ }
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+ }catch(NumberFormatException num_ex){
+ usage();
+ num_ex.printStackTrace();
+ System.exit(1);
+ }finally{
+ if(echo!=null) try{echo.ss.close();}catch(Exception e){}
+ }
+
+ }else{
+ usage();
+ }
+ }
+
+}//End of class
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksTest.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksTest.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksTest.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,129 @@
+package net.sourceforge.jsocks.test;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import net.sourceforge.jsocks.socks.*;
+//import net.sourceforge.jsocks.socks.Proxy;
+
+/** SOCKS aware echo client*/
+
+public class SocksTest implements Runnable{
+
+ private int port;
+ private InetAddress hostIP;
+
+ private Socket ss;
+ private InputStream in;
+ private OutputStream out;
+
+ private static final int BUF_SIZE = 1024;
+ static final int defaultProxyPort = 1080; //Default Port
+ static final String defaultProxyHost = "www-proxy"; //Default proxy
+
+ public SocksTest(String host,int port)
+ throws IOException,UnknownHostException,SocksException{
+ this.port = port;
+
+ ss = new SocksSocket(host, port);
+ out = ss.getOutputStream();
+ in = ss.getInputStream();
+ System.out.println("Connected...");
+ System.out.println("TO: "+host+":"+port);
+ System.out.println("ViaProxy: "+ss.getLocalAddress().getHostAddress()
+ +":"+ss.getLocalPort());
+
+ }
+
+ public void close()throws IOException{
+ ss.close();
+ }
+ public void send(String s) throws IOException{
+ out.write(s.getBytes());
+ }
+
+ public void run(){
+ byte[] buf = new byte[1024];
+ int bytes_read;
+ try{
+ while((bytes_read = in.read(buf)) > 0){
+ System.out.write(buf,0,bytes_read);
+ }
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ }
+ }
+
+ public static void usage(){
+ System.err.print(
+ "Usage: java SocksTest host port [socksHost socksPort]\n");
+ }
+
+
+ public static void main(String args[]){
+ int port;
+ String host;
+ int proxyPort;
+ String proxyHost;
+
+ if(args.length > 1 && args.length < 5){
+ try{
+
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+
+ proxyPort =(args.length > 3)? Integer.parseInt(args[3])
+ : defaultProxyPort;
+
+ host = args[0];
+ proxyHost =(args.length > 2)? args[2]
+ : defaultProxyHost;
+
+ Proxy.setDefaultProxy(proxyHost,proxyPort,"KOUKY001");
+ //Proxy.setDefaultProxy(proxyHost,proxyPort);
+ InetRange inetRange = new InetRange();
+ inetRange.add(InetAddress.getByName("localhost"));
+ Proxy.getDefaultProxy().setDirect(inetRange);
+
+
+ SocksTest st = new SocksTest(host,port);
+ Thread thread = new Thread(st);
+ thread.start();
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ String s;
+
+ s = in.readLine();
+ while(s != null){
+ st.send(s+"\r\n");
+ //try{
+ //Thread.currentThread().sleep(10);
+ //}catch(InterruptedException i_ex){
+ //}
+ s = in.readLine();
+ }
+ st.close();
+ System.exit(1);
+
+ }catch(SocksException s_ex){
+ System.err.println("SocksException:"+s_ex);
+ s_ex.printStackTrace();
+ System.exit(1);
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+ }catch(NumberFormatException num_ex){
+ usage();
+ num_ex.printStackTrace();
+ System.exit(1);
+ }
+
+ }else{
+ usage();
+ }
+ }
+
+}//End of class
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksUDPEcho.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksUDPEcho.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/SocksUDPEcho.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,103 @@
+package net.sourceforge.jsocks.test;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.io.*;
+
+import net.sourceforge.jsocks.socks.*;
+
+/** SOCKS aware UDP echo client.<br>
+ Reads input line by line and sends it to given on command line
+ host and port, using given proxy, then blocks until reply datagram
+ recieved, not really echo, single threaded client, I just used it
+ for testing before UDP actually worked.
+*/
+public class SocksUDPEcho{
+
+ public static void usage(){
+ System.err.print(
+ "Usage: java SocksUDPEcho host port [socksHost socksPort]\n");
+ }
+
+ static final int defaultProxyPort = 1080; //Default Port
+ static final String defaultProxyHost = "www-proxy"; //Default proxy
+
+ public static void main(String args[]){
+ int port;
+ String host;
+ int proxyPort;
+ String proxyHost;
+ InetAddress ip;
+
+ if(args.length > 1 && args.length < 5){
+ try{
+
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+
+ proxyPort =(args.length > 3)? Integer.parseInt(args[3])
+ : defaultProxyPort;
+
+ host = args[0];
+ ip = InetAddress.getByName(host);
+
+ proxyHost =(args.length > 2)? args[2]
+ : defaultProxyHost;
+
+ Proxy.setDefaultProxy(proxyHost,proxyPort);
+ Proxy p = Proxy.getDefaultProxy();
+ p.addDirect("lux");
+
+
+ DatagramSocket ds = new Socks5DatagramSocket();
+
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ String s;
+
+ System.out.print("Enter line:");
+ s = in.readLine();
+
+ while(s != null){
+ byte[] data = (s+"\r\n").getBytes();
+ DatagramPacket dp = new DatagramPacket(data,0,data.length,
+ ip,port);
+ System.out.println("Sending to: "+ip+":"+port);
+ ds.send(dp);
+ dp = new DatagramPacket(new byte[1024],1024);
+
+ System.out.println("Trying to recieve on port:"+
+ ds.getLocalPort());
+ ds.receive(dp);
+ System.out.print("Recieved:\n"+
+ "From:"+dp.getAddress()+":"+dp.getPort()+
+ "\n\n"+
+ new String(dp.getData(),dp.getOffset(),dp.getLength())+"\n"
+ );
+ System.out.print("Enter line:");
+ s = in.readLine();
+
+ }
+ ds.close();
+ System.exit(1);
+
+ }catch(SocksException s_ex){
+ System.err.println("SocksException:"+s_ex);
+ s_ex.printStackTrace();
+ System.exit(1);
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+ }catch(NumberFormatException num_ex){
+ usage();
+ num_ex.printStackTrace();
+ System.exit(1);
+ }
+
+ }else{
+ usage();
+ }
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestClient.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestClient.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestClient.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,241 @@
+package net.sourceforge.jsocks.test;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+
+import net.sourceforge.jsocks.socks.*;
+import net.sourceforge.jsocks.socks.Proxy;
+
+public class TestClient extends TestService{
+ /** Proxy which should be used*/
+ Proxy proxy;
+ /** Host on which TestServer is running*/
+ String testHost;
+
+ int timeout = 15000;
+ int acceptTimeout = 0;
+
+ BufferedReader in;
+ Writer out;
+
+ public TestClient(Proxy p,String testHost){
+ this.proxy = p;
+ this.testHost = testHost;
+ if(log == null) log = System.out;
+ }
+
+ public void start(){
+ connectTests(true);
+ acceptTests(true);
+ udpTests(true);
+
+ connectTests(false);
+ acceptTests(false);
+ udpTests(false);
+ }
+
+ void connectTests(boolean useString){
+ try{
+ open(ECHO, useString);
+ testEcho();
+ s.close();
+
+ open(DISCARD, useString);
+ testDiscard();
+ s.close();
+
+ open(CHARGEN, useString);
+
+ for(int i = 0; i< 3;){
+ try{
+ testChargen();
+ break;
+ }catch(InterruptedIOException ioe){
+ log("IO interrupted:"+i);
+ i++;
+ }
+ }
+
+ s.close();
+
+ }catch(IOException ioe){
+ ioe.printStackTrace();
+ }
+
+ }
+
+ void acceptTests(boolean useString){
+ try{
+ testAccept(ECHO, useString);
+ testEcho();
+ s.close();
+
+ testAccept(DISCARD, useString);
+ testDiscard();
+ s.close();
+
+ testAccept(CHARGEN, useString);
+
+ for(int i = 0; i< 3;){
+ try{
+ testChargen();
+ break;
+ }catch(InterruptedIOException ioe){
+ log("IO interrupted:"+i);
+ i++;
+ }
+ }
+ s.close();
+
+ }catch(IOException ioe){
+ ioe.printStackTrace();
+ }
+ }
+
+ void udpTests(boolean useString){
+ log("Udp tests are not yet implemented");
+ }
+
+ void testEcho() throws IOException{
+ log("Testing echo.");
+ for(int i=0;i<5;++i){
+ out.write("String number "+i+"\r\n");
+ out.flush();
+ log("Echo:"+in.readLine());;
+ }
+ log("Echo finished");
+ }
+
+ void testDiscard() throws IOException{
+ log("Testing discard");
+ for(int i =0; i < 5;++i){
+ log("Sending discard message:"+i);
+ out.write("Discard message:"+i+"\r\n");
+ out.flush();
+ }
+ log("Discard finished");
+ }
+
+ void testChargen() throws IOException{
+ log("Testing chargen");
+ String s;
+ s = in.readLine();
+ while(s!=null){
+ log("ChGen:"+s);
+ s = in.readLine();
+ }
+ log("Chargen finished.");
+ }
+
+ void testAccept(int service,boolean useString)throws IOException{
+ open(CONNECT,useString);
+
+ log("Testing accept");
+ ServerSocket ss;
+
+ if(useString)
+ ss = new SocksServerSocket(proxy,testHost,servicePorts[service]);
+ else
+ ss = new SocksServerSocket(proxy,InetAddress.getByName(testHost),
+ servicePorts[service]);
+ log("Listenning on "+ss.getInetAddress()+":"+ss.getLocalPort());
+ ss.setSoTimeout(acceptTimeout);
+
+ out.write(""+ss.getLocalPort()+" "+service+"\r\n");
+ out.flush();
+
+ String line = in.readLine();
+ if(line != null){
+ log("Accept failed:"+line);
+ }
+
+ s.close();
+
+ s = ss.accept();
+ log("Accepted:"+s);
+
+ s.setSoTimeout(timeout);
+
+ out = new OutputStreamWriter(s.getOutputStream());
+ in = new BufferedReader(new InputStreamReader(s.getInputStream()));
+
+ ss.close();
+ }
+
+ void open(int service,boolean useString) throws IOException{
+
+ if(!useString){
+ s = new SocksSocket(proxy,InetAddress.getByName(testHost),
+ servicePorts[service]);
+ }else{
+ s = new SocksSocket(proxy,testHost,servicePorts[service]);
+ }
+
+ s.setSoTimeout(timeout);
+
+ out = new OutputStreamWriter(s.getOutputStream());
+ in = new BufferedReader(new InputStreamReader(s.getInputStream()));
+ }
+
+ //Main function
+ ///////////////
+
+ static void usage(){
+ System.err.println(
+ "Usage: java Testclient testhost proxy [directhosts]");
+ }
+
+ static Proxy initProxy(String ps){
+ java.util.StringTokenizer st = new java.util.StringTokenizer(ps,",;");
+ Proxy proxy = null;
+ while(st.hasMoreElements()){
+ String entry = st.nextToken();
+ Proxy p = Proxy.parseProxy(entry);
+ if( p == null){
+ log("Proxy "+entry+" invalid.");
+ return null;
+ }
+ p.setChainProxy(proxy);
+ proxy = p;
+ }
+ return proxy;
+ }
+ static void addDirectHosts(Proxy p, String directHosts){
+ java.util.StringTokenizer st = new java.util.StringTokenizer(
+ directHosts,",;");
+
+ while(st.hasMoreElements()){
+ String entry = st.nextToken();
+ log("Adding direct host:"+entry);
+ p.addDirect(entry);
+ }
+ }
+
+ public static void main(String[] argv){
+ if(argv.length < 2){
+ usage();
+ return;
+ }
+
+ log = System.out;
+
+ String testHost = argv[0];
+ String proxyHost = argv[1];
+ String directHosts = argv.length >2 ? argv[2] : null;
+
+ Proxy p = initProxy(proxyHost);
+ if(p == null){
+ log("Can't init proxy.");
+ return;
+ }
+ if(directHosts!=null) addDirectHosts(p,directHosts);
+
+ if(p instanceof Socks5Proxy)
+ ((Socks5Proxy) p).resolveAddrLocally(false);
+
+ TestClient tc = new TestClient(p,testHost);
+ tc.start();
+
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestServer.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestServer.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestServer.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,83 @@
+package net.sourceforge.jsocks.test;
+
+import java.io.*;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import net.*;
+
+/**
+ Server to used perform tests for SOCKS library.
+*/
+public class TestServer implements Runnable{
+ static PrintStream log = null;
+
+ int service;
+
+
+ /**
+ Creates a TestServer object which will listen on the port associated
+ with given service.
+
+ @param service Service to provide
+ */
+ public TestServer(int service){
+ this.service = service;
+ }
+
+ public void run(){
+ try{
+ server(service);
+ }catch(IOException ioe){
+ log("Exception:"+ioe);
+ ioe.printStackTrace();
+ }
+ }
+ //Static functions
+ /////////////////
+
+
+ /**
+ Listens on the port associated with given service.
+ <p>
+ When connection is accepted, speciefied service is performed.
+ It is being done in separate thread.
+ @return Never returns.
+ */
+ static public void server(int service) throws IOException{
+ ServerSocket ss = new ServerSocket(TestService.servicePorts[service]);
+ Socket s;
+
+ s = ss.accept();
+ while(s!=null){
+ TestService st = new TestService(s,service);
+ Thread t = new Thread(st);
+ t.start();
+ s = ss.accept();
+ }
+ }
+
+
+ /**
+ Performs logging.
+ */
+ static synchronized void log(String s){
+ if(log != null) log.println(s);
+ }
+
+ //Main Function
+ ///////////////
+ public static void main(String[] args){
+ log = System.out;
+ TestService.log = log;
+
+ TestServer st;
+ for( int i = 0; i< TestService.serviceNames.length;++i){
+ log("Starting service "+TestService.serviceNames[i]+" at port "+
+ TestService.servicePorts[i]+".");
+ st = new TestServer(i);
+ Thread t = new Thread(st);
+ t.start();
+ }
+ }
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestService.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestService.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/TestService.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,275 @@
+package net.sourceforge.jsocks.test;
+
+import java.io.*;
+import java.net.Socket;
+
+import net.*;
+
+/**
+ Server to used perform tests for SOCKS library.
+*/
+public class TestService implements Runnable{
+ static final String chargenSequence = " !\"#$%&'()*+,-./0123456789:;<=>?@"+
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefg";
+
+ static final String serviceNames[] = {"echo","discard","chargen","connect"};
+ static final int servicePorts[] = {5678,5679,5680,5681};
+
+ static final int ECHO = 0;
+ static final int DISCARD = 1;
+ static final int CHARGEN = 2;
+ static final int CONNECT = 3;
+
+ static final int BUF_SIZE = 1024;
+
+ static final int CHARGEN_WAIT = 1000; //1 second
+ static final int MAX_WAIT = 60000; //1 minute
+
+ static PrintStream log = null;
+
+ //Class constants
+ Socket s;
+ int service;
+
+ /**
+ Creates new TestService object, which will perform particular
+ service on given socket.
+
+ @param s Socket on which to perform service.
+ @param service Service which to provide.
+ */
+ public TestService(Socket s, int service){
+ this.s = s;
+ this.service = service;
+ }
+
+ /**
+ Default constructor.
+ */
+ public TestService(){
+ this.s = null;
+ this.service = -1;
+ }
+
+ public void run(){
+ try{
+ serve(s,service);
+ }catch(IOException ioe){
+ log("Exception:"+ioe);
+ ioe.printStackTrace();
+ }
+ try{ s.close();}catch(IOException ioe){}
+ }
+
+ //Static functions
+ /////////////////
+
+ /**
+ Maps service name to the integer id, does it in simple
+ linear search manner.
+ @param serviceName Name of the service whose id one needs.
+ @return Integer identifier for this servuce, or -1, if service
+ can't be found.
+ */
+ static public int getServiceId(String serviceName){
+ serviceName = serviceName.toLowerCase();
+ for(int i = 0;i < serviceNames.length;++i)
+ if(serviceName.equals(serviceNames[i]))
+ return i;
+
+ //Couldn't find one.
+ return -1;
+ }
+
+ /**
+ Performs given service on given socket.
+ <p>
+ Simply looks up and calls associated method.
+ @param s Socket on which to perform service.
+ @param service Id of the service to perform.
+ @return true if service have been found, false otherwise.
+ */
+ static public boolean serve(Socket s, int service) throws IOException{
+ switch(service){
+ case ECHO:
+ echo(s);
+ break;
+ case DISCARD:
+ discard(s);
+ break;
+ case CHARGEN:
+ chargen(s,CHARGEN_WAIT,MAX_WAIT);
+ break;
+ case CONNECT:
+ connect(s);
+ break;
+ default:
+ log("Unknown service:"+service);
+ return false;
+ }
+ return true;
+ }
+ /**
+ Echos any input on the socket to the output.
+ Echo is being done line by line.
+ @param s Socket on which to perform service.
+ */
+ static public void echo(Socket s) throws IOException{
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ s.getInputStream()));
+ OutputStream out = s.getOutputStream();
+
+ log("Starting \"echo\" on "+s);
+
+ String line = in.readLine();
+ while(line != null){
+ out.write((line+"\n").getBytes());
+ log(line);
+ line = in.readLine();
+ }
+
+ log("Echo done.");
+ }
+
+ /**
+ Reads input from the socket, and does not write anything back.
+ logs input in line by line fashion.
+ @param s Socket on which to perform service.
+ */
+ static public void discard(Socket s) throws IOException{
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ s.getInputStream()));
+ log("Starting discard on "+s);
+
+ String line = in.readLine();
+ while(line != null){
+ log(line);
+ line = in.readLine();
+ }
+
+ log("Discard finished.");
+ }
+
+ /**
+ Generates characters and sends them to the socket.
+ <p>
+ Unlike usual chargen (port 19), each next line of the generated
+ output is send after increasingly larger time intervals. It starts
+ from wait_time (ms), and each next time wait time is doubled.
+ Eg. 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 ... well
+ you got the idea.
+ <p>
+ It starts if either connection is clsoed or the wait time grows
+ bigger than max_wait.
+
+ @param s Socket on which to perform service.
+ @param wait_time Time in ms, from which timing sequence should begin.
+ @param max_wait Time in ms, after reaching timeout greater than this
+ value, chargen will stop.
+ */
+ static public void chargen(Socket s,long wait_time,long max_wait)
+ throws IOException{
+ byte[] buf = chargenSequence.getBytes();
+ int pos = 0;
+ OutputStream out = s.getOutputStream();
+ InputStream in = s.getInputStream();
+ s.setSoTimeout(100); //0.1 ms
+
+ log("Starting \"chargen\" on "+s);
+ while(true){
+ log("Sending message.");
+ out.write(buf,pos,buf.length - pos);
+ out.write(buf,0,pos);
+ out.write("\n".getBytes());
+ pos++;
+ try{
+ if(wait_time > max_wait) break;
+
+ log("Going to sleep for "+wait_time+" ms.");
+ Thread.currentThread().sleep(wait_time);
+ wait_time *= 2;
+ if(in.read() < 0) break; //Connection closed
+ }catch(InterruptedException ie){
+ }catch(InterruptedIOException ioe){
+ }
+ }
+ log("Chargen finished.");
+ }
+
+ /**
+ Models connect back situation.
+ <p>
+ Reads a line from the socket connection, line should be in the
+ form port service_id. Connects back to the remote host to port
+ specified in the line, if successful performs a service speciefied
+ by id on that new connection. If accept was successful closes the
+ control connection, else outputs error message, and then closes
+ the connection.
+
+ @param s Control connection.
+ */
+ static public void connect(Socket s)throws IOException{
+ String line = null;
+ Socket sock;
+ int port;
+ int service_id;
+
+ BufferedReader in = new BufferedReader(new InputStreamReader(
+ s.getInputStream()));
+ OutputStream out = s.getOutputStream();
+
+ log("Starting \"connect\" on "+s);
+ line = in.readLine();
+ if(line == null) return; //They closed connection
+
+ java.util.StringTokenizer st = new java.util.StringTokenizer(line);
+ if(st.countTokens() < 2){ //We need at least 'port' and "id"
+ out.write("Expect: port serviceId.\n".getBytes());
+ log("Invalid arguments.");
+ return;
+ }
+ try{
+ port = Integer.parseInt(st.nextToken());
+ service_id = Integer.parseInt(st.nextToken());
+ }catch(NumberFormatException nfe){
+ out.write("Expect: port serviceId.\n".getBytes());
+ log("Invalid arguments.");
+ return;
+ }
+ try{
+ log("Connecting to "+s.getInetAddress()+":"+port);
+ sock = new Socket(s.getInetAddress(),port);
+ }catch(IOException ioe){
+ out.write(("Connect to "+s.getInetAddress()+
+ ":"+port+" failed").getBytes());
+ log("Connect failed.");
+ return;
+ }
+ s.close();
+ log("About to serve "+service_id);
+ serve(sock,service_id);
+ }
+
+ /**
+ Pipes data from the input stream to the output.
+ @param in Input stream.
+ @param out Output stream.
+ */
+ static public void pipe(InputStream in, OutputStream out)
+ throws IOException{
+ byte[] buf = new byte[BUF_SIZE];
+ int bread = 0;
+ while(bread >= 0){
+ bread = in.read(buf);
+ out.write(buf,0,bread);
+ }
+ }
+
+ /**
+ Performs logging.
+ */
+ static synchronized void log(String s){
+ if(log != null) log.println(s);
+ }
+
+}
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UDPEcho.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UDPEcho.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UDPEcho.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,151 @@
+package net.sourceforge.jsocks.test;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.io.*;
+
+import net.*;
+/**
+ Plain SOCKS unaware UDP echo server and client.
+*/
+public class UDPEcho implements Runnable{
+
+ private int port;
+ private InetAddress hostIP;
+ private DatagramSocket sock;
+
+ private static final int BUF_SIZE = 1024;
+
+
+ public UDPEcho(String host,int port)
+ throws IOException,UnknownHostException{
+ this.hostIP = InetAddress.getByName(host);
+ this.port = port;
+ sock = new DatagramSocket();
+ System.out.println("UDP: "+sock.getLocalAddress()+":"+
+ sock.getLocalPort());
+ //sock.connect(hostIP,port);
+ }
+
+ public void send(String s) throws IOException{
+ System.out.println("Sending:"+s);
+ DatagramPacket packet = new DatagramPacket(s.getBytes(),
+ s.length(),
+ hostIP,
+ port);
+ sock.send(packet);
+ }
+
+ public void run(){
+ byte[] buf = new byte[BUF_SIZE];
+ DatagramPacket incomingData = new DatagramPacket(buf,buf.length);
+ try{
+ while(true){
+ sock.receive(incomingData);
+ System.out.println("UDP From:"+
+ incomingData.getAddress().getHostAddress()+":"+
+ incomingData.getPort());
+ System.out.println(new String(incomingData.getData(),
+ 0,incomingData.getLength()));
+ System.out.flush();
+ incomingData.setLength(buf.length);
+ }
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ }
+ }
+
+ public static void usage(){
+ System.err.print(
+ "Usage: java UDPEcho host port\n"+
+ "OR\n"+
+ "Usage: java UDPEcho port\n");
+ }
+
+ public static void doEcho(int port)throws IOException{
+ byte[] buf = new byte[BUF_SIZE];
+ DatagramPacket packet = new DatagramPacket(buf,buf.length);
+ DatagramSocket sock = new DatagramSocket(port);
+
+ System.out.println("Starting UDP echo on"+
+ sock.getLocalAddress().getHostAddress()+
+ ":"+sock.getLocalPort());
+ while(true){
+ try{
+ sock.receive(packet);
+ sock.send(packet);
+ System.out.print(
+ "UDP From: "+packet.getAddress().getHostAddress()+":"+
+ packet.getPort()+
+ "\n"+
+ new String(packet.getData(),0,packet.getLength())+
+ "\n"
+ );
+ System.out.flush();
+
+ packet.setLength(buf.length);
+ //packet = new DatagramPacket(buf,buf.length);
+ }catch(IOException io_ex){
+ }
+ }
+ }
+
+ public static void main(String args[]){
+ int port;
+ String host;
+
+ if(args.length == 1){
+ try{
+ port = Integer.parseInt(args[0]);
+
+ doEcho(port);
+
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+
+ }catch(NumberFormatException num_ex){
+ num_ex.printStackTrace();
+ System.exit(1);
+ }
+ }else if(args.length == 2){
+ try{
+ host = args[0];
+ port = Integer.parseInt(args[1]);
+
+ UDPEcho ut = new UDPEcho(host,port);
+ Thread thread = new Thread(ut);
+ thread.start();
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(System.in));
+ String s;
+ System.out.print("Enter datagram:");
+ s = in.readLine();
+ while(s != null){
+ ut.send(s);
+ try{
+ Thread.currentThread().sleep(100);
+ }catch(InterruptedException i_ex){
+ }
+ System.out.print("Enter datagram:");
+ s = in.readLine();
+ }
+ System.exit(1);
+
+ }catch(IOException io_ex){
+ io_ex.printStackTrace();
+ System.exit(1);
+ }catch(NumberFormatException num_ex){
+ num_ex.printStackTrace();
+ System.exit(1);
+ }
+
+ }else{
+ usage();
+ }
+ }
+
+}//End of class
Added: projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UPSOCKS.java
===================================================================
--- projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UPSOCKS.java (rev 0)
+++ projects/android/trunk/asocks/src/net/sourceforge/jsocks/test/UPSOCKS.java 2009-10-25 04:59:39 UTC (rev 20837)
@@ -0,0 +1,41 @@
+package net.sourceforge.jsocks.test;
+
+import net.sourceforge.jsocks.socks.*;
+import net.sourceforge.jsocks.socks.server.*;
+
+import java.net.Socket;
+
+/** Test file for UserPasswordAuthentictor */
+
+public class UPSOCKS implements UserValidation{
+ String user, password;
+
+ UPSOCKS(String user,String password){
+ this.user = user;
+ this.password = password;
+ }
+
+ public boolean isUserValid(String user,String password,Socket s){
+ System.err.println("User:"+user+"\tPassword:"+password);
+ System.err.println("Socket:"+s);
+ return (user.equals(this.user) && password.equals(this.password));
+ }
+
+ public static void main(String args[]){
+ String user, password;
+
+ if(args.length == 2){
+ user = args[0];
+ password = args[1];
+ }else{
+ user = "user";
+ password = "password";
+ }
+
+ UPSOCKS us = new UPSOCKS(user,password);
+ UserPasswordAuthenticator auth = new UserPasswordAuthenticator(us);
+ ProxyServer server = new ProxyServer(auth);
+
+ server.start(1080);
+ }
+}