<commit_before>/*
  +----------------------------------------------------------------------+
  | 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       |
  | <EMAIL> so we can mail you a copy immediately.            |
  +----------------------------------------------------------------------+
  | Author: <NAME>  <<EMAIL>>                        |
  +----------------------------------------------------------------------+
*/

#include "php_swoole_cxx.h"
#include "php_swoole_client.h"
#include "swoole_mqtt.h"

#include <string>
#include <queue>
#include <unordered_map>

using swoole::Protocol;
using swoole::network::Client;
using swoole::network::Socket;
using swoole::Socks5Proxy;
using swoole::HttpProxy;
using swoole::String;

#include "ext/standard/basic_functions.h"

struct ClientCallback {
    zend_fcall_info_cache cache_onConnect;
    zend_fcall_info_cache cache_onReceive;
    zend_fcall_info_cache cache_onClose;
    zend_fcall_info_cache cache_onError;
    zend_fcall_info_cache cache_onBufferFull;
    zend_fcall_info_cache cache_onBufferEmpty;
#ifdef SW_USE_OPENSSL
    zend_fcall_info_cache cache_onSSLReady;
#endif
    zval _object;
};

static std::unordered_map<std::string, std::queue<Client *> *> long_connections;

zend_class_entry *swoole_client_ce;
static zend_object_handlers swoole_client_handlers;

static zend_class_entry *swoole_client_exception_ce;
static zend_object_handlers swoole_client_exception_handlers;

struct ClientObject {
    Client *cli;
    zval *zsocket;
    ClientCallback *cb;
    zend_object std;
};

static void php_swoole_client_free(zval *zobject, Client *cli);
static Client *php_swoole_client_new(zval *zobject, char *host, int host_len, int port);

static sw_inline ClientObject *php_swoole_client_fetch_object(zend_object *obj) {
    return (ClientObject *) ((char *) obj - swoole_client_handlers.offset);
}

static sw_inline Client *php_swoole_client_get_cli(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cli;
}

static sw_inline void php_swoole_client_set_cli(zval *zobject, Client *cli) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cli = cli;
}

#ifdef SWOOLE_SOCKETS_SUPPORT
static sw_inline zval *php_swoole_client_get_zsocket(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->zsocket;
}

static sw_inline void php_swoole_client_set_zsocket(zval *zobject, zval *zsocket) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->zsocket = zsocket;
}
#endif

static sw_inline ClientCallback *php_swoole_client_get_cb(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb;
}

static sw_inline void php_swoole_client_set_cb(zval *zobject, ClientCallback *cb) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb = cb;
}

static void php_swoole_client_free_object(zend_object *object) {
    zend_object_std_dtor(object);
}

static zend_object *php_swoole_client_create_object(zend_class_entry *ce) {
    ClientObject *client = (ClientObject *) zend_object_alloc(sizeof(ClientObject), ce);
    zend_object_std_init(&client->std, ce);
    object_properties_init(&client->std, ce);
    client->std.handlers = &swoole_client_handlers;
    return &client->std;
}

SW_EXTERN_C_BEGIN
static PHP_METHOD(swoole_client, __construct);
static PHP_METHOD(swoole_client, __destruct);
static PHP_METHOD(swoole_client, set);
static PHP_METHOD(swoole_client, connect);
static PHP_METHOD(swoole_client, recv);
static PHP_METHOD(swoole_client, send);
static PHP_METHOD(swoole_client, sendfile);
static PHP_METHOD(swoole_client, sendto);
#ifdef SW_USE_OPENSSL
static PHP_METHOD(swoole_client, enableSSL);
static PHP_METHOD(swoole_client, getPeerCert);
static PHP_METHOD(swoole_client, verifyPeerCert);
#endif
static PHP_METHOD(swoole_client, isConnected);
static PHP_METHOD(swoole_client, getsockname);
static PHP_METHOD(swoole_client, getpeername);
static PHP_METHOD(swoole_client, close);
static PHP_METHOD(swoole_client, shutdown);

#ifdef SWOOLE_SOCKETS_SUPPORT
static PHP_METHOD(swoole_client, getSocket);
#endif
SW_EXTERN_C_END

#ifdef PHP_SWOOLE_CLIENT_USE_POLL
static uint32_t client_poll_add(zval *sock_array, uint32_t index, struct pollfd *fds, int maxevents, int event);
static int client_poll_wait(zval *sock_array, struct pollfd *fds, int maxevents, int n_event, int revent);
#else
static int client_select_add(zval *sock_array, fd_set *fds, int *max_fd);
static int client_select_wait(zval *sock_array, fd_set *fds);
#endif

