旅の途中
你知道阿基米德原理吗?

导航

 

为了方便区分,以下分别使用local,server,remote代表ss客户端,ss服务端,以及ss客户端请求访问的远程主机。

在***中,无论对于local还是server,都需要建立两个socket:local_sock和remote_sock
对于local,local_sock用于和进程通讯,server_sock用于和server通讯。
对于server,local_sock用于和local通信,server_sock用于和remote通信。

上一次提到两者的事件处理均使用TCPRelayHandler,先来看一下handle_event函数。

# tcprelay.py

class TCPRelayHandler(object):
    def handle_event(self, sock, event):
        # handle all events in this handler and dispatch them to methods
        if self._stage == STAGE_DESTROYED:
            logging.debug('ignore handle_event: destroyed')
            return
        # order is important
        # remote_socket
        if sock == self._remote_sock:
            if event & eventloop.POLL_ERR:
                self._on_remote_error()
                if self._stage == STAGE_DESTROYED:
                    return
            if event & (eventloop.POLL_IN | eventloop.POLL_HUP):
                self._on_remote_read()
                if self._stage == STAGE_DESTROYED:
                    return
            if event & eventloop.POLL_OUT:
                self._on_remote_write()
        # local_socket
        elif sock == self._local_sock:
            if event & eventloop.POLL_ERR:
                self._on_local_error()
                if self._stage == STAGE_DESTROYED:
                    return
            if event & (eventloop.POLL_IN | eventloop.POLL_HUP):
                self._on_local_read()
                if self._stage == STAGE_DESTROYED:
                    return
            if event & eventloop.POLL_OUT:
                self._on_local_write()
        else:
            logging.warn('unknown socket')

该函数根据传入的socket参数来区别是local_sock,还是remote_sock,将read/write事件的处理分发到各个处理函数。

下面来具体看看这些事件处理函数。

remote_read

# tcprelay.py
class TCPRelayHandler(object):
    def _on_remote_read(self):
        # handle all remote read events
        data = None
        try:
            # 从remote_sock读取数据
            data = self._remote_sock.recv(BUF_SIZE)

        except (OSError, IOError) as e:
            if eventloop.errno_from_exception(e) in \
                    (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
                return
        if not data:
            self.destroy()
            return
        self._update_activity(len(data))
        # local,说明server回反了数据
        if self._is_local:
            # 解密数据
            data = self._encryptor.decrypt(data)
        # server,说明remote响应到达
        else:
            # 加密数据
            data = self._encryptor.encrypt(data)
        try:
            # 写到local_sock,对于server就是写回local,对于local就是写回进程
            self._write_to_sock(data, self._local_sock)
        except Exception as e:
            shell.print_exception(e)
            if self._config['verbose']:
                traceback.print_exc()
            # TODO use logging when debug completed
            self.destroy()

remote_write

# tcprelay.py

class TCPRelayHandler(object):
    def _on_remote_write(self):
        # 进入流传输阶段
        self._stage = STAGE_STREAM
        # 如果有需要写的数据
        if self._data_to_write_to_remote:
            data = b''.join(self._data_to_write_to_remote)
            self._data_to_write_to_remote = []
            self._write_to_sock(data, self._remote_sock)
        else:
            # 否则,更新状态
            self._update_stream(STREAM_UP, WAIT_STATUS_READING)

local_read

# tcprelay.py

class TCPRelayHandler(object):
    def _on_local_read(self):
        # handle all local read events and dispatch them to methods for
        # each stage
        if not self._local_sock:
            return

        is_local = self._is_local
        data = None
        try:
            # 尝试读取数据
            data = self._local_sock.recv(BUF_SIZE)
        except (OSError, IOError) as e:
            if eventloop.errno_from_exception(e) in \
                    (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK):
                return
        if not data:
            self.destroy()
            return
        # 
        self._update_activity(len(data))
        if not is_local:
            # server的local_sock,表明为local发来数据
            # 将数据解密
            data = self._encryptor.decrypt(data)
            if not data:
                return
        # 在stream状态,此时已经建立起协议,传输的是向remote的请求细节,以及remote的响应
        if self._stage == STAGE_STREAM:
            # 客户端
            if self._is_local:
                # 将数据加密
                data = self._encryptor.encrypt(data)
            # 直接转发给remote
            self._write_to_sock(data, self._remote_sock)
            return

        # 处于init状态,处理协议细节
        elif is_local and self._stage == STAGE_INIT:
            # TODO check auth method
            # 给进程发送确认信息
            self._write_to_sock(b'\x05\00', self._local_sock)
            self._stage = STAGE_ADDR
            return

        # 处于connecting状态,处理协议细节
        elif self._stage == STAGE_CONNECTING:
            self._handle_stage_connecting(data)
        # local,等待进程发来请求数据,或者server,初始化状态,等待local发来数据
        elif (is_local and self._stage == STAGE_ADDR) or \
                (not is_local and self._stage == STAGE_INIT):
            # 客户端:接受进程的请求信息,服务器:接受客户端的请求信息
            self._handle_stage_addr(data)

local_write

# tcprelay.py

class TCPRelayHandler(object):
    def _on_local_write(self):
        # 如果有数据可写
        if self._data_to_write_to_local:
            data = b''.join(self._data_to_write_to_local)
            self._data_to_write_to_local = []
            # 写到本地sock
            self._write_to_sock(data, self._local_sock)
        else:
            # 更新流状态
            self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)

posted on 2017-09-24 12:18  CknightX  阅读(42)  评论(0)    收藏  举报