@@ -20,21 +20,14 @@
#include "coroutine.h"
#include "connection.h"
#include "socks5.h"

#include <string>

namespace swoole
{
class Socket
{
public:
enum timer_levels
{
TIMER_LV_NORMAL,
TIMER_LV_MULTI,
TIMER_LV_PACKET,
TIMER_LV_GLOBAL
};

swConnection *socket = nullptr;
enum swSocket_type type;
int sock_domain = 0;
@@ -61,13 +54,11 @@ class Socket
swSSL_option ssl_option = {0};
#endif

Socket(int domain = AF_INET, int type = SOCK_STREAM, int protocol = 0);
Socket(int domain = AF_INET, int type = SOCK_STREAM, int protocol = IPPROTO_IP);
Socket(enum swSocket_type type = SW_SOCK_TCP);
Socket(int _fd, Socket *sock);
Socket(int _fd, Socket *socket);
Socket(int _fd, enum swSocket_type _type);
~Socket();
void set_timer(timer_levels _timer_level = TIMER_LV_NORMAL, double _timeout = 0);
void del_timer(timer_levels _timer_level = TIMER_LV_NORMAL);
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);
@@ -76,14 +67,14 @@ class Socket
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);
ssize_t read(void *__buf, size_t __n);
ssize_t write(const void *__buf, size_t __n);
ssize_t send(const void *__buf, size_t __n);
ssize_t sendmsg(const struct msghdr *msg, int flags);
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();
ssize_t recv_packet(double timeout = 0);
Socket* accept();
bool bind(std::string address, int port = 0);
bool listen(int backlog = 0);
@@ -117,25 +108,28 @@ class Socket
return socket ? socket->fd : -1;
}

inline long has_bound()
inline bool has_bound()
{
return coroutine ? coroutine->get_cid() : 0;
return read_co || write_co;
}

inline void check_bind()
inline Coroutine* get_bound_co(enum swEvent_type event)
{
long cid = has_bound();
if (unlikely(cid))
if (likely(event & SW_EVENT_READ))
{
return read_co;
}
if (event & SW_EVENT_WRITE)
{
swoole_error_log(
SW_LOG_ERROR, SW_ERROR_CO_HAS_BEEN_BOUND,
"Socket#%d has already been bound to another coroutine#%ld, "
"reading or writing of the same socket in multiple coroutines at the same time is not allowed.\n",
socket->fd, cid
);
set_err(SW_ERROR_CO_HAS_BEEN_BOUND);
exit(255);
return write_co;
}
return nullptr;
}

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

inline void set_err(int e)
@@ -153,7 +147,7 @@ class Socket
inline void set_err(enum swErrorCode e)
{
errCode = errno = e;
errMsg = swstrerror(e);
errMsg = swoole_strerror(e);
}

inline double get_timeout()
@@ -208,16 +202,21 @@ class Socket
}

protected:
Coroutine* coroutine = nullptr;
swReactor *reactor = nullptr;
Coroutine *read_co = nullptr;
Coroutine *write_co = nullptr;
#ifdef SW_USE_OPENSSL
enum swEvent_type want_event = SW_EVENT_NULL;
#endif

std::string host;
int port = 0;
std::string bind_address;
int bind_port = 0;
timer_levels timer_level = TIMER_LV_NORMAL;
swTimer_node *timer = nullptr;

double timeout = -1;
swTimer_node *read_timer = nullptr;
swTimer_node *write_timer = nullptr;

bool shutdown_read = false;
bool shutdown_write = false;
@@ -226,30 +225,9 @@ class Socket
#endif

static void timer_callback(swTimer *timer, swTimer_node *tnode);
static int event_callback(swReactor *reactor, swEvent *event);

bool socks5_handshake();
bool http_proxy_handshake();

inline void yield()
{
Coroutine *co = Coroutine::get_current();
if (unlikely(!co))
{
swError("Socket::yield() must be called in the coroutine.");
}
set_err(0);
set_timer();
coroutine = co;
co->yield();
coroutine = nullptr;
del_timer();
}

inline void resume()
{
coroutine->resume();
}
static int readable_event_callback(swReactor *reactor, swEvent *event);
static int writable_event_callback(swReactor *reactor, swEvent *event);
static int error_event_callback(swReactor *reactor, swEvent *event);

inline void init_members()
{
@@ -258,130 +236,82 @@ class Socket
protocol.package_body_offset = 0;
protocol.package_max_length = SW_BUFFER_INPUT_SIZE;
}

inline void init_sock_type(enum swSocket_type _type)
{
type = _type;
switch (type)
{
case SW_SOCK_TCP6:
sock_domain = AF_INET6;
sock_type = SOCK_STREAM;
break;
case SW_SOCK_UNIX_STREAM:
sock_domain = AF_UNIX;
sock_type = SOCK_STREAM;
break;
case SW_SOCK_UDP:
sock_domain = AF_INET;
sock_type = SOCK_DGRAM;
break;
case SW_SOCK_UDP6:
sock_domain = AF_INET6;
sock_type = SOCK_DGRAM;
break;
case SW_SOCK_UNIX_DGRAM:
sock_domain = AF_UNIX;
sock_type = SOCK_DGRAM;
break;
case SW_SOCK_TCP:
default:
sock_domain = AF_INET;
sock_type = SOCK_STREAM;
break;
}
}

inline void init_sock_type(enum swSocket_type _type);
inline void init_sock();

inline void init_sock(int _fd);

inline bool is_available()
bool add_event(const enum swEvent_type event);
bool wait_event(const enum swEvent_type event, const void **__buf = nullptr, size_t __n = 0);

inline bool is_available(enum swEvent_type event)
{
check_bind();
if (event != SW_EVENT_NULL)
{
long cid = get_bound_cid(event);
if (unlikely(cid))
{
swoole_error_log(
SW_LOG_ERROR, SW_ERROR_CO_HAS_BEEN_BOUND,
"Socket#%d has already been bound to another coroutine#%ld, "
"%s of the same socket in multiple coroutines at the same time is not allowed.\n",
socket->fd, cid, (event == SW_EVENT_READ ? "reading" : (event == SW_EVENT_WRITE ? "writing" : "reading or writing"))
);
exit(255);
}
}
if (unlikely(socket->closed))
{
swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SOCKET_CLOSED, "Socket#%d belongs to coroutine#%ld has already been closed.", socket->fd, Coroutine::get_current_cid());
set_err(ECONNRESET);
return false;
}
return true;
}

inline bool should_be_break()
{
switch (errCode)
{
case ETIMEDOUT:
case ECANCELED:
return true;
default:
return false;
}
}
// TODO: move to client.cc
bool socks5_handshake();
bool http_proxy_handshake();

inline bool wait_event(int event)
class timer
{
if (reactor->add(reactor, socket->fd, SW_FD_CORO_SOCKET | event) < 0)
public:
timer(swTimer_node **timer_pp, double timeout, void *data, swTimerCallback callback) :
timer_pp(timer_pp), timeout(timeout), data(data), callback(callback)
{
set_err(errno);
return false;
}
return true;
}

inline bool wait_readable()
{
#ifdef SW_USE_OPENSSL
if (socket->ssl && socket->ssl_want_write)
bool operator ()()
{
if (unlikely(!is_available() || !wait_event(SW_EVENT_WRITE)))
if (timeout != 0 && !*timer_pp)
{
return false;
enabled = true;
if (timeout > 0)
{
*timer_pp = swTimer_add(&SwooleG.timer, (long) (timeout * 1000), 0, data, callback);
return *timer_pp != nullptr;
}
else // if (timeout < 0)
{
*timer_pp = (swTimer_node *) -1;
}
}
return true;
}
else
#endif
if (unlikely(!wait_event(SW_EVENT_READ)))
{
return false;
}
yield();
return !should_be_break();
}

inline void copy_to_write_buffer(const void **__buf, size_t __n)
{
if (*__buf != get_write_buffer()->str)
~timer()
{
swString_clear(write_buffer);
swString_append_ptr(write_buffer, (const char *) *__buf, __n);
*__buf = write_buffer->str;
}
}

inline bool wait_writeable(const void **__buf = nullptr, size_t __n = 0)
{
#ifdef SW_USE_OPENSSL
if (socket->ssl && socket->ssl_want_read)
{
if (unlikely(!is_available() || !wait_event(SW_EVENT_READ)))
if (enabled && *timer_pp)
{
return false;
if (*timer_pp != (swTimer_node *) -1)
{
swTimer_del(&SwooleG.timer, *timer_pp);
}
*timer_pp = nullptr;
}
}
else
#endif
if (unlikely(!wait_event(SW_EVENT_WRITE)))
{
return false;
}
if (__n > 0)
{
copy_to_write_buffer(__buf, __n);
}
yield();
return !should_be_break();
}
private:
bool enabled = false;
swTimer_node** timer_pp;
double timeout;
void *data;
swTimerCallback callback;
};
};
};
@@ -43,24 +43,23 @@ enum swSocks5_method
typedef struct _swSocks5
{
char *host;
int l_host;
int port;

uint8_t state;
uint8_t version;
uint8_t method;
uint8_t dns_tunnel;

char *password;
char *username;
char *password;
uint16_t l_username;
uint16_t l_password;

char *target_host;
int target_port;
int l_target_host;
int l_username;
int l_password;
uint16_t l_target_host;

char buf[600];

} swSocks5;

static sw_inline void swSocks5_pack(char *buf, int method)
@@ -87,10 +87,10 @@ int clock_gettime(clock_id_t which_clock, struct timespec *t);

#define SWOOLE_MAJOR_VERSION 4
#define SWOOLE_MINOR_VERSION 2
#define SWOOLE_RELEASE_VERSION 12
#define SWOOLE_RELEASE_VERSION 13
#define SWOOLE_EXTRA_VERSION ""
#define SWOOLE_VERSION "4.2.12"
#define SWOOLE_VERSION_ID 40212
#define SWOOLE_VERSION "4.2.13"
#define SWOOLE_VERSION_ID 40213
#define SWOOLE_BUG_REPORT \
"A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n"\
"The Swoole developers probably don't know about it,\n"\
@@ -148,7 +148,7 @@ typedef unsigned long ulong_t;
#endif

#define SW_START_LINE "-------------------------START----------------------------"
#define SW_END_LINE "-------------------------END------------------------------"
#define SW_END_LINE "--------------------------END-----------------------------"
#define SW_ECHO_RED "\e[31m%s\e[0m"
#define SW_ECHO_GREEN "\e[32m%s\e[0m"
#define SW_ECHO_YELLOW "\e[33m%s\e[0m"
@@ -180,25 +180,30 @@ typedef unsigned long ulong_t;
#include "array.h"
#include "error.h"