static sw_inline Client *client_get_ptr(zval *zobject) {
    Client *cli = php_swoole_client_get_cli(zobject);
    if (cli && cli->socket) {
        if (cli->active) {
            return cli;
        }
        if (cli->async_connect) {
            cli->async_connect = false;
            int error = -1;
            cli->get_socket()->get_option(SOL_SOCKET, SO_ERROR, &error);
            if (error == 0) {
                cli->active = 1;
                return cli;
            }
            php_swoole_client_free(zobject, cli);
        }
    }
    swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION);
    zend_update_property_long(
        swoole_client_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error());<commit_msg>Fix get_option without checking return value (#4160)<commit_after>/*
  +----------------------------------------------------------------------+
  | 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       |
  | <EMAIL>@<EMAIL> so we can mail you a copy immediately.            |
  +----------------------------------------------------------------------+
  | Author: <NAME>  <<EMAIL>>                        |
  +----------------------------------------------------------------------+
*/

#include "php_swoole_cxx.h"
#include "php_swoole_client.h"
#include "swoole_mqtt.h"

#include <string>
#include <queue>
#include <unordered_map>

using swoole::Protocol;
using swoole::network::Client;
using swoole::network::Socket;
using swoole::Socks5Proxy;
using swoole::HttpProxy;
using swoole::String;

#include "ext/standard/basic_functions.h"

struct ClientCallback {
    zend_fcall_info_cache cache_onConnect;
    zend_fcall_info_cache cache_onReceive;
    zend_fcall_info_cache cache_onClose;
    zend_fcall_info_cache cache_onError;
    zend_fcall_info_cache cache_onBufferFull;
    zend_fcall_info_cache cache_onBufferEmpty;
#ifdef SW_USE_OPENSSL
    zend_fcall_info_cache cache_onSSLReady;
#endif
    zval _object;
};

static std::unordered_map<std::string, std::queue<Client *> *> long_connections;

zend_class_entry *swoole_client_ce;
static zend_object_handlers swoole_client_handlers;

static zend_class_entry *swoole_client_exception_ce;
static zend_object_handlers swoole_client_exception_handlers;

struct ClientObject {
    Client *cli;
    zval *zsocket;
    ClientCallback *cb;
    zend_object std;
};

static void php_swoole_client_free(zval *zobject, Client *cli);
static Client *php_swoole_client_new(zval *zobject, char *host, int host_len, int port);

static sw_inline ClientObject *php_swoole_client_fetch_object(zend_object *obj) {
    return (ClientObject *) ((char *) obj - swoole_client_handlers.offset);
}

static sw_inline Client *php_swoole_client_get_cli(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cli;
}

static sw_inline void php_swoole_client_set_cli(zval *zobject, Client *cli) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cli = cli;
}

#ifdef SWOOLE_SOCKETS_SUPPORT
static sw_inline zval *php_swoole_client_get_zsocket(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->zsocket;
}

static sw_inline void php_swoole_client_set_zsocket(zval *zobject, zval *zsocket) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->zsocket = zsocket;
}
#endif

static sw_inline ClientCallback *php_swoole_client_get_cb(zval *zobject) {
    return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb;
}

static sw_inline void php_swoole_client_set_cb(zval *zobject, ClientCallback *cb) {
    php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb = cb;
}

static void php_swoole_client_free_object(zend_object *object) {
    zend_object_std_dtor(object);
}

static zend_object *php_swoole_client_create_object(zend_class_entry *ce) {
    ClientObject *client = (ClientObject *) zend_object_alloc(sizeof(ClientObject), ce);
    zend_object_std_init(&client->std, ce);
    object_properties_init(&client->std, ce);
    client->std.handlers = &swoole_client_handlers;
    return &client->std;
}

SW_EXTERN_C_BEGIN
static PHP_METHOD(swoole_client, __construct);
static PHP_METHOD(swoole_client, __destruct);
static PHP_METHOD(swoole_client, set);
static PHP_METHOD(swoole_client, connect);
static PHP_METHOD(swoole_client, recv);
static PHP_METHOD(swoole_client, send);
static PHP_METHOD(swoole_client, sendfile);
static PHP_METHOD(swoole_client, sendto);
#ifdef SW_USE_OPENSSL
static PHP_METHOD(swoole_client, enableSSL);
static PHP_METHOD(swoole_client, getPeerCert);
static PHP_METHOD(swoole_client, verifyPeerCert);
#endif
static PHP_METHOD(swoole_client, isConnected);
static PHP_METHOD(swoole_client, getsockname);
static PHP_METHOD(swoole_client, getpeername);
static PHP_METHOD(swoole_client, close);
static PHP_METHOD(swoole_client, shutdown);

#ifdef SWOOLE_SOCKETS_SUPPORT
static PHP_METHOD(swoole_client, getSocket);
#endif
SW_EXTERN_C_END

#ifdef PHP_SWOOLE_CLIENT_USE_POLL
static uint32_t client_poll_add(zval *sock_array, uint32_t index, struct pollfd *fds, int maxevents, int event);
static int client_poll_wait(zval *sock_array, struct pollfd *fds, int maxevents, int n_event, int revent);
#else
static int client_select_add(zval *sock_array, fd_set *fds, int *max_fd);
static int client_select_wait(zval *sock_array, fd_set *fds);
#endif

static sw_inline Client *client_get_ptr(zval *zobject) {
    Client *cli = php_swoole_client_get_cli(zobject);
    if (cli && cli->socket) {
        if (cli->active) {
            return cli;
        }
        if (cli->async_connect) {
            cli->async_connect = false;
            int error = -1;
            if (cli->get_socket()->get_option(SOL_SOCKET, SO_ERROR, &error) == 0) {
                if (error == 0) {
                    cli->active = 1;
                    return cli;
                }
            }
            php_swoole_client_free(zobject, cli);
        }
    }
    swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION);
    zend_update_property_long(
        swoole_client_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error());
{'fraction_non_alphanumeric': 0.1371856699965553, 'fraction_numerical': 0.0030141233207027214, 'mean_word_length': 3.57565011820331, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6853323', 'n_tokens_mistral': 3982, 'n_tokens_neox': 3894, 'n_words': 779}