1. /*
  2. * @(#)SocksSocketImplFactory.java 1.4 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.security.AccessController;
  9. import java.security.PrivilegedExceptionAction;
  10. import java.io.InputStream;
  11. import java.io.OutputStream;
  12. /**
  13. * This factory creates an SocketImpl that implements the SOCKS protocol
  14. * (both V5 & V4). It implements RFC 1928.
  15. *
  16. * @see java.net.Socket#setSocketImplFactory(SocketImplFactory)
  17. * @see java.net.ServerSocket#setSocketImplFactory(SocketImplFactory)
  18. */
  19. class SocksSocketImplFactory implements SocketImplFactory, SocksConsts {
  20. private String server;
  21. private int port = -1;
  22. private boolean useV4 = false;
  23. /**
  24. * Creates a SocksSocketImplFactory with a specific server & port.
  25. * This should point to a SOCKS v5 proxy server.
  26. *
  27. * @param server the server hostname
  28. * @param port the port number. -1 for the default SOCKS port.
  29. */
  30. SocksSocketImplFactory(String server, int port) {
  31. this.server = server;
  32. this.port = port == -1 ? DEFAULT_PORT : port;
  33. guessVersion();
  34. }
  35. /**
  36. * Creates a SocksSocketImplFactory with a specific server & port.
  37. *
  38. * @param server the server hostname
  39. * @param port the port number. -1 for the default SOCKS port.
  40. * @param v4 <code>true</code> if the protocol should be version 4
  41. * <code>false</code> for version 5.
  42. */
  43. SocksSocketImplFactory(String server, int port, boolean v4) {
  44. this.server = server;
  45. this.port = port == -1 ? DEFAULT_PORT : port;
  46. this.useV4 = v4;
  47. }
  48. /*
  49. * Checks whether the System properties changed.
  50. * If they did, we need to renegociate the protocol version
  51. */
  52. private synchronized void checkProps() {
  53. boolean changed = false;
  54. int newport = DEFAULT_PORT;
  55. String socksPort = null;
  56. String socksHost =
  57. (String) java.security.AccessController.doPrivileged(
  58. new sun.security.action.GetPropertyAction("socksProxyHost"));
  59. socksPort =
  60. (String) java.security.AccessController.doPrivileged(
  61. new sun.security.action.GetPropertyAction("socksProxyPort"));
  62. if (socksPort != null) {
  63. try {
  64. newport = Integer.parseInt(socksPort);
  65. } catch (Exception e) {
  66. newport = DEFAULT_PORT;
  67. }
  68. }
  69. if (socksHost != null && !socksHost.equals(this.server)) {
  70. this.server = socksHost;
  71. changed = true;
  72. }
  73. if (newport != this.port) {
  74. this.port = newport;
  75. changed = true;
  76. }
  77. if (changed) {
  78. guessVersion();
  79. }
  80. }
  81. private void guessVersion() {
  82. Socket s;
  83. // Connects to the SOCKS server
  84. try {
  85. s = (Socket) AccessController.doPrivileged(new PrivilegedExceptionAction() {
  86. public Object run() throws Exception {
  87. Socket so = new Socket(new PlainSocketImpl());
  88. so.connect(new InetSocketAddress(server, port));
  89. return so;
  90. }
  91. });
  92. } catch (Exception e) {
  93. e.printStackTrace();
  94. return;
  95. }
  96. InputStream in = null;
  97. OutputStream out = null;
  98. try {
  99. // If it's taking too long to get an answer, then it's probably
  100. // the wrong version
  101. s.setSoTimeout(1000);
  102. out = s.getOutputStream();
  103. in = s.getInputStream();
  104. // Try V5 first
  105. out.write(PROTO_VERS);
  106. out.write(2);
  107. out.write(NO_AUTH);
  108. out.write(USER_PASSW);
  109. out.flush();
  110. int i = in.read();
  111. if (i == PROTO_VERS) {
  112. // All rigth it's V5
  113. useV4 = false;
  114. i = in.read();
  115. } else {
  116. // V5 doesn't work, let's assume it's V4
  117. useV4 = true;
  118. }
  119. in.close();
  120. out.close();
  121. s.close();
  122. } catch (java.net.SocketTimeoutException te) {
  123. // Timeout. Took too long let's assume it's V4 then
  124. useV4 = true;
  125. try {
  126. in.close();
  127. out.close();
  128. s.close();
  129. } catch (Exception e2) {
  130. }
  131. } catch (java.io.IOException ioe) {
  132. // Nothing much we can do here, but we tried
  133. }
  134. }
  135. /**
  136. * Creates a new <code>SocketImpl</code> instance.
  137. *
  138. * @return a new instance of <code>SocketImpl</code>.
  139. * @see java.net.SocketImpl
  140. */
  141. public SocketImpl createSocketImpl() {
  142. checkProps();
  143. SocksSocketImpl impl = new SocksSocketImpl(server, port);
  144. if (useV4)
  145. impl.setV4();
  146. return impl;
  147. }
  148. }