#define SW_MAX_UINT UINT_MAX
#define SW_MAX_INT INT_MAX
#define SW_MAX(A, B) ((A) > (B) ? (A) : (B))
#define SW_MIN(A, B) ((A) < (B) ? (A) : (B))

#ifndef MAX
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MAX(A, B) SW_MAX(A, B)
#endif
#ifndef MIN
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define MIN(A, B) SW_MIN(A, B)
#endif

#ifdef SW_DEBUG
#define SW_ASSERT(e) assert(e)
#else
#define SW_ASSERT(e)
#endif
#define SW_STRS(s) s, sizeof(s)
#define SW_STRL(s) s, sizeof(s)-1
#define SW_START_SLEEP usleep(100000) //sleep 1s,wait fork and pthread_create

/*-----------------------------------Memory------------------------------------*/

#define SW_MEM_ALIGNED_SIZE(size) \
SW_MM_ALIGNED_SIZE_EX(size, 8)
#define SW_MEM_ALIGNED_SIZE_EX(size, alignment) \
(((size) + ((alignment) - 1LL)) & ~((alignment) - 1LL))

#ifdef SW_USE_EMALLOC
#define sw_malloc emalloc
#define sw_free efree
@@ -219,8 +224,21 @@ typedef unsigned long ulong_t;
#endif
#endif

#define SW_MEM_ALIGNED_SIZE(size) SW_MM_ALIGNED_SIZE_EX(size, 8)
#define SW_MEM_ALIGNED_SIZE_EX(size, alignment) (((size) + ((alignment) - 1LL)) & ~((alignment) - 1LL))
/*----------------------------------String-------------------------------------*/

#define SW_STRS(s) s, sizeof(s)
#define SW_STRL(s) s, sizeof(s)-1

#if defined(SW_USE_JEMALLOC) || defined(SW_USE_TCMALLOC)
#define sw_strdup swoole_strdup
#define sw_strndup swoole_strndup
#else
#define sw_strdup strdup
#define sw_strndup strndup
#endif

/** always return less than size */
size_t sw_snprintf(char *buf, size_t s, const char *format, ...);

static sw_inline char* swoole_strdup(const char *s)
{
@@ -238,17 +256,8 @@ static sw_inline char* swoole_strndup(const char *s, size_t n)
return p;
}

#if defined(SW_USE_JEMALLOC) || defined(SW_USE_TCMALLOC)
#define sw_strdup swoole_strdup
#define sw_strndup swoole_strndup
#else
#define sw_strdup strdup
#define sw_strndup strndup
#endif
/*--------------------------------Constants------------------------------------*/

#define METHOD_DEF(class,name,...) class##_##name(class *object, ##__VA_ARGS__)
#define METHOD(class,name,...) class##_##name(object, ##__VA_ARGS__)
//-------------------------------------------------------------------------------
#define SW_OK 0
#define SW_ERR -1
#define SW_AGAIN -2
@@ -297,11 +306,13 @@ enum swBool_type

enum swEvent_type
{
SW_EVENT_DEAULT = 256,
SW_EVENT_READ = 1u << 9,
SW_EVENT_WRITE = 1u << 10,
SW_EVENT_ERROR = 1u << 11,
SW_EVENT_ONCE = 1u << 12,
SW_EVENT_NULL = 0,
SW_EVENT_DEAULT = 1u << 8,
SW_EVENT_READ = 1u << 9,
SW_EVENT_WRITE = 1u << 10,
SW_EVENT_RDWR = SW_EVENT_READ | SW_EVENT_WRITE,
SW_EVENT_ERROR = 1u << 11,
SW_EVENT_ONCE = 1u << 12,
};

enum swPipe_type
@@ -385,11 +396,11 @@ enum swWorker_status
SwooleGS->lock_2.unlock(&SwooleGS->lock_2);\
exit(1)

#define swSysError(str,...) SwooleGS->lock_2.lock(&SwooleGS->lock_2);\
#define swSysError(str,...) do{SwooleGS->lock_2.lock(&SwooleGS->lock_2);\
snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s(:%d): " str " Error: %s[%d].",__func__,__LINE__,##__VA_ARGS__,strerror(errno),errno);\
swLog_put(SW_LOG_ERROR, sw_error);\
SwooleG.error=errno;\
SwooleGS->lock_2.unlock(&SwooleGS->lock_2)
SwooleGS->lock_2.unlock(&SwooleGS->lock_2);}while(0)

#define swoole_error_log(level, __errno, str, ...) do{SwooleG.error=__errno;\
if (level >= SwooleG.log_level){\
@@ -643,7 +654,7 @@ typedef struct _swConnection
/**
* memory buffer size;
*/
int buffer_size;
uint32_t buffer_size;

/**
* upgarde websocket
@@ -722,7 +733,7 @@ static sw_inline size_t swoole_size_align(size_t size, int pagesize)
#define SW_STRINGCVL(s) s->str + s->offset, s->length - s->offset

swString *swString_new(size_t size);
swString *swString_dup(const char *src_str, int length);
swString *swString_dup(const char *src_str, size_t length);
swString *swString_dup2(swString *src);

void swString_print(swString *str);
@@ -756,6 +767,14 @@ static sw_inline int swString_extend_align(swString *str, size_t _new_size)
}

//------------------------------Base--------------------------------
enum _swEventData_flag
{
SW_EVENT_DATA_NORMAL,
SW_EVENT_DATA_PTR = 1u << 1,
SW_EVENT_DATA_CHUNK = 1u << 2,
SW_EVENT_DATA_END = 1u << 3,
};

typedef struct _swDataHead
{
int fd;
@@ -780,21 +799,12 @@ typedef struct _swEvent
typedef struct _swEventData
{
swDataHead info;
char data[SW_BUFFER_SIZE];
char data[SW_IPC_BUFFER_SIZE];
} swEventData;

typedef struct _swDgramPacket
{
union
{
struct in6_addr v6;
struct in_addr v4;
struct
{
uint16_t path_length;
} un;
} addr;
uint16_t port;
swSocketAddress info;
uint32_t length;
char data[0];
} swDgramPacket;
@@ -1399,30 +1409,14 @@ int swSocket_recv_blocking(int fd, void *__data, size_t __len, int flags);
static sw_inline int swWaitpid(pid_t __pid, int *__stat_loc, int __options)
{
int ret;
do
{
ret = waitpid(__pid, __stat_loc, __options);
if (ret < 0 && errno == EINTR)
{
continue;
}
break;
} while(1);
do { ret = waitpid(__pid, __stat_loc, __options); } while (ret < 0 && errno == EINTR);
return ret;
}

static sw_inline int swKill(pid_t __pid, int __sig)
{
int ret;
do
{
ret = kill(__pid, __sig);
if (ret < 0 && errno == EINTR)
{
continue;
}
break;
} while (1);
do { ret = kill(__pid, __sig); } while (ret < 0 && errno == EINTR);
return ret;
}
#endif
@@ -1639,6 +1633,9 @@ struct _swProcessPool
uint8_t dispatch_mode;
uint8_t ipc_mode;
uint8_t started;
uint32_t reload_worker_i;
uint32_t max_wait_time;
swWorker *reload_workers;

/**
* process type
@@ -1775,11 +1772,7 @@ static sw_inline swConnection* swReactor_get(swReactor *reactor, int fd)
return &reactor->socket_list[fd];
}
swConnection *socket = (swConnection*) swArray_alloc(reactor->socket_array, fd);
if (socket == NULL)
{
return NULL;
}
if (!socket->active)
if (socket && !socket->active)
{
socket->fd = fd;
}
@@ -1900,6 +1893,26 @@ int swProcessPool_add_worker(swProcessPool *pool, swWorker *worker);
int swProcessPool_del_worker(swProcessPool *pool, swWorker *worker);
int swProcessPool_get_max_request(swProcessPool *pool);

static sw_inline void swProcessPool_set_start_id(swProcessPool *pool, int start_id)
{
int i;
pool->start_id = start_id;
for (i = 0; i < pool->worker_num; i++)
{
pool->workers[i].id = pool->start_id + i;
}
}

static sw_inline void swProcessPool_set_type(swProcessPool *pool, int type)
{
int i;
pool->type = type;
for (i = 0; i < pool->worker_num; i++)
{
pool->workers[i].type = type;
}
}

static sw_inline swWorker* swProcessPool_get_worker(swProcessPool *pool, int worker_id)
{
return &(pool->workers[worker_id - pool->start_id]);
@@ -2021,6 +2034,13 @@ typedef struct _swTimer swTimer;
typedef struct _swTimer_node swTimer_node;

typedef void (*swTimerCallback)(swTimer *, swTimer_node *);
typedef void (*swTimerDtor)(swTimer_node *);

enum swTimer_type
{
SW_TIMER_TYPE_KERNEL,
SW_TIMER_TYPE_PHP,
};

struct _swTimer_node
{
@@ -2031,19 +2051,10 @@ struct _swTimer_node
int64_t interval;
uint64_t round;
long id;
int type; //0 normal node 1 node for client_coro
enum swTimer_type type;
uint8_t remove;
};

enum swTimer_type
{
SW_TIMER_TYPE_KERNEL,
SW_TIMER_TYPE_PHP,
SW_TIMER_TYPE_CORO_READ,
SW_TIMER_TYPE_CORO_WRITE,
SW_TIMER_TYPE_CORO_ALL,
};

struct _swTimer
{
/*--------------signal timer--------------*/
@@ -2063,7 +2074,8 @@ struct _swTimer
};

swTimer_node* swTimer_add(swTimer *timer, long _msec, int interval, void *data, swTimerCallback callback);
int swTimer_del(swTimer *timer, swTimer_node *node);
enum swBool_type swTimer_del(swTimer *timer, swTimer_node *node);
enum swBool_type swTimer_del_ex(swTimer *timer, swTimer_node *node, swTimerDtor dtor);
void swTimer_free(swTimer *timer);
int swTimer_select(swTimer *timer);
int swTimer_now(struct timeval *time);
@@ -2123,8 +2135,6 @@ typedef struct
uint16_t id;
uint8_t type;
uint8_t update_time;
uint8_t factory_lock_target;
int16_t factory_target_worker;
swString *buffer_stack;
swReactor *reactor;
} swThreadG;
@@ -81,7 +81,7 @@ typedef struct
uint8_t type;
uint32_t size;
swString* name;
uint16_t index;
size_t index;
} swTableColumn;

