implement fast open in local

This commit is contained in:
clowwindy 2014-06-03 21:59:34 +08:00
parent f6a9cad684
commit 0c12ee04cb
3 changed files with 57 additions and 11 deletions

View File

@ -13,3 +13,4 @@ script:
- python test.py -c tests/salsa20.json
- python test.py -c tests/server-multi-passwd.json
- python test.py -c tests/workers.json
- python test.py -c tests/fastopen.json

View File

@ -34,6 +34,8 @@ from common import parse_header
TIMEOUTS_CLEAN_SIZE = 512
TIMEOUT_PRECISION = 4
MSG_FASTOPEN = 0x20000000
CMD_CONNECT = 1
CMD_BIND = 2
CMD_UDP_ASSOCIATE = 3
@ -199,6 +201,34 @@ class TCPRelayHandler(object):
if is_local:
data = self._encryptor.encrypt(data)
self._data_to_write_to_remote.append(data)
if is_local and self._upstream_status == WAIT_STATUS_INIT and \
self._config['fast_open']:
try:
data = ''.join(self._data_to_write_to_local)
l = len(data)
s = self._remote_sock.sendto(data, MSG_FASTOPEN,
self.remote_address)
if s < l:
data = data[s:]
self._data_to_write_to_local = [data]
self.update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
self.update_stream(STREAM_DOWN, WAIT_STATUS_READING)
else:
self._data_to_write_to_local = []
self.update_stream(STREAM_UP, WAIT_STATUS_READING)
self.update_stream(STREAM_DOWN, WAIT_STATUS_READING)
self._stage = STAGE_STREAM
except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == errno.EINPROGRESS:
self.update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
self.update_stream(STREAM_DOWN, WAIT_STATUS_READING)
elif eventloop.errno_from_exception(e) == errno.ENOTCONN:
logging.error('fast open not supported on this OS')
self._config['fast_open'] = False
self.destroy()
else:
logging.error(e)
self.destroy()
elif (is_local and self._stage == STAGE_HELLO) or \
(not is_local and self._stage == STAGE_INIT):
try:
@ -259,18 +289,23 @@ class TCPRelayHandler(object):
self._fd_to_handlers[remote_sock.fileno()] = self
remote_sock.setblocking(False)
remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
# TODO support TCP fast open
try:
remote_sock.connect(sa)
except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == errno.EINPROGRESS:
pass
self._loop.add(remote_sock,
eventloop.POLL_ERR | eventloop.POLL_OUT)
self._stage = STAGE_REPLY
self.update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
self.update_stream(STREAM_DOWN, WAIT_STATUS_READING)
if self._is_local and self._config['fast_open']:
# wait for more data to arrive and send them in one SYN
self._stage = STAGE_REPLY
# TODO when there is already data in this packet
else:
try:
remote_sock.connect(sa)
except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == \
errno.EINPROGRESS:
pass
self._loop.add(remote_sock,
eventloop.POLL_ERR | eventloop.POLL_OUT)
self._stage = STAGE_REPLY
self.update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
self.update_stream(STREAM_DOWN, WAIT_STATUS_READING)
return
except Exception:
import traceback

10
tests/fastopen.json Normal file
View File

@ -0,0 +1,10 @@
{
"server":"127.0.0.1",
"server_port":8388,
"local_port":1081,
"password":"barfoo!",
"timeout":300,
"method":"aes-256-cfb",
"local_address":"127.0.0.1",
"fast_open":true
}