/**
* Copyright (c) 2009 - 2012 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org>
*
* This file is part of org.appwork.utils.net.httpconnection
*
* This software is licensed under the Artistic License 2.0,
* see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php
* for details
*/
package org.appwork.utils.net.httpconnection;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
/**
* @author daniel
*
*/
public class Socks4HTTPConnectionImpl extends SocksHTTPconnection {
public Socks4HTTPConnectionImpl(final URL url, final HTTPProxy proxy) {
super(url, proxy);
}
@Override
protected void authenticateProxyPlain() throws IOException {
/* SOCKS4 has no authentication */
}
@Override
protected Socket establishConnection() throws IOException {
try {
/* tcp/ip connection */
this.socksoutputstream.write((byte) 1);
/* send port */
/* network byte order */
this.socksoutputstream.write(this.httpPort >> 8 & 0xff);
this.socksoutputstream.write(this.httpPort & 0xff);
boolean ipResolvOK = false;
/* send domain ip */
try {
final InetAddress addr = InetAddress.getByName(this.httpHost);
if (addr == null) { throw new UnknownHostException("Could not resolv host"); }
final byte[] addrIP = addr.getAddress();
this.proxyRequest.append("->SEND tcp connect request by ip\r\n");
this.socksoutputstream.write(addrIP);
ipResolvOK = true;
} catch (final UnknownHostException e) {
}
if (ipResolvOK == false) {
this.proxyRequest.append("->SEND tcp connect request by domain\r\n");
this.socksoutputstream.write((byte) 0);
this.socksoutputstream.write((byte) 0);
this.socksoutputstream.write((byte) 0);
this.socksoutputstream.write((byte) 100);
}
/* user ID string */
final String user = this.proxy.getUser() == null ? "" : this.proxy.getUser().trim();
final byte[] username = user.getBytes("ISO-8859-1");
if (username.length > 0) {
this.socksoutputstream.write(username);
}
this.socksoutputstream.write((byte) 0);
if (ipResolvOK == false) {
/* send domain as string,socks4a */
final byte[] domain = this.httpHost.getBytes("ISO-8859-1");
this.socksoutputstream.write(domain);
this.socksoutputstream.write((byte) 0);
}
this.socksoutputstream.flush();
/* read response, 8 bytes */
final byte[] resp = this.readResponse(8);
switch (resp[1]) {
case 0x5a:
break;
case 0x5b:
throw new SocketException("request rejected or failed");
case 0x5c:
throw new SocketException("request failed because client is not running identd (or not reachable from the server)");
case 0x5d:
throw new ConnectException("request failed because client's identd could not confirm the user ID string in the request");
default:
throw new ProxyConnectException("Socks4HTTPConnection: could not establish connection, status=" + resp[1], this.proxy);
}
return this.sockssocket;
} catch (final IOException e) {
try {
this.sockssocket.close();
} catch (final Throwable e2) {
}
if (e instanceof HTTPProxyException) { throw e; }
throw new ProxyConnectException(e, this.proxy);
}
}
@Override
protected AUTH sayHello() throws IOException {
try {
this.proxyRequest.append("->SOCKS4 Hello\r\n");
/* socks4 */
this.socksoutputstream.write((byte) 4);
return AUTH.NONE;
} catch (final IOException e) {
try {
this.sockssocket.close();
} catch (final Throwable e2) {
}
if (e instanceof HTTPProxyException) { throw e; }
throw new ProxyConnectException(e, this.proxy);
}
}
@Override
protected void validateProxy() throws IOException {
if (this.proxy == null || !this.proxy.getType().equals(HTTPProxy.TYPE.SOCKS4)) { throw new IOException("Socks4HTTPConnection: invalid Socks4 Proxy!"); }
}
}