enum swoole_table_type
@@ -1,18 +1,18 @@
/*
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/

#pragma once

@@ -21,7 +21,7 @@

namespace swoole
{
void event_init(void);
void event_wait(void);
void check_reactor(void);
void event_init(void);
void event_wait(void);
void check_reactor(void);
}
@@ -1,3 +1,19 @@
/*
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/

#pragma once

#include "client.h"
@@ -1,18 +1,18 @@
/*
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/

#pragma once

@@ -27,146 +27,148 @@ using namespace std;

namespace swoole
{
class ClientInfo
{
public:
char address[256];
int port;
int server_socket;
};
class ClientInfo
{
public:
char address[256];
int port;
int server_socket;
};

extern swString *_callback_buffer;
extern swString *_callback_buffer;

struct DataBuffer
{
size_t length;
void *buffer;
struct DataBuffer
{
size_t length;
void *buffer;

DataBuffer()
{
length = 0;
buffer = NULL;
}
DataBuffer()
{
length = 0;
buffer = NULL;
}

DataBuffer(const char *str)
{
copy((void *) str, strlen(str));
}
DataBuffer(const char *str)
{
copy((void *) str, strlen(str));
}

DataBuffer(string &str)
{
copy((void *) str.c_str(), str.length());
}
DataBuffer(string &str)
{
copy((void *) str.c_str(), str.length());
}

DataBuffer(const char *str, size_t length)
{
copy((void *) str, length);
}
DataBuffer(const char *str, size_t length)
{
copy((void *) str, length);
}

void copy(void *_data, size_t _length)
{
alloc(_length);
memcpy(buffer, _data, _length);
}
void copy(void *_data, size_t _length)
{
alloc(_length);
memcpy(buffer, _data, _length);
}

void *alloc(size_t _size)
void *alloc(size_t _size)
{
if (_size >= _callback_buffer->size)
{
if (_size >= _callback_buffer->size)
size_t new_size = _callback_buffer->size * 2;
while (new_size < _size + 1)
{
size_t new_size = _callback_buffer->size * 2;
while (new_size < _size + 1)
{
new_size *= 2;
}
if (swString_extend(_callback_buffer, new_size) < 0)
{
abort();
}
new_size *= 2;
}
if (swString_extend(_callback_buffer, new_size) < 0)
{
abort();
}
length = _size;
buffer = _callback_buffer->str;
((char *) buffer)[_size] = '\0';
return buffer;
}
};
length = _size;
buffer = _callback_buffer->str;
((char *) buffer)[_size] = '\0';
return buffer;
}
};

enum
{
EVENT_onStart = 1u << 1,
EVENT_onShutdown = 1u << 2,
EVENT_onWorkerStart = 1u << 3,
EVENT_onWorkerStop = 1u << 4,
EVENT_onConnect = 1u << 5,
EVENT_onReceive = 1u << 6,
EVENT_onPacket = 1u << 7,
EVENT_onClose = 1u << 8,
EVENT_onTask = 1u << 9,
EVENT_onFinish = 1u << 10,
EVENT_onPipeMessage = 1u << 11,
};

class Server
{
public:
Server(string _host, int _port, int _mode = SW_MODE_PROCESS, int _type = SW_SOCK_TCP);

enum
virtual ~Server()
{
EVENT_onStart = 1u << 1,
EVENT_onShutdown = 1u << 2,
EVENT_onWorkerStart = 1u << 3,
EVENT_onWorkerStop = 1u << 4,
EVENT_onConnect = 1u << 5,
EVENT_onReceive = 1u << 6,
EVENT_onPacket = 1u << 7,
EVENT_onClose = 1u << 8,
EVENT_onTask = 1u << 9,
EVENT_onFinish = 1u << 10,
EVENT_onPipeMessage = 1u << 11,
};

class Server
}
;

bool start(void);
void setEvents(int _events);
bool listen(string host, int port, int type);
bool send(int fd, const char *data, int length);
bool send(int fd, const DataBuffer &data);
bool sendfile(int fd, string &file, off_t offset = 0, size_t length = 0);
bool sendMessage(int worker_id, DataBuffer &data);
bool sendwait(int fd, const DataBuffer &data);
bool close(int fd, bool reset = false);
bool sendto(const string &ip, int port, const DataBuffer &data, int server_socket = -1);
int task(DataBuffer &data, int dst_worker_id = -1);
bool finish(DataBuffer &data);
DataBuffer taskwait(const DataBuffer &data, double timeout = SW_TASKWAIT_TIMEOUT, int dst_worker_id = -1);
map<int, DataBuffer> taskWaitMulti(const vector<DataBuffer> &data, double timeout = SW_TASKWAIT_TIMEOUT);

int getLastError()
{
public:
Server(string _host, int _port, int _mode = SW_MODE_PROCESS, int _type = SW_SOCK_TCP);

virtual ~Server()
{};

bool start(void);
void setEvents(int _events);
bool listen(string host, int port, int type);
bool send(int fd, const char *data, int length);
bool send(int fd, const DataBuffer &data);
bool sendfile(int fd, string &file, off_t offset = 0, size_t length = 0);
bool sendMessage(int worker_id, DataBuffer &data);
bool sendwait(int fd, const DataBuffer &data);
bool close(int fd, bool reset = false);
bool sendto(const string &ip, int port, const DataBuffer &data, int server_socket = -1);
int task(DataBuffer &data, int dst_worker_id = -1);
bool finish(DataBuffer &data);
DataBuffer taskwait(const DataBuffer &data, double timeout = SW_TASKWAIT_TIMEOUT, int dst_worker_id = -1);
map<int, DataBuffer> taskWaitMulti(const vector<DataBuffer> &data, double timeout = SW_TASKWAIT_TIMEOUT);

int getLastError()
{
return SwooleG.error;
}

virtual void onStart() = 0;
virtual void onShutdown() = 0;
virtual void onWorkerStart(int worker_id) = 0;
virtual void onWorkerStop(int worker_id) = 0;
virtual void onReceive(int fd, const DataBuffer &data) = 0;
virtual void onConnect(int fd) = 0;
virtual void onClose(int fd) = 0;
virtual void onPacket(const DataBuffer &, ClientInfo &) = 0;
virtual void onPipeMessage(int src_worker_id, const DataBuffer &) = 0;
virtual void onTask(int, int, const DataBuffer &) = 0;
virtual void onFinish(int, const DataBuffer &) = 0;

public:
static int _onReceive(swServer *serv, swEventData *req);
static void _onConnect(swServer *serv, swDataHead *info);
static void _onClose(swServer *serv, swDataHead *info);
static int _onPacket(swServer *serv, swEventData *req);
static void _onPipeMessage(swServer *serv, swEventData *req);
static void _onStart(swServer *serv);
static void _onShutdown(swServer *serv);
static void _onWorkerStart(swServer *serv, int worker_id);
static void _onWorkerStop(swServer *serv, int worker_id);
static int _onTask(swServer *serv, swEventData *task);
static int _onFinish(swServer *serv, swEventData *task);

private:
int check_task_param(int dst_worker_id);

protected:
swServer serv;
vector<swListenPort *> ports;
string host;
int port;
int mode;
int events;
};
return SwooleG.error;
}

virtual void onStart() = 0;
virtual void onShutdown() = 0;
virtual void onWorkerStart(int worker_id) = 0;
virtual void onWorkerStop(int worker_id) = 0;
virtual void onReceive(int fd, const DataBuffer &data) = 0;
virtual void onConnect(int fd) = 0;
virtual void onClose(int fd) = 0;
virtual void onPacket(const DataBuffer &, ClientInfo &) = 0;
virtual void onPipeMessage(int src_worker_id, const DataBuffer &) = 0;
virtual void onTask(int, int, const DataBuffer &) = 0;
virtual void onFinish(int, const DataBuffer &) = 0;

public:
static int _onReceive(swServer *serv, swEventData *req);
static void _onConnect(swServer *serv, swDataHead *info);
static void _onClose(swServer *serv, swDataHead *info);
static int _onPacket(swServer *serv, swEventData *req);
static void _onPipeMessage(swServer *serv, swEventData *req);
static void _onStart(swServer *serv);
static void _onShutdown(swServer *serv);
static void _onWorkerStart(swServer *serv, int worker_id);
static void _onWorkerStop(swServer *serv, int worker_id);
static int _onTask(swServer *serv, swEventData *task);
static int _onFinish(swServer *serv, swEventData *task);

private:
int check_task_param(int dst_worker_id);

protected:
swServer serv;
vector<swListenPort *> ports;
string host;
int port;
int mode;
int events;
};
}
@@ -1,18 +1,18 @@
/*
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
+----------------------------------------------------------------------+
| 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 <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/

#pragma once

@@ -23,53 +23,53 @@ using namespace std;

namespace swoole
{
class Timer
class Timer
{
public:
Timer(long ms, bool interval);
Timer(long ms);
~Timer()
{
public:
Timer(long ms, bool interval);
Timer(long ms);
~Timer()
{
clear();
}
clear();
}

swTimer_node *getNode()
{
return m_tnode;
}
swTimer_node *getNode()
{
return m_tnode;
}

void setNode(swTimer_node *tnode)
{
m_tnode = tnode;
}
void setNode(swTimer_node *tnode)
{
m_tnode = tnode;
}

void clear()
void clear()
{
if (m_tnode)
{
if (m_tnode)
{
Timer::del(m_tnode);
m_tnode = NULL;
id = -1;
interval = 0;
}
Timer::del(m_tnode);
m_tnode = NULL;
id = -1;
interval = 0;
}
}

static void _onAfter(swTimer *timer, swTimer_node *tnode);
static void _onTick(swTimer *timer, swTimer_node *tnode);
static void init(int msec);
static void _onAfter(swTimer *timer, swTimer_node *tnode);
static void _onTick(swTimer *timer, swTimer_node *tnode);
static void init(int msec);

static bool clear(long id);
static bool exists(long id);
static bool clear(long id);
static bool exists(long id);

protected:
virtual void callback(void) = 0;
static long add(int ms, Timer *object, bool tick);
static bool del(swTimer_node *tnode);
protected:
virtual void callback(void) = 0;
static long add(int ms, Timer *object, bool tick);
static bool del(swTimer_node *tnode);

bool interval;
long id;
swTimer_node* m_tnode;
};
bool interval;
long id;
swTimer_node* m_tnode;
};

static map<long, Timer *> timer_map;
static map<long, Timer *> timer_map;
}

Large diffs are not rendered by default.

@@ -94,6 +94,7 @@ extern zend_module_entry swoole_module_entry;
#endif

#define SWOOLE_PROPERTY_MAX 32
#define SWOOLE_OBJECT_DEFAULT 65536
#define SWOOLE_OBJECT_MAX 10000000

typedef struct
@@ -139,7 +140,7 @@ extern swoole_object_array swoole_objects;
#endif
#endif

#if PHP_VERSION_ID < 70300
#if PHP_VERSION_ID < 70400
#define SW_USE_FAST_SERIALIZE 1
#endif

@@ -249,7 +250,7 @@ typedef struct
{
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
} php_defer_fci;
} php_swoole_fci;
//---------------------------------------------------------
#define php_swoole_socktype(type) (type & (~SW_FLAG_SYNC) & (~SW_FLAG_ASYNC) & (~SW_FLAG_KEEP) & (~SW_SOCK_SSL))

@@ -328,6 +329,11 @@ PHP_FUNCTION(swoole_timer_clear);
//---------------------------------------------------------
// error
//---------------------------------------------------------
#define SW_STRERROR_SYSTEM 0
#define SW_STRERROR_GAI 1
#define SW_STRERROR_DNS 2
#define SW_STRERROR_SWOOLE 9

PHP_FUNCTION(swoole_strerror);
PHP_FUNCTION(swoole_errno);
PHP_FUNCTION(swoole_last_error);
@@ -400,7 +406,6 @@ void php_swoole_register_shutdown_function_prepend(char *function);
void php_swoole_event_init();
void php_swoole_event_wait();
void php_swoole_event_exit();
long php_swoole_add_timer(long ms, zval *callback, zval *param, int persistent);
void php_swoole_clear_all_timer();
void php_swoole_register_callback(swServer *serv);
void php_swoole_trace_check(void *arg);
@@ -480,10 +485,8 @@ void php_swoole_onClose(swServer *, swDataHead *);
void php_swoole_onBufferFull(swServer *, swDataHead *);
void php_swoole_onBufferEmpty(swServer *, swDataHead *);
ssize_t php_swoole_length_func(swProtocol *protocol, swConnection *conn, char *data, uint32_t length);
int php_swoole_dispatch_func(swServer *serv, swConnection *conn, swEventData *data);
int php_swoole_dispatch_func(swServer *serv, swConnection *conn, swSendData *data);
int php_swoole_client_onPackage(swConnection *conn, char *data, uint32_t length);
void php_swoole_onTimeout(swTimer *timer, swTimer_node *tnode);
void php_swoole_onInterval(swTimer *timer, swTimer_node *tnode);
zend_bool php_swoole_signal_isset_handler(int signo);
void php_swoole_event_onDefer(void *_cb);

@@ -614,7 +617,7 @@ static sw_inline void _sw_zend_bailout(const char *filename, uint32_t lineno)

#ifndef GC_IS_RECURSIVE
#define GC_IS_RECURSIVE(p) \
(ZEND_HASH_GET_APPLY_COUNT(p) > 1)
(ZEND_HASH_GET_APPLY_COUNT(p) >= 1)
#define GC_PROTECT_RECURSION(p) \
ZEND_HASH_INC_APPLY_COUNT(p)
#define GC_UNPROTECT_RECURSION(p) \
@@ -691,7 +694,7 @@ static sw_inline void sw_zval_free(zval *val)
#define SW_HASHTABLE_FOREACH_START2(ht, k, klen, ktype, _val) zend_string *_foreach_key;\
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _foreach_key, _val); \
if (!_foreach_key) {k = NULL; klen = 0; ktype = 0;} \
else {k = _foreach_key->val, klen=_foreach_key->len; ktype = 1;} {
else {k = ZSTR_VAL(_foreach_key), klen=ZSTR_LEN(_foreach_key); ktype = 1;} {
#define SW_HASHTABLE_FOREACH_END() } ZEND_HASH_FOREACH_END();

static sw_inline int add_assoc_ulong_safe(zval *arg, const char *key, zend_ulong value)
@@ -751,10 +754,16 @@ static sw_inline int add_assoc_ulong_safe(zval *arg, const char *key, zend_ulong
#define SWOOLE_SET_CLASS_UNSET_PROPERTY_HANDLER(module, _unset_property) \
module##_handlers.unset_property = _unset_property;

#define SWOOLE_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj) \
module##_ce_ptr->create_object = _create_object; \
#define SWOOLE_SET_CLASS_CREATE(module, _create_object) \
module##_ce_ptr->create_object = _create_object;

#define SWOOLE_SET_CLASS_FREE(module, _free_obj) \
module##_handlers.free_obj = _free_obj;

#define SWOOLE_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj) \
SWOOLE_SET_CLASS_CREATE(module, _create_object); \
SWOOLE_SET_CLASS_FREE(module, _free_obj);

#define SWOOLE_SET_CLASS_CUSTOM_OBJECT(module, _create_object, _free_obj, _struct, _std) \
SWOOLE_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj); \
module##_handlers.offset = XtOffsetOf(_struct, _std);
@@ -778,9 +787,9 @@ static sw_inline int sw_zend_register_class_alias(const char *name, size_t name_
zend_string *_interned_name = zend_new_interned_string(_name);

#if PHP_VERSION_ID >= 70300
return zend_register_class_alias_ex(_interned_name->val, _interned_name->len, ce, 1);
return zend_register_class_alias_ex(ZSTR_VAL(_interned_name), ZSTR_LEN(_interned_name), ce, 1);
#else
return zend_register_class_alias_ex(_interned_name->val, _interned_name->len, ce);
return zend_register_class_alias_ex(ZSTR_VAL(_interned_name), ZSTR_LEN(_interned_name), ce);
#endif
}

@@ -840,13 +849,19 @@ static sw_inline zval* sw_zend_read_property_array(zend_class_entry *class_ptr,
if (ZVAL_IS_NULL(&__retval)) *(retval) = NULL;\
else *(retval) = &__retval;

// TODO: remove it after remove async modules
static sw_inline int sw_zend_function_max_num_args(zend_function *function)
{
// https://github.com/php/php-src/commit/2646f7bcb98dcdd322ea21701c8bb101104ea619
// zend_function.common.num_args don't include the variadic argument anymore.
return (function->common.fn_flags & ZEND_ACC_VARIADIC) ? UINT32_MAX : function->common.num_args;
}

// TODO: remove it after remove async modules
static sw_inline int sw_zend_is_callable(zval *cb, int a, char **name)
{
zend_string *key = NULL;
int ret = zend_is_callable(cb, a, &key);
char *tmp = estrndup(key->val, key->len);
char *tmp = estrndup(ZSTR_VAL(key), ZSTR_LEN(key));
zend_string_release(key);
*name = tmp;
return ret;
@@ -876,7 +891,7 @@ static sw_inline int sw_zend_is_callable_ex(zval *zcallable, zval *zobject, uint
{
zend_string *key = NULL;
int ret = zend_is_callable_ex(zcallable, NULL, check_flags, &key, fci_cache, error);
char *tmp = estrndup(key->val, key->len);
char *tmp = estrndup(ZSTR_VAL(key), ZSTR_LEN(key));
zend_string_release(key);
*callable_name = tmp;
return ret;
@@ -931,6 +946,33 @@ static sw_inline int sw_call_function_anyway(zend_fcall_info *fci, zend_fcall_in
return ret;
}

static sw_inline void sw_fci_params_persist(zend_fcall_info *fci)
{
if (fci->param_count > 0)
{
uint32_t i;
zval *params = (zval *) ecalloc(fci->param_count, sizeof(zval));
for (i = 0; i < fci->param_count; i++)
{
ZVAL_COPY(&params[i], &fci->params[i]);
}
fci->params = params;
}
}

static sw_inline void sw_fci_params_discard(zend_fcall_info *fci)
{
if (fci->param_count > 0)
{
uint32_t i;
for (i = 0; i < fci->param_count; i++)
{
zval_ptr_dtor(&fci->params[i]);
}
efree(fci->params);
}
}

static sw_inline void sw_fci_cache_persist(zend_fcall_info_cache *fci_cache)
{
if (fci_cache->object)
@@ -960,16 +1002,16 @@ static sw_inline void sw_fci_cache_discard(zend_fcall_info_cache *fci_cache)
static sw_inline char* sw_php_format_date(char *format, size_t format_len, time_t ts, int localtime)
{
zend_string *time = php_format_date(format, format_len, ts, localtime);
char *return_str = estrndup(time->val, time->len);
char *return_str = estrndup(ZSTR_VAL(time), ZSTR_LEN(time));
zend_string_release(time);
return return_str;
}

static sw_inline char* sw_php_url_encode(char *value, size_t value_len, int* exten)
{
zend_string *str = php_url_encode(value, value_len);
*exten = str->len;
char *return_str = estrndup(str->val, str->len);
*exten = ZSTR_LEN(str);
char *return_str = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
zend_string_release(str);
return return_str;
}
@@ -0,0 +1,91 @@
#pragma once

#include "php_swoole.h"

namespace zend
{
class string
{
public:
static char* dup(zval *v)
{
string str(v);
return sw_strndup(str.val(), str.len());
}

static char* edup(zval *v)
{
string str(v);
return estrndup(str.val(), str.len());
}

string()
{
str = nullptr;
}

string(zval *v)
{
str = zval_get_string(v);
}

string(zend_string *v)
{
str = zend_string_copy(v);
}

void operator =(zval* v)
{
if (str)
{
zend_string_release(str);
}
str = zval_get_string(v);
}

inline char* val()
{
return ZSTR_VAL(str);
}

inline size_t len()
{
return ZSTR_LEN(str);
}

~string()
{
if (str)
{
zend_string_release(str);
}
}

private:
zend_string *str;
};

class string_ptr
{
public:
string_ptr(zend_string *str) :
str(str)
{
}
string_ptr(string_ptr &&o)
{
str = o.str;
o.str = nullptr;
}
~string_ptr()
{
if (str)
{
zend_string_release(str);
}
}
private:
zend_string *str;
};
}

@@ -108,6 +108,8 @@ void swoole_init(void)
}
#endif

SwooleG.socket_buffer_size = SW_SOCKET_BUFFER_SIZE;

SwooleTG.buffer_stack = swString_new(SW_STACK_BUFFER_SIZE);
if (SwooleTG.buffer_stack == NULL)
{
@@ -774,6 +776,27 @@ void swBreakPoint()

}

size_t sw_snprintf(char *buf, size_t size, const char *format, ...)
{
int ret;
va_list args;

va_start(args, format);
ret = vsnprintf(buf, size, format, args);
va_end(args);
if (unlikely(ret < 0))
{
ret = 0;
buf[0] = '\0';
}
else if (unlikely(ret >= size))
{
ret = size - 1;
buf[ret] = '\0';
}
return ret;
}

void swoole_ioctl_set_block(int sock, int nonblock)
{
int ret;
@@ -1265,21 +1288,20 @@ int swoole_shell_exec(const char *command, pid_t *pid, uint8_t get_error_stream)
char* swoole_string_format(size_t n, const char *format, ...)
{
char *buf = sw_malloc(n);
if (buf == NULL)
{
return NULL;
}

va_list _va_list;
va_start(_va_list, format);

if (vsnprintf(buf, n, format, _va_list) < 0)
{
if (buf)
{
int ret;
va_list va_list;
va_start(va_list, format);
ret = vsnprintf(buf, n, format, va_list);
va_end(va_list);
if (ret >= 0)
{
return buf;
}
sw_free(buf);
return NULL;
}

return buf;
return NULL;
}

#ifdef HAVE_EXECINFO
@@ -32,159 +32,165 @@ class Exception
};
}

const char* swstrerror(enum swErrorCode code)
const char* swoole_strerror(enum swErrorCode code)
{
/* swstrerror {{{*/
switch(code)
{
case SW_ERROR_MALLOC_FAIL:
return "malloc fail";
return "Malloc fail";
case SW_ERROR_SYSTEM_CALL_FAIL:
return "system call fail";
return "System call fail";
case SW_ERROR_PHP_FATAL_ERROR:
return "php fatal error";
return "PHP fatal error";
case SW_ERROR_NAME_TOO_LONG:
return "name too long";
return "Name too long";
case SW_ERROR_INVALID_PARAMS:
return "invalid params";
return "Invalid params";
case SW_ERROR_QUEUE_FULL:
return "queue full";
return "Queue full";
case SW_ERROR_FILE_NOT_EXIST:
return "file not exist";
return "File not exist";
case SW_ERROR_FILE_TOO_LARGE:
return "file too large";
return "File too large";
case SW_ERROR_FILE_EMPTY:
return "file empty";
return "File empty";
case SW_ERROR_DNSLOOKUP_DUPLICATE_REQUEST:
return "dnslookup duplicate request";
return "DNS Lookup duplicate request";
case SW_ERROR_DNSLOOKUP_RESOLVE_FAILED:
return "dnslookup resolve failed";
return "DNS Lookup resolve failed";
case SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT:
return "dnslookup resolve timeout";
return "DNS Lookup resolve timeout";
case SW_ERROR_BAD_IPV6_ADDRESS:
return "bad ipv6 address";
return "Bad ipv6 address";
case SW_ERROR_UNREGISTERED_SIGNAL:
return "unregistered signal";
return "Unregistered signal";
case SW_ERROR_SESSION_CLOSED_BY_SERVER:
return "session closed by server";
return "Session closed by server";
case SW_ERROR_SESSION_CLOSED_BY_CLIENT:
return "session closed by client";
return "Session closed by client";
case SW_ERROR_SESSION_CLOSING:
return "session closing";
return "Session closing";
case SW_ERROR_SESSION_CLOSED:
return "session closed";
return "Session closed";
case SW_ERROR_SESSION_NOT_EXIST:
return "session not exist";
return "Session not exist";
case SW_ERROR_SESSION_INVALID_ID:
return "session invalid id";
return "Session invalid id";
case SW_ERROR_SESSION_DISCARD_TIMEOUT_DATA:
return "session discard timeout data";
return "Session discard timeout data";
case SW_ERROR_OUTPUT_BUFFER_OVERFLOW:
return "output buffer overflow";
return "Output buffer overflow";
case SW_ERROR_SSL_NOT_READY:
return "ssl not ready";
return "SSL not ready";
case SW_ERROR_SSL_CANNOT_USE_SENFILE:
return "ssl cannot use senfile";
return "SSL cannot use senfile";
case SW_ERROR_SSL_EMPTY_PEER_CERTIFICATE:
return "ssl empty peer certificate";
return "SSL empty peer certificate";
case SW_ERROR_SSL_VEFIRY_FAILED:
return "ssl vefiry failed";
return "SSL vefiry failed";
case SW_ERROR_SSL_BAD_CLIENT:
return "ssl bad client";
return "SSL bad client";
case SW_ERROR_SSL_BAD_PROTOCOL:
return "ssl bad protocol";
return "SSL bad protocol";
case SW_ERROR_PACKAGE_LENGTH_TOO_LARGE:
return "package length too large";
return "Package length too large";
case SW_ERROR_DATA_LENGTH_TOO_LARGE:
return "data length too large";
return "Data length too large";
case SW_ERROR_TASK_PACKAGE_TOO_BIG:
return "task package too big";
return "Task package too big";
case SW_ERROR_TASK_DISPATCH_FAIL:
return "task dispatch fail";
return "Task dispatch fail";
case SW_ERROR_HTTP2_STREAM_ID_TOO_BIG:
return "http2 stream id too big";
return "Http2 stream id too big";
case SW_ERROR_HTTP2_STREAM_NO_HEADER:
return "http2 stream no header";
return "Http2 stream no header";
case SW_ERROR_HTTP2_STREAM_NOT_FOUND:
return "http2 stream not found";
return "Http2 stream not found";
case SW_ERROR_AIO_BAD_REQUEST:
return "aio bad request";
return "Aio bad request";
case SW_ERROR_AIO_CANCELED:
return "aio canceled";
return "Aio canceled";
case SW_ERROR_CLIENT_NO_CONNECTION:
return "client no connection";
return "Client no connection";
case SW_ERROR_SOCKET_CLOSED:
return "socket closed";
return "Socket closed";
case SW_ERROR_SOCKS5_UNSUPPORT_VERSION:
return "socks5 unsupport version";
return "Socks5 unsupport version";
case SW_ERROR_SOCKS5_UNSUPPORT_METHOD:
return "socks5 unsupport method";
return "Socks5 unsupport method";
case SW_ERROR_SOCKS5_AUTH_FAILED:
return "socks5 auth failed";
return "Socks5 auth failed";
case SW_ERROR_SOCKS5_SERVER_ERROR:
return "socks5 server error";
return "Socks5 server error";
case SW_ERROR_HTTP_PROXY_HANDSHAKE_ERROR:
return "http proxy handshake error";
return "Http proxy handshake error";
case SW_ERROR_HTTP_INVALID_PROTOCOL:
return "http invalid protocol";
return "Http invalid protocol";
case SW_ERROR_WEBSOCKET_BAD_CLIENT:
return "websocket bad client";
return "Websocket bad client";
case SW_ERROR_WEBSOCKET_BAD_OPCODE:
return "websocket bad opcode";
return "Websocket bad opcode";
case SW_ERROR_WEBSOCKET_UNCONNECTED:
return "websocket unconnected";
return "Websocket unconnected";
case SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED:
return "websocket handshake failed";
return "Websocket handshake failed";
case SW_ERROR_SERVER_MUST_CREATED_BEFORE_CLIENT:
return "server must created before client";
return "Server must created before client";
case SW_ERROR_SERVER_TOO_MANY_SOCKET:
return "server too many socket";
return "Server too many socket";
case SW_ERROR_SERVER_WORKER_TERMINATED:
return "server worker terminated";
return "Server worker terminated";
case SW_ERROR_SERVER_INVALID_LISTEN_PORT:
return "server invalid listen port";
return "Server invalid listen port";
case SW_ERROR_SERVER_TOO_MANY_LISTEN_PORT:
return "server too many listen port";
return "Server too many listen port";
case SW_ERROR_SERVER_PIPE_BUFFER_FULL:
return "server pipe buffer full";
return "Server pipe buffer full";
case SW_ERROR_SERVER_NO_IDLE_WORKER:
return "server no idle worker";
return "Server no idle worker";
case SW_ERROR_SERVER_ONLY_START_ONE:
return "server only start one";
return "Server only start one";
case SW_ERROR_SERVER_SEND_IN_MASTER:
return "server send in master";
return "Server send in master";
case SW_ERROR_SERVER_INVALID_REQUEST:
return "server invalid request";
return "Server invalid request";
case SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT:
return "server worker exit timeout";
return "Server worker exit timeout";
case SW_ERROR_CO_OUT_OF_COROUTINE:
return "coroutine out of coroutine";
return "Coroutine out of coroutine";
case SW_ERROR_CO_HAS_BEEN_BOUND:
return "coroutine has been bound";
return "Coroutine has been bound";
case SW_ERROR_CO_MUTEX_DOUBLE_UNLOCK:
return "coroutine mutex double unlock";
return "Coroutine mutex double unlock";
case SW_ERROR_CO_BLOCK_OBJECT_LOCKED:
return "coroutine block object locked";
return "Coroutine block object locked";
case SW_ERROR_CO_BLOCK_OBJECT_WAITING:
return "coroutine block object waiting";
return "Coroutine block object waiting";
case SW_ERROR_CO_YIELD_FAILED:
return "coroutine yield failed";
return "Coroutine yield failed";
case SW_ERROR_CO_GETCONTEXT_FAILED:
return "coroutine getcontext failed";
return "Coroutine getcontext failed";
case SW_ERROR_CO_SWAPCONTEXT_FAILED:
return "coroutine swapcontext failed";
return "Coroutine swapcontext failed";
case SW_ERROR_CO_MAKECONTEXT_FAILED:
return "coroutine makecontext failed";
return "Coroutine makecontext failed";
case SW_ERROR_CO_IOCPINIT_FAILED:
return "coroutine iocpinit failed";
return "Coroutine iocpinit failed";
case SW_ERROR_CO_PROTECT_STACK_FAILED:
return "coroutine protect stack failed";
return "Coroutine protect stack failed";
case SW_ERROR_CO_STD_THREAD_LINK_ERROR:
return "coroutine std thread link error";
return "Coroutine std thread link error";
case SW_ERROR_CO_DISABLED_MULTI_THREAD:
return "coroutine disabled multi thread";
default:
return "Unknown error";
return "Coroutine disabled multi thread";
default:
static char buffer[32];
#ifndef __MACH__
snprintf(buffer, sizeof(buffer), "Unknown error %d", code);
#else
snprintf(buffer, sizeof(buffer), "Unknown error: %d", code);
#endif
return buffer;
}
/*}}}*/
}
@@ -162,7 +162,7 @@ void swHeap_change_priority(swHeap *heap, uint64_t new_priority, void* ptr)
}
}

