123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- /**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- #ifndef TC_CPP_TRANSCEIVER_H
- #define TC_CPP_TRANSCEIVER_H
- #include <list>
- #include "util/tc_network_buffer.h"
- #include "util/tc_clientsocket.h"
- #include "util/tc_epoller.h"
- #include "util/tc_proxy_info.h"
- namespace tars
- {
- class TC_OpenSSL;
- /**
- * @brief 连接异常类
- */
- struct TC_Transceiver_Exception : public TC_Exception
- {
- TC_Transceiver_Exception(const string &sBuffer) : TC_Exception(sBuffer){};
- TC_Transceiver_Exception(const string &sBuffer, int err) : TC_Exception(sBuffer, err){};
- ~TC_Transceiver_Exception() throw(){};
- };
- /**
- * 网络传输基类
- * 使用方式说明:
- * 1 通过暴露注册回调的机制来和使用方交互, 配和epoller类完成网路层的收发都统一, epoller对象需要使用者自己创建和管理, 并传递给TC_Transceiver
- * 2 即可支持客户端的网络, 也可以支持服务端的网络, 但是两者初始化过程是有区别的(initializeClient & initializeServer)
- * 客户端网络: 发送connect时, 会创建句柄, 有oncreate_callback调用到业务层, 通过参数将TC_Epoller::EpollInfo*给业务层, 业务层在回调中根据实际情况完成epoll事件函数的注册
- * 服务端网络: 调用者完成accept, 然后通过bindFd的形式, 将句柄传递进来, bindFd会创建TC_Epoller::EpollInfo*, 返回给调用方
- * 3 无论是客户端网络还是服务端网络, 使用者都不用管理TC_Epoller::EpollInfo*的生命周期, 它会被TC_Transceiver管理, 连接关闭时释放
- * 4 作为客户端, 支持sock4/sock5/http代理(通过oncreate_callback回调, 业务层将代理信息TC_ProxyInfo返回给TC_Transceiver), 也可以通过setBindAddr指定客户端发包时的绑定地址
- * 5 在数据包的管理上, TC_Transceiver内只保存最后一个发送的数据包(可能发送了一半), 因此调用者需要维持发送的数据包队列, 几个回调函数的说明:
- * oncreate_callback: 只存在于客户端模式, 当TC_Transceiver创建完客户端fd时回调oncreate_callback, 使用者在回调事件中监听fd事件, 如果有代理, 则返回代理信息, 否则返回null(注意, 如果有, 则没法都要new一个新的, 因为代理是具备状态信息的)
- * onconnect_callback: 建立连接以后的回调, 注意对于ssl, 是指已经完成ssl握手后的回调
- * onsend_callback: 当TC_Transceiver内的数据都发送完毕, 则回调onsend_callback, 使得调用者可以发送下一个数据
- * onrequest_callback: 该回调表示网络层的连接建立完毕(如果SSL则表示SSL握手完成), 可以发送业务层队列的数据了(通过sendRequest来发送)
- * onopenssl_callback: 需要常见openssl的对象回调, 业务层完成openssl对象的创建(因为涉及证书管理, 因此丢该业务层来创建)
- * onparser_callback: 协议解析的回调
- * onclose_callback: 关闭socket的回调(在close句柄之前回调的)
- * 这种连接中只有最后一个数据包的模式, 保证当连接异常时,在调用者队列中还没有发送的数据能够通过其他连接来发送
- * 6 发送数据使用sendRequest函数, 注意返回值
- * eRetError: 表示发送失败, 当前的数据包没有发送出去, 需要检查连接有有效性, 如果有效: isValid, 则数据需要进入使用自己的队列, onsend_callback回调的时候再发送
- * eRetOk: 发送成功
- * eRetFull: 发送了一半, 系统网络buff满了, 即当前fd不能再发送数据了, 等EPOLLOUT事件来的时候, 业务层再发送
- * eRetNotSend: 数据没有发送(比如连接还没有建立, ssl没有握手, 没有鉴权等), 业务层可以缓存此数据, 等可以发送时onrequest_callback会被回调
- * 7 注册事件, 客户端在oncreate_callback回调中注册相关事件, 服务端在accept句柄并bindFd之后, 来注册事件, 通常需要注册三个事件
- *
- * 8 注意: 主要接口都以异常的形式对外抛出错误, 因此外部调用时注意捕获异常(一般是在注册的事件中)
- * 9 连接直接鉴权逻辑, 即可客户端发业务包前, 会发送一个鉴权包到服务器端, 服务器收到同样解包, 鉴权通过后, 才能继续发送业务包
- * 10 具体客户端使用方式可以参考: CommunicatorEpoll类, 服务端参考: tc_epoll_server
- *
- */
- class TC_Transceiver
- {
- public:
- /**
- * 连接状态
- */
- enum ConnectStatus
- {
- eUnconnected,
- eConnecting,
- eConnected,
- };
- /**
- * sendRequest返回值
- */
- enum ReturnStatus
- {
- eRetError = -1,
- eRetOk =0,
- eRetFull=1,
- eRetNotSend = 2,
- };
- /**
- * 连接关闭原因
- */
- enum CloseReason
- {
- CR_Type = 0, //连接类型错误
- CR_Connect = 1, //连接出错
- CR_ConnectTimeout = 2, //连接超时
- CR_SSL = 3, //ssl错误
- CR_PROXY_SEND = 4, //代理模式下, 发送包错误
- CR_PROXY_RECV = 5, //代理模式下, 接收包错误
- CR_PROTOCOL = 6, //协议解析错误
- CR_SEND = 7, //发送错误
- CR_RECV = 8, //接收错误
- CR_ACTIVE = 9, //主动调用close触发
- CR_DECONSTRUCTOR = 10, //析构
- CR_SSL_HANDSHAKE = 11, //ssl handshake错误
- };
- /**
- * 鉴权状态
- */
- enum AUTH_STATUS
- {
- eAuthInit = -127,
- eAuthSucc = 0,
- };
- enum
- {
- DEFAULT_RECV_BUFFERSIZE = 64*1024 /*缺省数据接收buffer的大小*/
- };
- struct SocketOpt
- {
- int level;
- int optname;
- const void *optval;
- SOCKET_LEN_TYPE optlen;
- };
- //发起连接前, 创建网络句柄后的回调(只对客户端有效)
- using oncreate_callback = std::function<shared_ptr<TC_ProxyInfo>(TC_Transceiver*)>;
- //开启openssl对象的回调
- using onopenssl_callback = std::function<std::shared_ptr<TC_OpenSSL>(TC_Transceiver*)>;
- //关闭句柄的回调
- using onclose_callback = std::function<void(TC_Transceiver*, CloseReason reason, const string &err)> ;
- //建立连接上的回调(只对客户端有效)
- using onconnect_callback = std::function<void(TC_Transceiver*)> ;
- //可以发出业务请求了(对客户端: 连接建立完成, 对SSL: 握手完成, 可以发业务数据的回调)
- using onrequest_callback = std::function<void(TC_Transceiver*)> ;
- //解析协议的回调
- using onparser_callback = std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer&, TC_Transceiver*)> ;
- //完整解析完一个包之后的回调
- using oncompletepackage_callback = std::function<void(TC_Transceiver*)> ;
- //cient侧: 发送鉴权包的回调, 业务层在回调里面组织鉴权包
- using onclientsendauth_callback = std::function<shared_ptr<TC_NetWorkBuffer::Buffer>(TC_Transceiver*)> ;
- //client侧: 收到鉴权包的的回调, 业务层解包(注意返回PACKET_FULL, 表示鉴权成功)
- using onclientverifyauth_callback = std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer &, TC_Transceiver*)> ;
- //server侧: 验证鉴权包并返回验证包的回调
- using onserververifyauth_callback = std::function<pair<TC_NetWorkBuffer::PACKET_TYPE, shared_ptr<TC_NetWorkBuffer::Buffer>>(TC_NetWorkBuffer &, TC_Transceiver*)> ;
- /**
- * 构造函数
- * @param epoller
- * @param ep, 服务端地址
- */
- TC_Transceiver(TC_Epoller* epoller, const TC_Endpoint &ep);
- /**
- *
- *析构函数
- */
- virtual ~TC_Transceiver();
- /**
- *
- * 初始化客户端的连接
- * 句柄是connect时创建的
- */
- void initializeClient(const oncreate_callback &oncreate,
- const onclose_callback &onclose,
- const onconnect_callback &onconnect,
- const onrequest_callback &onrequest,
- const onparser_callback &onparser,
- const onopenssl_callback &onopenssl,
- const oncompletepackage_callback &onfinish = oncompletepackage_callback());
- /**
- *
- * 初始化服务端的连接
- * 句柄是外部accept后, 传递进去的
- */
- void initializeServer(const onclose_callback &onclose,
- const onrequest_callback &onrequest,
- const onparser_callback &onparser,
- const onopenssl_callback &onopenssl,
- const oncompletepackage_callback &onfinish = oncompletepackage_callback());
- /**
- * 设置绑定地址(对客户端有效, 服务端本身就是绑定的)
- */
- void setBindAddr(const char *host);
- /**
- * 设置绑定地址(对客户端有效, 服务端本身就是绑定的)
- * @param bindAddr
- */
- void setBindAddr(const TC_Socket::addr_type &bindAddr);
- /**
- * 获取client地址, 如果是udp, 则表示最后一个包对应的client地址
- * @return
- */
- const TC_Socket::addr_type & getClientAddr() const { return _clientAddr; }
- /**
- * 获取server地址(如果是客户端, 并设置了代理, 则返回代理地址)
- * @return
- */
- const TC_Socket::addr_type & getServerAddr() const { return _serverAddr; }
- /**
- * 设置鉴权回调(不需要鉴权逻辑, 则不需要处理这一步)
- */
- void setClientAuthCallback(const onclientsendauth_callback &onsendauth, const onclientverifyauth_callback &onverify);
- /**
- * 设置鉴权回调(不需要鉴权逻辑, 则不需要处理这一步)
- */
- void setServerAuthCallback(const onserververifyauth_callback &onverify);
- /**
- * 绑定fd上, 一旦绑定, 就创建对fd的事件监听EPOLLIN|EPOLLOUT
- * 并且会维持句柄的持有
- * @param fd
- * @return TC_Epoller::EpollInfo*
- */
- shared_ptr<TC_Epoller::EpollInfo> bindFd(int fd);
- /**
- * 设置udp接收buffer大小(只对udp有效)
- */
- void setUdpRecvBuffer(size_t nSize);
- /**
- * 设置socket opt
- */
- void setSocketOpt(const vector<SocketOpt> &socketOpts) { _socketOpts = socketOpts; }
- /**
- * 是否ssl
- */
- bool isSSL() const ;
- /**
- * 创建连接
- */
- void connect();
- /*
- * 关闭连接
- */
- void close();
- /**
- * send buffer
- * @return
- */
- inline TC_NetWorkBuffer &getSendBuffer() { return _sendBuffer; }
- /**
- * recv buffer
- * @return
- */
- inline TC_NetWorkBuffer &getRecvBuffer() { return _recvBuffer; }
- /**
- * get epoll info
- */
- inline const shared_ptr<TC_Epoller::EpollInfo> &getEpollInfo() { return _epollInfo; }
- /**
- * 发送buffer
- * @param buff, buffer内容
- * @param addr, 发送地址(注意如果udp server, 回包一定要指向客户端的地址, 其他情况可以不传入这个地址)
- */
- virtual ReturnStatus sendRequest(const shared_ptr<TC_NetWorkBuffer::Buffer> &buff, const TC_Socket::addr_type& addr = TC_Socket::addr_type());
- /**
- * 是否鉴权成功
- */
- bool isAuthSucc() const { return _authState == eAuthSucc; }
- /**
- * 鉴权成功
- */
- void enableAuthSucc() { _authState = eAuthSucc; }
- /**
- * 授权状态值
- */
- inline AUTH_STATUS getAuthStatus() const { return _authState; }
- /*
- * 发送链接中已经有数据, 如果连接数据都已经发送完毕, 则会回调onrequest_callback
- * @return int throw TC_Transceiver_Exception
- */
- void doRequest();
- /*
- * 接受网络请求
- * @return throw TC_Transceiver_Exception
- */
- virtual void doResponse() = 0;
- /*
- * 获取文件描述符
- * @return int
- */
- inline int fd() const { return _fd; }
- /*
- * 是否有效
- */
- inline bool isValid() const { return (_fd != -1); }
- /*
- * 获取端口信息(服务器地址)
- */
- inline const TC_Endpoint& getEndpoint() const { return _ep; }
- /**
- * 获取openssl
- */
- inline const std::shared_ptr<TC_OpenSSL>& getOpenSSL() { return _openssl; }
- /*
- * 判断是否已经连接到服务端
- */
- inline bool hasConnected() { return isValid() && (_connStatus == eConnected); }
- /*
- * 判断是否正在连接
- */
- inline bool isConnecting() { return isValid() && (_connStatus == eConnecting); }
- /**
- * 获取连接地址
- * @return
- */
- inline const TC_Endpoint &getConnectEndpoint() const { return _proxyInfo? _proxyInfo->getEndpoint() : _ep; }
- /**
- * 端口描述
- */
- inline const string& getConnectionString() const { return _desc; }
- /**
- * @brief is ipv6 socket or not
- * @return true if is ipv6
- */
- inline bool isConnectIPv6() const { return getConnectEndpoint().isIPv6(); }
- /**
- * 设置连接超时时间(tcp下才有效)
- */
- void setConnTimeout(int connTimeout) { _connTimeout = connTimeout; }
- /**
- * 连接超时的时间(tcp下才有效)
- */
- int getConnTimeout() const { return _connTimeout; };
- /**
- * 连接是否超时(tcp下才有效)
- */
- inline bool isConnTimeout() const { return _isConnTimeout; }
- /**
- *
- * @param connTimeout
- * @return
- */
- inline void setIsConnTimeout(bool connTimeout) { _isConnTimeout = connTimeout; }
- protected:
- /**
- * create socket
- */
- int createSocket(bool udp, bool isLocal = false, bool isIpv6 = false);
- /**
- * connect
- */
- bool doConnect(int, const struct sockaddr *, socklen_t len);
- /**
- * check connect
- */
- void checkConnect();
- /*
- * 设置当前连接态
- */
- void setConnected();
- /*
- * 设置当前连接态
- */
- void onSetConnected();
- /**
- * 检查连接超时
- */
- void checkConnectTimeout();
- /**
- ** 物理连接成功回调
- **/
- void onConnect();
- /**
- ** 发送打通代理请求
- **/
- void connectProxy();
- /**
- * 检查是否代理创建成功
- * @param buff
- * @param length
- * @return <0: 失败, 0: 成功: 1: 需要验证
- */
- int doCheckProxy(const char *buff, size_t length);
- /**
- * 解析域名
- */
- void parseConnectAddress();
- /**
- * 发送鉴权代码
- */
- void doAuthReq();
- /**
- * 验证鉴权信息
- */
- void doAuthCheck(TC_NetWorkBuffer *buff);
- /**
- * 解析协议
- */
- int doProtocolAnalysis(TC_NetWorkBuffer *buff);
- /*
- * 内部关闭连接, udp连接不关闭
- */
- void tcpClose(bool deconstructor, CloseReason reason, const string &err);
- /**
- * udp Close
- */
- void udpClose();
- /*
- * 网络发送接口
- * @param buf
- * @param len
- * @param flag
- * @return int
- */
- virtual int send(const void* buf, uint32_t len, uint32_t flag) = 0;
- /*
- * 网络接收接口
- * @param buf
- * @param len
- * @param flag
- *
- * @return int
- */
- virtual int recv(void* buf, uint32_t len, uint32_t flag) = 0;
- friend class CloseClourse;
- protected:
- /*
- * 服务端的地址
- */
- TC_Socket::addr_type _serverAddr;
- /**
- * 客户端地址
- */
- TC_Socket::addr_type _clientAddr;
- /**
- * bind addr
- */
- TC_Socket::addr_type _bindAddr;
- /*
- * epoller
- */
- TC_Epoller* _epoller = NULL;
- /*
- * 连接的节点信息(服务端地址)
- */
- TC_Endpoint _ep;
- /*
- * 端口描述
- */
- string _desc;
- /*
- * 套接字
- */
- int _fd;
- /**
- * true: server端, false: 客户端
- */
- bool _isServer;
- /**
- * socket选项
- */
- vector<SocketOpt> _socketOpts;
- /*
- * 事件注册信息
- */
- shared_ptr<TC_Epoller::EpollInfo> _epollInfo;
-
- /*
- * 连接状态
- */
- ConnectStatus _connStatus;
- /*
- * openssl
- */
- std::shared_ptr<TC_OpenSSL> _openssl;
- /*
- * 发送buffer
- */
- TC_NetWorkBuffer _sendBuffer;
- /*
- * 接收buffer
- */
- TC_NetWorkBuffer _recvBuffer;
- /**
- * 代理
- */
- shared_ptr<TC_ProxyInfo> _proxyInfo;
- /*
- * 鉴权状态
- */
- AUTH_STATUS _authState = eAuthInit;
- /**
- * 最后一个包的发送地址
- */
- TC_Socket::addr_type _lastAddr;
- /*
- * 接收缓存(udp情况才有效)
- */
- shared_ptr<TC_NetWorkBuffer::Buffer> _pRecvBuffer;
- /*
- * 接收缓存大小(udp情况才有效)
- */
- size_t _nRecvBufferSize = DEFAULT_RECV_BUFFERSIZE;
- /**
- * 是否超时
- */
- bool _isConnTimeout = false;
- /**
- * 连接超时时间
- */
- int _connTimeout = 5000;
- int64_t _connTimerId = 0;
- oncreate_callback _createSocketCallback;
- onopenssl_callback _onOpensslCallback;
- onconnect_callback _onConnectCallback;
- onrequest_callback _onRequestCallback;
- onclose_callback _onCloseCallback;
- onparser_callback _onParserCallback;
- oncompletepackage_callback _onCompletePackageCallback;
- onclientsendauth_callback _onClientSendAuthCallback;
-
- onclientverifyauth_callback _onClientVerifyAuthCallback;
- onserververifyauth_callback _onServerVerifyAuthCallback;
- };
- //////////////////////////////////////////////////////////
- /**
- * TCP 传输实现
- */
- class TC_TCPTransceiver : public TC_Transceiver
- {
- public:
- /**
- * 构造函数
- * @param ep
- * @param fd
- */
- TC_TCPTransceiver(TC_Epoller* epoller, const TC_Endpoint &ep);
- /**
- * TCP 发送实现
- * @param buf
- * @param len
- * @param flag
- * @return int
- */
- virtual int send(const void* buf, uint32_t len, uint32_t flag);
- /**
- * TCP 接收实现
- * @param buf
- * @param len
- * @param flag
- *
- * @return int
- */
- virtual int recv(void* buf, uint32_t len, uint32_t flag);
- /**
- * 处理返回,判断Recv BufferCache是否有完整的包
- * @return throw
- */
- virtual void doResponse();
- };
- //////////////////////////////////////////////////////////
- /**
- * SSL 传输实现
- */
- class TC_SSLTransceiver : public TC_TCPTransceiver
- {
- public:
- /**
- * 构造函数
- * @param ep
- * @param fd
- */
- TC_SSLTransceiver(TC_Epoller* epoller, const TC_Endpoint &ep);
- /**
- * 处理返回
- * @return throw
- */
- virtual void doResponse();
- };
- //////////////////////////////////////////////////////////
- /**
- * UDP 传输实现
- */
- class TC_UDPTransceiver : public TC_Transceiver
- {
- public:
- /**
- * 构造函数
- */
- TC_UDPTransceiver(TC_Epoller* epoller, const TC_Endpoint &ep);
- /**
- * 析构函数
- */
- ~TC_UDPTransceiver();
- /**
- * UDP 发送实现
- * @param buf
- * @param len
- * @param flag
- * @return int
- */
- virtual int send(const void* buf, uint32_t len, uint32_t flag);
- /**
- * UDP 接收实现
- * @param buf
- * @param len
- * @param flag
- * @return int
- */
- virtual int recv(void* buf, uint32_t len, uint32_t flag);
- /**
- * 处理返回,判断Recv BufferCache是否有完整的包
- * @return throw
- */
- virtual void doResponse();
- protected:
- };
- }
- #endif
|