auto-pod
Version:
Automatically choose tunneling or direct connection for cocoapods. As easy as `pod` itself. Help you get rid of GFW of China.
115 lines (96 loc) • 2.95 kB
text/typescript
/*
Rewritten from: https://github.com/TooTallNate/node-socks-proxy-agent
*/
import * as dns from 'dns';
import * as tls from 'tls';
import * as url from 'url';
import * as agentBase from 'agent-base';
import { SocksClient } from 'socks';
import { SocksCommandOption, SocksProxyType } from 'socks/typings/common/constants';
export interface IAuthentication {
username?: string;
password: string;
}
export interface IProxyInfo extends url.UrlObjectCommon {
// destination: SocksRemoteHost;
port: number;
version: number; // Socks Version.
authentication?: IAuthentication;
lookup: boolean;
command: SocksCommandOption;
timeout?: number;
}
/**
* The `SocksProxyAgent`.
*
* @api public
*/
export class SocksProxyAgent extends agentBase {
public maxFreeSockets: number;
public maxSockets: number;
public requests: any; // tslint:disable-line no-any
public sockets: any; // tslint:disable-line no-any
private proxy: IProxyInfo;
constructor(options?: IProxyInfo) {
super(options);
this.proxy = options;
}
public destroy() {} // tslint:disable-line no-empty
/**
* Initiates a SOCKS connection to the specified SOCKS proxy server,
* which in turn connects to the specified remote host and port.
*
* @api public
*/
public callback(req, opts, fn) {
const proxy = this.proxy;
// called once the SOCKS proxy has connected to the specified remote endpoint
function onhostconnect(err, result) {
if (err) return fn(err);
const socket = result.socket;
let s = socket;
if (opts.secureEndpoint) {
// since the proxy is connecting to an SSL server, we have
// to upgrade this socket connection to an SSL connection
opts.socket = socket;
opts.servername = opts.host;
opts.host = null;
opts.hostname = null;
opts.port = null;
s = tls.connect(opts);
}
fn(null, s);
}
// called for the `dns.lookup()` callback
function onlookup(err: Error, ip: string) {
if (err) return fn(err);
options.destination.host = ip;
SocksClient.createConnection(options, onhostconnect);
}
const options = {
command: 'connect' as SocksCommandOption,
destination: {
host: undefined,
port: +opts.port,
},
proxy: {
ipaddress: proxy.host,
password: undefined,
port: +proxy.port,
type: proxy.version as SocksProxyType,
userId: undefined,
},
};
if (proxy.authentication) {
options.proxy.userId = proxy.authentication.username;
options.proxy.password = proxy.authentication.password;
}
if (proxy.lookup) {
// client-side DNS resolution for "4" and "5" socks proxy versions
dns.lookup(opts.host, onlookup);
} else {
// proxy hostname DNS resolution for "4a" and "5h" socks proxy servers
onlookup(null, opts.host);
}
}
}