int swHeap_remove(swHeap *heap, swHeap_node *node)
void swHeap_remove(swHeap *heap, swHeap_node *node)
{
uint32_t pos = node->position;
heap->nodes[pos] = heap->nodes[--heap->num];
@@ -175,7 +175,6 @@ int swHeap_remove(swHeap *heap, swHeap_node *node)
{
swHeap_percolate_down(heap, pos);
}
return SW_OK;
}

void *swHeap_pop(swHeap *heap)
@@ -101,9 +101,9 @@ void swLog_put(int level, char *cnt)
break;
}

n = snprintf(log_str, SW_LOG_BUFFER_SIZE, "[%s %c%d.%d]\t%s\t%s\n", date_str, process_flag, SwooleG.pid, process_id, level_str, cnt);
n = sw_snprintf(log_str, SW_LOG_BUFFER_SIZE, "[%s %c%d.%d]\t%s\t%s\n", date_str, process_flag, SwooleG.pid, process_id, level_str, cnt);
if (write(SwooleG.log_fd, log_str, n) < 0)
{
printf("write(log_fd, size=%d) failed. Error: %s[%d].\n", n, strerror(errno), errno);
printf("write(log_fd, size=%d) failed. Error: %s[%d].\nMessage: %s\n", n, strerror(errno), errno, log_str);
}
}
@@ -24,23 +24,27 @@ swString *swString_new(size_t size)
swWarn("malloc[1] failed.");
return NULL;
}
bzero(str, sizeof(swString));

