aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/sourceforge/jsocks/Socks4Message.java
blob: 1d68cb7cbb3bee9f765553eeaba123f8a2bb5796 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package net.sourceforge.jsocks;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
  SOCKS4 Reply/Request message.
*/

public 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);
   }

   @Override
public void read(InputStream in) throws IOException{
        read(in,true);
   }

   @Override
public void read(InputStream in, boolean clientMode) throws IOException{
       boolean mode4a = false;
       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);
       if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] != 0)
          mode4a = true;
       else {
          ip=bytes2IP(addr);
          host = ip.getHostName();
       }
       if(!clientMode){
          StringBuilder sb = new StringBuilder();
          int b;
          while ((b = in.read()) != 0)
             sb.append((char) b);
          user = sb.toString();
          if (mode4a) {
             sb.setLength(0);
             while ((b = in.read()) != 0)
                sb.append((char) b);
             host = sb.toString();
          }
       }
   }
   @Override
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;

}