def handle_socks(self, reader, writer):
    (version, authnum) = (yield from reader.read(2))
    if (version != 5):
        writer.close()
        return
    methods = (yield from reader.read(authnum))
    if (self.username and (2 in methods)):
        writer.write(b'\x05\x02')
        (version, ulen) = (yield from reader.read(2))
        username = (yield from reader.read(ulen))
        ulen = (yield from reader.read(1))[0]
        password = (yield from reader.read(ulen))
        if ((version == 1) and ((username == self.username) and (password == self.password))):
            writer.write(b'\x01\x00')
        else:
            writer.write(b'\x01\xff')
            writer.close()
            return
    elif ((self.username is None) and (0 in methods)):
        writer.write(b'\x05\x00')
    else:
        writer.write(b'\x05\xff')
        writer.close()
        return
    try:
        (version, command, reserved, addrtype) = (yield from reader.read(4))
    except ValueError:
        writer.close()
        return
    if (version != 5):
        writer.close()
        return
    if (addrtype == 1):
        host = (yield from reader.read(4))
        hostname = socket.inet_ntop(socket.AF_INET, host)
    elif (addrtype == 3):
        length = (yield from reader.read(1))[0]
        hostname = (yield from reader.read(length)).decode('utf-8')
    elif (addrtype == 4):
        host = (yield from reader.read(16))
        hostname = socket.inet_ntop(socket.AF_INET6, host)
    port = struct.unpack('!H', (yield from reader.read(2)))[0]
    sockname = writer.get_extra_info('sockname')
    if (len(sockname) == 2):
        bndinfo = (b'\x01' + socket.inet_pton(socket.AF_INET, sockname[0]))
    else:
        bndinfo = (b'\x04' + socket.inet_pton(socket.AF_INET6, sockname[0]))
    bndinfo += struct.pack('!H', sockname[1])
    if (command == 1):
        writer.write((b'\x05\x00\x00' + bndinfo))
    else:
        writer.write((b'\x05\x07\x00' + bndinfo))
        writer.close()
        return
    (r_reader, r_writer) = (yield from asyncio.open_connection(hostname, port))
    asyncio.ensure_future(proxy_data(reader, r_writer), loop=self.loop)
    asyncio.ensure_future(proxy_data(r_reader, writer), loop=self.loop)
def handle_socks(self, reader, writer):
    (version, authnum) = (yield from reader.read(2))
    if (version != 5):
        writer.close()
        return
    methods = (yield from reader.read(authnum))
    if (self.username and (2 in methods)):
        writer.write(b'\x05\x02')
        (version, ulen) = (yield from reader.read(2))
        username = (yield from reader.read(ulen))
        ulen = (yield from reader.read(1))[0]
        password = (yield from reader.read(ulen))
        if ((version == 1) and ((username == self.username) and (password == self.password))):
            writer.write(b'\x01\x00')
        else:
            writer.write(b'\x01\xff')
            writer.close()
            return
    elif ((self.username is None) and (0 in methods)):
        writer.write(b'\x05\x00')
    else:
        writer.write(b'\x05\xff')
        writer.close()
        return
    try:
        (version, command, reserved, addrtype) = (yield from reader.read(4))
    except ValueError:
        writer.close()
        return
    if (version != 5):
        writer.close()
        return
    if (addrtype == 1):
        host = (yield from reader.read(4))
        hostname = socket.inet_ntop(socket.AF_INET, host)
    elif (addrtype == 3):
        length = (yield from reader.read(1))[0]
        hostname = (yield from reader.read(length)).decode('utf-8')
    elif (addrtype == 4):
        host = (yield from reader.read(16))
        hostname = socket.inet_ntop(socket.AF_INET6, host)
    port = struct.unpack('!H', (yield from reader.read(2)))[0]
    sockname = writer.get_extra_info('sockname')
    if (len(sockname) == 2):
        bndinfo = (b'\x01' + socket.inet_pton(socket.AF_INET, sockname[0]))
    else:
        bndinfo = (b'\x04' + socket.inet_pton(socket.AF_INET6, sockname[0]))
    bndinfo += struct.pack('!H', sockname[1])
    if (command == 1):
        writer.write((b'\x05\x00\x00' + bndinfo))
    else:
        writer.write((b'\x05\x07\x00' + bndinfo))
        writer.close()
        return
    (r_reader, r_writer) = (yield from asyncio.open_connection(hostname, port))
    asyncio.ensure_future(proxy_data(reader, r_writer), loop=self.loop)
    asyncio.ensure_future(proxy_data(r_reader, writer), loop=self.loop)