str->length = 0;
str->size = size;
str->offset = 0;
str->str = sw_malloc(size);

if (str->str == NULL)
{
swSysError("malloc[2](%ld) failed.", size);
sw_free(str);
return NULL;
}

return str;
}

void swString_print(swString *str)
{
printf(
"String[length=%d,size=%d,offset=%d]=%s\n",
(int) str->length, (int) str->size, (int) str->offset, str->str
"String[length=%zu,size=%zu,offset=%jd]=%.*s\n",
str->length, str->size, (intmax_t) str->offset, (int) str->length, str->str
);
}

@@ -54,42 +58,33 @@ swString *swString_dup2(swString *src)
dst->offset = src->offset;
memcpy(dst->str, src->str, src->length);
}

return dst;
}

swString *swString_dup(const char *src_str, int length)
swString *swString_dup(const char *src_str, size_t length)
{
swString *str = sw_malloc(sizeof(swString));
if (str == NULL)
swString *str = swString_new(length);
if (str)
{
swWarn("malloc[1] failed.");
return NULL;
str->length = length;
memcpy(str->str, src_str, length);
}

bzero(str, sizeof(swString));
str->length = length;
str->size = length + 1;
str->str = sw_malloc(str->size);
if (str->str == NULL)
{
swWarn("malloc[2] failed.");
sw_free(str);
return NULL;
}
memcpy(str->str, src_str, length + 1);
return str;
}

