Fix socks binds

This fixes socks binds so they actually send data both ways and
also can be rebound without waiting for the TIME_WAIT timeout.
Below is a handy script:

#!/usr/bin/python

import socket
import select
import fcntl
import struct
import errno
import os
import asyncore
import sys

proxy_port = 1080

try:
	proxy = sys.argv[1].split(':')
	proxy_server = proxy[0]
	if len(proxy) > 1:
		proxy_port = int(proxy[1])

	host = sys.argv[2].split(':')
	if len(host) > 2:
		listen_port = int(host[0])
		connect_address = host[1]
		connect_port = int(host[2])
	else:
		connect_address = host[0]
		connect_port = int(host[1])
		listen_port = connect_port
except:
	print 'socks_forward.py <proxy>[:<port>] [<listen_port:]<address>:<port>'
	sys.exit(1)

class socks_client(asyncore.dispatcher_with_send):
	def __init__(self, sock):
		asyncore.dispatcher_with_send.__init__(self)
		sock.setblocking(0)
		self.set_socket(sock)
		self.pc = None
		self.waiting = False

	def set_pass(self, pc):
		self.pc = pc;
		if self.waiting:
			self.pc.send(self.recv(8192))

	def handle_close(self):
		sys.exit(0)

	def handle_read(self):
		if self.pc is None:
			self.waiting = True
		else:
			self.pc.send(self.recv(8192))

class pass_client(asyncore.dispatcher_with_send):
	def __init__(self, host, port, sc):
		asyncore.dispatcher_with_send.__init__(self)
		self.sc = sc
		self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
		self.connect((host, port))
		self.host = host
		self.port = port

	def handle_connect(self):
		print 'Connected to', self.host + ':' + str(self.port)

	def handle_close(self):
		sys.exit(0)

	def handle_read(self):
		self.sc.send(self.recv(8192))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((proxy_server, proxy_port))
s.send(struct.pack('!BBHIB', 4, 2, listen_port, 0, 0))
ver, resp, port, ip = struct.unpack('!BBHI', s.recv(8))
ip = struct.pack('!I', ip);
if resp == 91:
	raise Exception("Denied")
elif resp != 90:
	raise Exception("Unknown response")
print 'Granted, ip', socket.inet_ntoa(ip), 'port', port
ver, resp, port, ip = struct.unpack('!BBHI', s.recv(8))
if resp != 90:
	raise Exception("Connect failed")

ip = struct.pack('!I', ip);
print 'Connection from', socket.inet_ntoa(ip) + ':' + str(port)

sc = socks_client(s)
pc = pass_client(connect_address, connect_port, sc)
sc.set_pass(pc)
asyncore.loop()