Browse Source

fix tcp fastopen

auth
clowwindy 11 years ago
parent
commit
cb5481499e
  1. 44
      shadowsocks/tcprelay.py

44
shadowsocks/tcprelay.py

@ -200,10 +200,12 @@ class TCPRelayHandler(object):
self._config['fast_open']: self._config['fast_open']:
try: try:
self._fastopen_connected = True self._fastopen_connected = True
remote_sock = self._create_remote_socket(self._chosen_server[0],
self._chosen_server[1])
self._loop.add(remote_sock, eventloop.POLL_ERR)
data = ''.join(self._data_to_write_to_local) data = ''.join(self._data_to_write_to_local)
l = len(data) l = len(data)
s = self._remote_sock.sendto(data, MSG_FASTOPEN, s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server)
self._chosen_server)
if s < l: if s < l:
data = data[s:] data = data[s:]
self._data_to_write_to_local = [data] self._data_to_write_to_local = [data]
@ -282,6 +284,19 @@ class TCPRelayHandler(object):
# TODO use logging when debug completed # TODO use logging when debug completed
self.destroy() self.destroy()
def _create_remote_socket(self, ip, port):
addrs = socket.getaddrinfo(ip, port, 0, socket.SOCK_STREAM,
socket.SOL_TCP)
if len(addrs) == 0:
raise Exception("getaddrinfo failed for %s:%d" % (ip, port))
af, socktype, proto, canonname, sa = addrs[0]
remote_sock = socket.socket(af, socktype, proto)
self._remote_sock = remote_sock
self._fd_to_handlers[remote_sock.fileno()] = self
remote_sock.setblocking(False)
remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
return remote_sock
def _handle_dns_resolved(self, result, error): def _handle_dns_resolved(self, result, error):
if error: if error:
logging.error(error) logging.error(error)
@ -292,33 +307,22 @@ class TCPRelayHandler(object):
if ip: if ip:
try: try:
self._stage = STAGE_REPLY self._stage = STAGE_REPLY
remote_addr = self._remote_address[0] remote_addr = ip
remote_port = self._remote_address[1]
if self._is_local: if self._is_local:
remote_addr, remote_port = self._chosen_server remote_port = self._chosen_server[1]
addrs = socket.getaddrinfo(ip, remote_port, 0, else:
socket.SOCK_STREAM, remote_port = self._remote_address[1]
socket.SOL_TCP)
if len(addrs) == 0:
raise Exception("getaddrinfo failed for %s:%d" %
(remote_addr, remote_port))
af, socktype, proto, canonname, sa = addrs[0]
remote_sock = socket.socket(af, socktype, proto)
self._remote_sock = remote_sock
self._fd_to_handlers[remote_sock.fileno()] = self
remote_sock.setblocking(False)
remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY,
1)
if self._is_local and self._config['fast_open']: if self._is_local and self._config['fast_open']:
# wait for more data to arrive and send them in one SYN # wait for more data to arrive and send them in one SYN
self._stage = STAGE_REPLY self._stage = STAGE_REPLY
self._loop.add(remote_sock, eventloop.POLL_ERR)
self._update_stream(STREAM_UP, WAIT_STATUS_READING) self._update_stream(STREAM_UP, WAIT_STATUS_READING)
# TODO when there is already data in this packet # TODO when there is already data in this packet
else: else:
remote_sock = self._create_remote_socket(remote_addr,
remote_port)
try: try:
remote_sock.connect(sa) remote_sock.connect((remote_addr, remote_port))
except (OSError, IOError) as e: except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == \ if eventloop.errno_from_exception(e) == \
errno.EINPROGRESS: errno.EINPROGRESS:

Loading…
Cancel
Save