int swString_append(swString *str, swString *append_str)
{
int new_size = str->length + append_str->length;
size_t new_size = str->length + append_str->length;
if (new_size > str->size)
{
if (swString_extend(str, swoole_size_align(new_size * 2, SwooleG.pagesize)) < 0)
{
return SW_ERR;
}
}

memcpy(str->str + str->length, append_str->str, append_str->length);
str->length += append_str->length;
return SW_OK;
@@ -100,67 +95,73 @@ int swString_append_int(swString *str, int value)
char buf[16];
int s_len = swoole_itoa(buf, value);

int new_size = str->length + s_len;
size_t new_size = str->length + s_len;
if (new_size > str->size)
{
if (swString_extend(str, swoole_size_align(new_size * 2, SwooleG.pagesize)) < 0)
{
return SW_ERR;
}
}

memcpy(str->str + str->length, buf, s_len);
str->length += s_len;
return SW_OK;
}

int swString_append_ptr(swString *str, const char *append_str, size_t length)
{
int new_size = str->length + length;
size_t new_size = str->length + length;
if (new_size > str->size)
{
if (swString_extend(str, swoole_size_align(new_size * 2, SwooleG.pagesize)) < 0)
{
return SW_ERR;
}
}

memcpy(str->str + str->length, append_str, length);
str->length += length;
return SW_OK;
}

int swString_write(swString *str, off_t offset, swString *write_str)
{
int new_length = offset + write_str->length;
size_t new_length = offset + write_str->length;
if (new_length > str->size)
{
if (swString_extend(str, swoole_size_align(new_length * 2, SwooleG.pagesize)) < 0)
{
return SW_ERR;
}
}

memcpy(str->str + offset, write_str->str, write_str->length);
if (new_length > str->length)
{
str->length = new_length;
}

return SW_OK;
}

int swString_write_ptr(swString *str, off_t offset, char *write_str, size_t length)
{
int new_length = offset + length;
size_t new_length = offset + length;
if (new_length > str->size)
{
if (swString_extend(str, swoole_size_align(new_length * 2, SwooleG.pagesize)) < 0)
{
return SW_ERR;
}
}

memcpy(str->str + offset, write_str, length);
if (new_length > str->length)
{
str->length = new_length;
}

return SW_OK;
}

@@ -173,6 +174,7 @@ int swString_extend(swString *str, size_t new_size)
swSysError("realloc(%ld) failed.", new_size);
return SW_ERR;
}

str->str = new_str;
str->size = new_size;
return SW_OK;
@@ -187,6 +189,7 @@ char* swString_alloc(swString *str, size_t __size)
return NULL;
}
}

char *tmp = str->str + str->length;
str->length += __size;
return tmp;
@@ -32,34 +32,33 @@ std::unordered_map<long, Coroutine*> Coroutine::coroutines;

long Coroutine::create(coroutine_func_t fn, void* args)
{
if (unlikely(Coroutine::call_stack_size == SW_MAX_CORO_NESTING_LEVEL))
if (unlikely(call_stack_size == SW_MAX_CORO_NESTING_LEVEL))
{
swWarn("reaches the max coroutine nesting level %d", SW_MAX_CORO_NESTING_LEVEL);
return SW_CORO_ERR_LIMIT;
}
Coroutine *co = new Coroutine(fn, args);
return co->run();
return (new Coroutine(fn, args))->run();
}

void Coroutine::yield()
{
state = SW_CORO_WAITING;
if (Coroutine::on_yield)
if (on_yield)
{
Coroutine::on_yield(task);
on_yield(task);
}
Coroutine::call_stack_size--;
call_stack_size--;
ctx.SwapOut();
}

void Coroutine::resume()
{
state = SW_CORO_RUNNING;
if (Coroutine::on_resume)
if (on_resume)
{
Coroutine::on_resume(task);
on_resume(task);
}
Coroutine::call_stack[Coroutine::call_stack_size++] = this;
call_stack[call_stack_size++] = this;
ctx.SwapIn();
if (ctx.end)
{
@@ -70,14 +69,14 @@ void Coroutine::resume()
void Coroutine::yield_naked()
{
state = SW_CORO_WAITING;
Coroutine::call_stack_size--;
call_stack_size--;
ctx.SwapOut();
}

void Coroutine::resume_naked()
{
state = SW_CORO_RUNNING;
Coroutine::call_stack[Coroutine::call_stack_size++] = this;
call_stack[call_stack_size++] = this;
ctx.SwapIn();
if (ctx.end)
{
@@ -88,54 +87,47 @@ void Coroutine::resume_naked()
void Coroutine::close()
{
state = SW_CORO_END;
if (Coroutine::on_close)
if (on_close)
{
Coroutine::on_close(task);
on_close(task);
}
Coroutine::call_stack_size--;
Coroutine::coroutines.erase(cid);
call_stack_size--;
coroutines.erase(cid);
delete this;
}

Coroutine* Coroutine::get_current()
{
return likely(Coroutine::call_stack_size > 0) ? Coroutine::call_stack[Coroutine::call_stack_size - 1] : nullptr;
return likely(call_stack_size > 0) ? call_stack[call_stack_size - 1] : nullptr;
}

void* Coroutine::get_current_task()
{
Coroutine* co = Coroutine::get_current();
Coroutine* co = get_current();
return likely(co) ? co->get_task() : nullptr;
}

long Coroutine::get_current_cid()
{
Coroutine* co = Coroutine::get_current();
Coroutine* co = get_current();
return likely(co) ? co->get_cid() : -1;
}

Coroutine* Coroutine::get_by_cid(long cid)
{
auto coroutine_iterator = Coroutine::coroutines.find(cid);
if (coroutine_iterator == Coroutine::coroutines.end())
{
return nullptr;
}
else
{
return coroutine_iterator->second;
}
auto i = coroutines.find(cid);
return likely(i != coroutines.end()) ? i->second : nullptr;
}

void* Coroutine::get_task_by_cid(long cid)
{
Coroutine *co = Coroutine::get_by_cid(cid);
Coroutine *co = get_by_cid(cid);
return likely(co) ? co->get_task() : nullptr;
}

void Coroutine::print_list()
{
for (auto i = Coroutine::coroutines.begin(); i != Coroutine::coroutines.end(); i++)
for (auto i = coroutines.begin(); i != coroutines.end(); i++)
{
const char *state;
switch(i->second->state){
@@ -161,17 +153,17 @@ void Coroutine::print_list()

void Coroutine::set_on_yield(coro_php_yield_t func)
{
Coroutine::on_yield = func;
on_yield = func;
}

void Coroutine::set_on_resume(coro_php_resume_t func)
{
Coroutine::on_resume = func;
on_resume = func;
}

void Coroutine::set_on_close(coro_php_close_t func)
{
Coroutine::on_close = func;
on_close = func;
}

/**
@@ -15,18 +15,23 @@
*/

#include "swoole.h"
#include "context.h"

#ifndef SW_NO_USE_ASM_CONTEXT

#include "context.h"

#ifdef USE_VALGRIND
#include <valgrind/valgrind.h>
#endif

using namespace swoole;

Context::Context(size_t stack_size, coroutine_func_t fn, void* private_data) :
fn_(fn), stack_size_(stack_size), private_data_(private_data)
{
protect_page_ = 0;
end = false;
swap_ctx_ = NULL;
swap_ctx_ = nullptr;

stack_ = (char*) sw_malloc(stack_size_);
swTraceLog(SW_TRACE_COROUTINE, "alloc stack: size=%u, ptr=%p.", stack_size_, stack_);
@@ -56,7 +61,7 @@ Context::~Context()
{
unprotect_stack(stack_, protect_page_);
}
#if defined(USE_VALGRIND)
#ifdef USE_VALGRIND
VALGRIND_STACK_DEREGISTER(valgrind_stack_id);
#endif
sw_free(stack_);
@@ -51,7 +51,10 @@ void swoole::set_dns_cache_capacity(size_t capacity)

void swoole::clear_dns_cache()
{
dns_cache->clear();
if (dns_cache)
{
dns_cache->clear();
}
}

extern "C"
@@ -68,13 +71,13 @@ int swoole_coroutine_socket(int domain, int type, int protocol)
{
return socket(domain, type, protocol);
}
Socket *sock = new Socket(domain, type, protocol);
if (sock->socket == nullptr)
Socket *socket = new Socket(domain, type, protocol);
if (socket->socket == nullptr)
{
delete sock;
delete socket;
return -1;
}
return sock->socket->fd;
return socket->socket->fd;
}

ssize_t swoole_coroutine_send(int sockfd, const void *buf, size_t len, int flags)
@@ -89,15 +92,7 @@ ssize_t swoole_coroutine_send(int sockfd, const void *buf, size_t len, int flags
goto _no_coro;
}
Socket *socket = (Socket *) conn->object;
ssize_t retval = socket->send(buf, len);
if (retval < 0)
{
return -1;
}
else
{
return retval;
}
return socket->send(buf, len);
}

ssize_t swoole_coroutine_sendmsg(int sockfd, const struct msghdr *msg, int flags)
@@ -112,15 +107,7 @@ ssize_t swoole_coroutine_sendmsg(int sockfd, const struct msghdr *msg, int flags
goto _no_coro;
}
Socket *socket = (Socket *) conn->object;
ssize_t retval = socket->sendmsg(msg, flags);
if (retval < 0)
{
return -1;
}
else
{
return retval;
}
return socket->sendmsg(msg, flags);
}

ssize_t swoole_coroutine_recvmsg(int sockfd, struct msghdr *msg, int flags)
@@ -135,15 +122,7 @@ ssize_t swoole_coroutine_recvmsg(int sockfd, struct msghdr *msg, int flags)
goto _no_coro;
}
Socket *socket = (Socket *) conn->object;
ssize_t retval = socket->recvmsg(msg, flags);
if (retval < 0)
{
return -1;
}
else
{
return retval;
}
return socket->recvmsg(msg, flags);
}

ssize_t swoole_coroutine_recv(int sockfd, void *buf, size_t len, int flags)
@@ -158,22 +137,13 @@ ssize_t swoole_coroutine_recv(int sockfd, void *buf, size_t len, int flags)
goto _no_coro;
}
Socket *socket = (Socket *) conn->object;
ssize_t retval;
if (flags & MSG_PEEK)
{
retval = socket->peek(buf, len);
}
else
{
retval = socket->recv(buf, len);
}
if (retval < 0)
{
return -1;
return socket->peek(buf, len);
}
else
{
return retval;
return socket->recv(buf, len);
}
}

@@ -188,11 +158,8 @@ int swoole_coroutine_close(int fd)
{
goto _no_coro;
}
else
{
delete (Socket *) conn->object;
return 0;
}
Socket *socket = (Socket *) conn->object;
return socket->close() ? 0 : -1;
}

int swoole_coroutine_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
@@ -207,14 +174,7 @@ int swoole_coroutine_connect(int sockfd, const struct sockaddr *addr, socklen_t
goto _no_coro;
}
Socket *socket = (Socket *) conn->object;
if (socket->connect(addr, addrlen) == false)
{
return -1;
}
else
{
return 0;
}
return socket->connect(addr, addrlen) ? 0 : -1;
}

int swoole_coroutine_poll(struct pollfd *fds, nfds_t nfds, int timeout)
@@ -380,7 +340,7 @@ int swoole_coroutine_open(const char *pathname, int flags, mode_t mode)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -413,7 +373,7 @@ ssize_t swoole_coroutine_read(int fd, void *buf, size_t count)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -446,7 +406,7 @@ ssize_t swoole_coroutine_write(int fd, const void *buf, size_t count)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -472,7 +432,7 @@ off_t swoole_coroutine_lseek(int fd, off_t offset, int whence)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -497,7 +457,7 @@ int swoole_coroutine_fstat(int fd, struct stat *statbuf)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -521,7 +481,7 @@ int swoole_coroutine_unlink(const char *pathname)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -546,7 +506,7 @@ int swoole_coroutine_statvfs(const char *path, struct statvfs *buf)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -571,7 +531,7 @@ int swoole_coroutine_mkdir(const char *pathname, mode_t mode)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -595,7 +555,7 @@ int swoole_coroutine_rmdir(const char *pathname)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -620,7 +580,7 @@ int swoole_coroutine_rename(const char *oldpath, const char *newpath)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -645,7 +605,7 @@ int swoole_coroutine_access(const char *pathname, int mode)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -670,7 +630,7 @@ int swoole_coroutine_flock(int fd, int operation)
int ret = swAio_dispatch(&ev);
if (ret < 0)
{
return SW_ERR;
return -1;
}
((Coroutine *) ev.object)->yield();
return ev.ret;
@@ -783,7 +743,7 @@ string Coroutine::gethostbyname(const string &hostname, int domain, double timeo
}

swAio_event ev;
aio_task task ;
aio_task task;

bzero(&ev, sizeof(swAio_event));
if (hostname.size() < SW_IP_MAX_LENGTH)
@@ -812,7 +772,7 @@ string Coroutine::gethostbyname(const string &hostname, int domain, double timeo
ev.callback = aio_onDNSCompleted;

swAio_event *event = swAio_dispatch2(&ev);
swTimer_node* timer = nullptr;
swTimer_node *timer = nullptr;
if (timeout > 0)
{
timer = swTimer_add(&SwooleG.timer, (long) (timeout * 1000), 0, event, aio_onDNSTimeout);

Large diffs are not rendered by default.

@@ -143,7 +143,7 @@ int swTableColumn_add(swTable *table, char *name, int len, int type, int size)
}
col->index = table->item_size;
table->item_size += col->size;
table->column_num ++;
++table->column_num;
return swHashMap_add(table->columns, name, len, col);
}

@@ -169,8 +169,7 @@ class async_thread_pool

async_event* dispatch(const async_event *request)
{
async_event *_event_copy = new async_event;
*_event_copy = *request;
auto _event_copy = new async_event(*request);
schedule();
_event_copy->task_id = current_task_id++;
queue.push(_event_copy);
@@ -199,7 +198,7 @@ class async_thread_pool
_accept: event = queue.pop();
if (event)
{
if (unlikely(event->handler == NULL))
if (unlikely(event->handler == nullptr))
{
event->error = SW_ERROR_AIO_BAD_REQUEST;
event->ret = -1;
@@ -218,7 +217,7 @@ class async_thread_pool

swTrace("aio_thread ok. ret=%d, error=%d", event->ret, event->error);

_error: while (1)
_error: while (true)
{
SwooleAIO.lock.lock(&SwooleAIO.lock);
int ret = write(_pipe_write, &event, sizeof(event));
@@ -250,11 +249,14 @@ class async_thread_pool
else
{
unique_lock<mutex> lock(_mutex);
++n_waiting;
_cv.wait(lock);
--n_waiting;
if (running)
{
++n_waiting;
_cv.wait(lock);
--n_waiting;
}
}
if (running )
if (running)
{
goto _accept;
}
@@ -281,7 +283,7 @@ class async_thread_pool

static async_thread_pool *pool = nullptr;

static int swAio_init(void)
static int swAio_init()
{
if (SwooleAIO.init)
{
@@ -1514,7 +1514,7 @@ static int swClient_onWrite(swReactor *reactor, swEvent *event)
if (cli->open_ssl)
{
cli->http_proxy->state = SW_HTTP_PROXY_STATE_HANDSHAKE;
int n = snprintf(cli->http_proxy->buf, sizeof (cli->http_proxy->buf), "CONNECT %s:%d HTTP/1.1\r\n\r\n", cli->http_proxy->target_host, cli->http_proxy->target_port);
int n = sw_snprintf(cli->http_proxy->buf, sizeof (cli->http_proxy->buf), "CONNECT %s:%d HTTP/1.1\r\n\r\n", cli->http_proxy->target_host, cli->http_proxy->target_port);
return cli->send(cli, cli->http_proxy->buf, n, 0);
}
#endif
@@ -174,7 +174,7 @@ swString* swConnection_get_string_buffer(swConnection *conn)
swString *buffer = conn->object;
if (buffer == NULL)
{
return swString_new(SW_BUFFER_SIZE);
return swString_new(SW_IPC_BUFFER_SIZE);
}
else
{
@@ -230,7 +230,7 @@ int swConnection_sendfile(swConnection *conn, char *filename, off_t offset, size
{
if (conn->out_buffer == NULL)
{
conn->out_buffer = swBuffer_new(SW_BUFFER_SIZE);
conn->out_buffer = swBuffer_new(SW_IPC_BUFFER_SIZE);
if (conn->out_buffer == NULL)
{
return SW_ERR;
@@ -315,7 +315,7 @@ swBuffer_chunk* swConnection_get_in_buffer(swConnection *conn)

if (conn->in_buffer == NULL)
{
buffer = swBuffer_new(SW_BUFFER_SIZE);
buffer = swBuffer_new(SW_IPC_BUFFER_SIZE);
//buffer create failed
if (buffer == NULL)
{
@@ -347,7 +347,7 @@ swBuffer_chunk* swConnection_get_out_buffer(swConnection *conn, uint32_t type)
swBuffer_chunk *chunk;
if (conn->out_buffer == NULL)
{
conn->out_buffer = swBuffer_new(SW_BUFFER_SIZE);
conn->out_buffer = swBuffer_new(SW_IPC_BUFFER_SIZE);
if (conn->out_buffer == NULL)
{
return NULL;
@@ -233,7 +233,7 @@ static int swDNSResolver_onReceive(swReactor *reactor, swEvent *event)

char key[1024];
int request_id = ntohs(header->id);
int key_len = snprintf(key, sizeof(key), "%s-%d", _domain_name, request_id);
int key_len = sw_snprintf(key, sizeof(key), "%s-%d", _domain_name, request_id);
swDNS_lookup_request *request = swHashMap_find(request_map, key, key_len);
if (request == NULL)
{
@@ -310,7 +310,7 @@ int swDNSResolver_request(char *domain, void (*callback)(char *, swDNSResolver_r
return SW_ERR;
}

int key_len = snprintf(key, sizeof(key), "%s-%d", domain, swoole_dns_request_id);
int key_len = sw_snprintf(key, sizeof(key), "%s-%d", domain, swoole_dns_request_id);
if (!request_map)
{
request_map = swHashMap_new(128, NULL);
@@ -29,13 +29,46 @@ static int swProcessPool_worker_loop_ex(swProcessPool *pool, swWorker *worker);

static void swProcessPool_free(swProcessPool *pool);


static void swProcessPool_killTimeout(swTimer *timer, swTimer_node *tnode)
{
int i;
pid_t reload_worker_pid = 0;
swProcessPool *pool = (swProcessPool *)tnode->data;
pool->reloading = 0;

for (i = 0; i < pool->worker_num; i++)
{
if (i >= pool->reload_worker_i)
{
reload_worker_pid = pool->reload_workers[i].pid;
if (kill(reload_worker_pid, 0 == -1))
{
continue;
}
if (kill(reload_worker_pid, SIGKILL) < 0)
{
swSysError("kill(%d, SIGKILL) [%d] failed.", pool->reload_workers[i].pid, i);
}
else
{
swWarn("kill(%d, SIGKILL) [%d].", pool->reload_workers[i].pid, i);
}
}
}
errno = 0;
pool->reload_worker_i = 0;
pool->reload_init = 0;
}
/**
* Process manager
*/
int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, key_t msgqueue_key, int ipc_mode)
{
bzero(pool, sizeof(swProcessPool));

int i;

pool->worker_num = worker_num;
pool->max_request = max_request;

@@ -74,7 +107,6 @@ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, k
}

swPipe *pipe;
int i;
for (i = 0; i < worker_num; i++)
{
pipe = &pool->pipes[i];
@@ -118,6 +150,11 @@ int swProcessPool_create(swProcessPool *pool, int worker_num, int max_request, k
pool->main_loop = swProcessPool_worker_loop;
}

for (i = 0; i < worker_num; i++)
{
pool->workers[i].pool = pool;
}

return SW_OK;
}

@@ -180,12 +217,16 @@ int swProcessPool_start(swProcessPool *pool)
pool->workers[i].pool = pool;
pool->workers[i].id = pool->start_id + i;
pool->workers[i].type = pool->type;
}

for (i = 0; i < pool->worker_num; i++)
{
if (swProcessPool_spawn(pool, &(pool->workers[i])) < 0)
{
return SW_ERR;
}
}

return SW_OK;
}

@@ -235,7 +276,6 @@ int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int *dst_work
return SW_ERR;
}
stream->response = NULL;
stream->session_id = 0;
if (swStream_send(stream, (char*) data, sizeof(data->info) + data->info.len) < 0)
{
stream->cancel = 1;
@@ -693,13 +733,13 @@ int swProcessPool_add_worker(swProcessPool *pool, swWorker *worker)
int swProcessPool_wait(swProcessPool *pool)
{
int pid, new_pid;
int reload_worker_i = 0;
// int reload_worker_i = 0;
pid_t reload_worker_pid = 0;
int ret;
int status;

swWorker *reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker));
if (reload_workers == NULL)
pool->reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker));
if (pool->reload_workers == NULL)
{
swError("malloc[reload_workers] failed");
return SW_ERR;
@@ -708,6 +748,11 @@ int swProcessPool_wait(swProcessPool *pool)
while (SwooleG.running)
{
pid = wait(&status);
if (SwooleG.signal_alarm == 1)
{
SwooleG.signal_alarm = 0;
swTimer_select(&SwooleG.timer);
}
if (pid < 0)
{
if (SwooleG.running == 0)
@@ -716,22 +761,26 @@ int swProcessPool_wait(swProcessPool *pool)
}
if (pool->reloading == 0)
{
if (errno != EINTR)
if (errno > 0 && errno != EINTR)
{
swWarn("[Manager] wait failed. Error: %s [%d]", strerror(errno), errno);
}
continue;
}

swNotice("reload workers.");

if (pool->reload_init == 0)
else
{
pool->reload_init = 1;
memcpy(reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num);
if (pool->reload_init == 0)
{
swNotice("reload workers.");
pool->reload_init = 1;
memcpy(pool->reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num);
if (pool->max_wait_time)
{
swTimer_add(&SwooleG.timer, (long) (pool->max_wait_time * 1000), 0, pool, swProcessPool_killTimeout);
}
}
goto kill_worker;
}

goto kill_worker;
}

if (SwooleG.running == 1)
@@ -761,39 +810,39 @@ int swProcessPool_wait(swProcessPool *pool)
if (new_pid < 0)
{
swWarn("Fork worker process failed. Error: %s [%d]", strerror(errno), errno);
sw_free(reload_workers);
sw_free(pool->reload_workers);
return SW_ERR;
}
swHashMap_del_int(pool->map, pid);
if (pid == reload_worker_pid)
{
reload_worker_i++;
pool->reload_worker_i++;
}
}
//reload worker
kill_worker: if (pool->reloading == 1)
{
//reload finish
if (reload_worker_i >= pool->worker_num)
if (pool->reload_worker_i >= pool->worker_num)
{
pool->reloading = pool->reload_init = reload_worker_pid = reload_worker_i = 0;
pool->reloading = pool->reload_init = reload_worker_pid = pool->reload_worker_i = 0;
continue;
}
reload_worker_pid = reload_workers[reload_worker_i].pid;
reload_worker_pid = pool->reload_workers[pool->reload_worker_i].pid;
ret = kill(reload_worker_pid, SIGTERM);
if (ret < 0)
{
if (errno == ECHILD)
{
reload_worker_i++;
pool->reload_worker_i++;
goto kill_worker;
}
swSysError("[Manager]kill(%d) failed.", reload_workers[reload_worker_i].pid);
swSysError("[Manager]kill(%d) failed.", pool->reload_workers[pool->reload_worker_i].pid);
continue;
}
}
}
sw_free(reload_workers);
sw_free(pool->reload_workers);
return SW_OK;
}

@@ -40,6 +40,8 @@ static void swStream_onConnect(swClient *cli)

static void swStream_onError(swClient *cli)
{
swoole_error_log(SW_LOG_WARNING, SW_ERROR_SERVER_CONNECT_FAIL,
" connect() failed (%d: %s) while connecting to worker process.", errno, strerror(errno));
swStream_free(cli->object);
}

@@ -94,7 +96,6 @@ swStream* swStream_new(char *dst_host, int dst_port, int type)
if (cli->connect(cli, dst_host, dst_port, -1, 0) < 0)
{
swSysError("failed to connect to [%s:%d].", dst_host, dst_port);
swStream_free(stream);
return NULL;
}
else
@@ -16,8 +16,7 @@

#include "swoole.h"

static int swReactorTimer_init(long msec);
static int swReactorTimer_set(swTimer *timer, long exec_msec);
static int swTimer_init(long msec);

int swTimer_now(struct timeval *time)
{
@@ -40,6 +39,21 @@ int swTimer_now(struct timeval *time)
return SW_OK;
}

static int swReactorTimer_set(swTimer *timer, long exec_msec)
{
SwooleG.main_reactor->timeout_msec = exec_msec;
return SW_OK;
}

static int swReactorTimer_init(long exec_msec)
{
SwooleG.main_reactor->check_timer = SW_TRUE;
SwooleG.main_reactor->timeout_msec = exec_msec;
SwooleG.timer.set = swReactorTimer_set;
SwooleG.timer.initialized = 1;
return SW_OK;
}

static int swTimer_init(long msec)
{
if (swTimer_now(&SwooleG.timer.basetime) < 0)
@@ -69,14 +83,12 @@ static int swTimer_init(long msec)

if (SwooleG.main_reactor == NULL)
{
swSystemTimer_init(msec);
return swSystemTimer_init(msec);
}
else
{
swReactorTimer_init(msec);
return swReactorTimer_init(msec);
}

return SW_OK;
}

void swTimer_free(swTimer *timer)
@@ -88,21 +100,6 @@ void swTimer_free(swTimer *timer)
timer->set(timer, -1);
}

static int swReactorTimer_init(long exec_msec)
{
SwooleG.main_reactor->check_timer = SW_TRUE;
SwooleG.main_reactor->timeout_msec = exec_msec;
SwooleG.timer.set = swReactorTimer_set;
SwooleG.timer.initialized = 1;
return SW_OK;
}

static int swReactorTimer_set(swTimer *timer, long exec_msec)
{
SwooleG.main_reactor->timeout_msec = exec_msec;
return SW_OK;
}

swTimer_node* swTimer_add(swTimer *timer, long _msec, int interval, void *data, swTimerCallback callback)
{
if (unlikely(SwooleG.timer.initialized == 0))
@@ -167,46 +164,53 @@ swTimer_node* swTimer_add(swTimer *timer, long _msec, int interval, void *data,
return tnode;
}

int swTimer_del(swTimer *timer, swTimer_node *tnode)
enum swBool_type swTimer_del_ex(swTimer *timer, swTimer_node *tnode, swTimerDtor dtor)
{
if (unlikely(tnode->remove))
if (unlikely(!tnode || tnode->remove))
{
return SW_FALSE;
}
if (SwooleG.timer._current_id > 0 && tnode->id == SwooleG.timer._current_id)
if (unlikely(SwooleG.timer._current_id > 0 && tnode->id == SwooleG.timer._current_id))
{
tnode->remove = 1;
swTraceLog(SW_TRACE_TIMER, "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", tnode->id, tnode->exec_msec, tnode->round, timer->num);
return SW_TRUE;
}
if (unlikely(swHashMap_del_int(timer->map, tnode->id) < 0))
{
return SW_ERR;
return SW_FALSE;
}
if (tnode->heap_node)
{
//remove from min-heap
swHeap_remove(timer->heap, tnode->heap_node);
sw_free(tnode->heap_node);
}
if (dtor)
{
dtor(tnode);
}
timer->num--;
swTraceLog(SW_TRACE_TIMER, "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", tnode->id, tnode->exec_msec, tnode->round, timer->num);
sw_free(tnode);
return SW_TRUE;
}

enum swBool_type swTimer_del(swTimer *timer, swTimer_node *tnode)
{
return swTimer_del_ex(timer, tnode, NULL);
}

int swTimer_select(swTimer *timer)
{
swTimer_node *tnode = NULL;
swHeap_node *tmp;
int64_t now_msec = swTimer_get_relative_msec();
if (now_msec < 0)

if (unlikely(now_msec < 0))
{
return SW_ERR;
}

swTimer_node *tnode = NULL;
swHeap_node *tmp;
long timer_id;

swTraceLog(SW_TRACE_TIMER, "timer msec=%" PRId64 ", round=%" PRId64, now_msec, timer->round);
while ((tmp = swHeap_top(timer->heap)))
{
@@ -216,7 +220,7 @@ int swTimer_select(swTimer *timer)
break;
}

timer_id = timer->_current_id = tnode->id;
timer->_current_id = tnode->id;
if (!tnode->remove)
{
swTraceLog(SW_TRACE_TIMER, "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", tnode->id, tnode->exec_msec, tnode->round, timer->num - 1);
@@ -237,7 +241,7 @@ int swTimer_select(swTimer *timer)

timer->num--;
swHeap_pop(timer->heap);
swHashMap_del_int(timer->map, timer_id);
swHashMap_del_int(timer->map, tnode->id);
sw_free(tnode);
}

@@ -256,5 +260,6 @@ int swTimer_select(swTimer *timer)
timer->set(timer, next_msec);
}
timer->round++;

return SW_OK;
}
@@ -30,6 +30,8 @@ int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
hdtr.hdr_cnt = 0;
hdtr.trailers = NULL;
hdtr.trl_cnt = 0;
#else
off_t sent_bytes;
#endif


@@ -43,7 +45,12 @@ int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size)
//sent_bytes = (off_t)size;
swTrace("send file, ret:%d, out_fd:%d, in_fd:%d, offset:%jd, size:%zu", ret, out_fd, in_fd, (intmax_t) *offset, size);

#ifdef __MACH__
*offset += size;
#else
*offset += sent_bytes;
#endif

if (ret == -1)
{
if (errno == EINTR)