From ca6ec5adeedf53fe8217e559150c9dab451ad4cc Mon Sep 17 00:00:00 2001 From: CismonX Date: Tue, 5 May 2020 10:57:39 +0800 Subject: [PATCH 1/3] Add support for platform Solaris. --- README.md | 2 +- base/hplatform.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 56543df29..3a6739858 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ but simpler apis and richer protocols. ## Features -- cross-platform (Linux, Windows, Mac) +- cross-platform (Linux, Windows, Mac, Solaris) - event-loop (IO, timer, idle) - ENABLE_IPV6 - WITH_OPENSSL diff --git a/base/hplatform.h b/base/hplatform.h index 39b1d1614..180b20f3b 100644 --- a/base/hplatform.h +++ b/base/hplatform.h @@ -38,6 +38,8 @@ #elif defined(__OpenBSD__) #define OS_OPENBSD #define OS_BSD +#elif defined(sun) || defined(__sun) || defined(__sun__) + #define OS_SOLARIS #else #error "Unsupported operating system platform!" #endif From 1ff49d1921073ebb881dabec38bc26392682d4e2 Mon Sep 17 00:00:00 2001 From: CismonX Date: Tue, 5 May 2020 10:59:16 +0800 Subject: [PATCH 2/3] Fix conflicting declarations. --- base/hmutex.h | 1 - base/hsocket.c | 6 +++--- base/hsocket.h | 24 ++++++++++++------------ base/htime.c | 2 ++ base/htime.h | 3 +++ event/hevent.c | 4 ++-- event/hloop.c | 12 ++++++------ event/nio.c | 16 ++++++++-------- http/server/HttpServer.cpp | 4 ++-- protocol/icmp.c | 2 +- 10 files changed, 39 insertions(+), 35 deletions(-) diff --git a/base/hmutex.h b/base/hmutex.h index afb83503f..e0c0c30fe 100644 --- a/base/hmutex.h +++ b/base/hmutex.h @@ -193,7 +193,6 @@ END_EXTERN_C #ifdef __cplusplus #include #include -using std::mutex; // NOTE: test std::timed_mutex incorrect in some platforms, use htimed_mutex_t // using std::timed_mutex; using std::condition_variable; diff --git a/base/hsocket.c b/base/hsocket.c index b60e60cd3..ca74cec36 100644 --- a/base/hsocket.c +++ b/base/hsocket.c @@ -15,7 +15,7 @@ const char* socket_strerror(int err) { #endif } -int Resolver(const char* host, sockaddr_un* addr) { +int Resolver(const char* host, sockaddr_u* addr) { if (inet_pton(AF_INET, host, &addr->sin.sin_addr) == 1) { addr->sa.sa_family = AF_INET; // host is ipv4, so easy ;) return 0; @@ -60,7 +60,7 @@ int Bind(int port, const char* host, int type) { WSAStartup(MAKEWORD(2,2), &wsadata); } #endif - sockaddr_un localaddr; + sockaddr_u localaddr; socklen_t addrlen = sizeof(localaddr); memset(&localaddr, 0, addrlen); int ret = sockaddr_assign(&localaddr, host, port); @@ -109,7 +109,7 @@ int Listen(int port, const char* host) { int Connect(const char* host, int port, int nonblock) { // Resolver -> socket -> nonblocking -> connect - sockaddr_un peeraddr; + sockaddr_u peeraddr; socklen_t addrlen = sizeof(peeraddr); memset(&peeraddr, 0, addrlen); int ret = sockaddr_assign(&peeraddr, host, port); diff --git a/base/hsocket.h b/base/hsocket.h index b60b5d284..2cbb24e20 100644 --- a/base/hsocket.h +++ b/base/hsocket.h @@ -51,23 +51,23 @@ typedef union { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; -} sockaddr_un; +} sockaddr_u; // @param host: domain or ip // @retval 0:succeed -int Resolver(const char* host, sockaddr_un* addr); +int Resolver(const char* host, sockaddr_u* addr); -static inline socklen_t sockaddrlen(sockaddr_un* addr) { +static inline socklen_t sockaddrlen(sockaddr_u* addr) { if (addr->sa.sa_family == AF_INET) { return sizeof(struct sockaddr_in); } else if (addr->sa.sa_family == AF_INET6) { return sizeof(struct sockaddr_in6); } - return sizeof(sockaddr_un); + return sizeof(sockaddr_u); } -static inline const char* sockaddr_ip(sockaddr_un* addr, char *ip, int len) { +static inline const char* sockaddr_ip(sockaddr_u* addr, char *ip, int len) { if (addr->sa.sa_family == AF_INET) { return inet_ntop(AF_INET, &addr->sin.sin_addr, ip, len); } @@ -77,7 +77,7 @@ static inline const char* sockaddr_ip(sockaddr_un* addr, char *ip, int len) { return ip; } -static inline uint16_t sockaddr_port(sockaddr_un* addr) { +static inline uint16_t sockaddr_port(sockaddr_u* addr) { uint16_t port = 0; if (addr->sa.sa_family == AF_INET) { port = htons(addr->sin.sin_port); @@ -88,7 +88,7 @@ static inline uint16_t sockaddr_port(sockaddr_un* addr) { return port; } -static inline void sockaddr_set_port(sockaddr_un* addr, int port) { +static inline void sockaddr_set_port(sockaddr_u* addr, int port) { if (addr->sa.sa_family == AF_INET) { addr->sin.sin_port = ntohs(port); } @@ -100,12 +100,12 @@ static inline void sockaddr_set_port(sockaddr_un* addr, int port) { //#define INET_ADDRSTRLEN 16 //#define INET6_ADDRSTRLEN 46 #define SOCKADDR_STRLEN 64 // ipv4:port | [ipv6]:port -#define SOCKADDR_STR(addr, buf) sockaddr_str((sockaddr_un*)addr, buf, sizeof(buf)) -// NOTE: typeof(addr)=[sockaddr*, sockaddr_in*, sockaddr_in6*, sockaddr_un*] +#define SOCKADDR_STR(addr, buf) sockaddr_str((sockaddr_u*)addr, buf, sizeof(buf)) +// NOTE: typeof(addr)=[sockaddr*, sockaddr_in*, sockaddr_in6*, sockaddr_u*] // char buf[SOCKADDR_STRLEN] = {0}; // SOCKADDR_STR(addr, buf); -static inline const char* sockaddr_str(sockaddr_un* addr, char* buf, int len) { +static inline const char* sockaddr_str(sockaddr_u* addr, char* buf, int len) { char ip[SOCKADDR_STRLEN] = {0}; uint16_t port = 0; if (addr->sa.sa_family == AF_INET) { @@ -121,13 +121,13 @@ static inline const char* sockaddr_str(sockaddr_un* addr, char* buf, int len) { return buf; } -static inline void sockaddr_print(sockaddr_un* addr) { +static inline void sockaddr_print(sockaddr_u* addr) { char buf[SOCKADDR_STRLEN] = {0}; sockaddr_str(addr, buf, sizeof(buf)); puts(buf); } -static inline int sockaddr_assign(sockaddr_un* addr, const char* host, int port) { +static inline int sockaddr_assign(sockaddr_u* addr, const char* host, int port) { if (host) { int ret = Resolver(host, addr); if (ret != 0) return ret; diff --git a/base/htime.c b/base/htime.c index 797228384..8b94c757e 100644 --- a/base/htime.c +++ b/base/htime.c @@ -41,6 +41,7 @@ unsigned int gettick() { #endif } +#ifndef OS_SOLARIS unsigned long long gethrtime() { #ifdef OS_WIN static LONGLONG s_freq = 0; @@ -65,6 +66,7 @@ unsigned long long gethrtime() { return tv.tv_sec*(unsigned long long)1000000 + tv.tv_usec; #endif } +#endif datetime_t datetime_now() { datetime_t dt; diff --git a/base/htime.h b/base/htime.h index 742682d6b..34ea206f1 100644 --- a/base/htime.h +++ b/base/htime.h @@ -72,8 +72,11 @@ static inline unsigned long long timestamp_ms() { void msleep(unsigned int ms); // ms unsigned int gettick(); + +#ifndef OS_SOLARIS // Solaris has built-in gethrtime(). // us unsigned long long gethrtime(); +#endif datetime_t datetime_now(); time_t datetime_mktime(datetime_t* dt); diff --git a/event/hevent.c b/event/hevent.c index 05393540c..698e412f1 100644 --- a/event/hevent.c +++ b/event/hevent.c @@ -68,14 +68,14 @@ void hio_set_type(hio_t* io, hio_type_e type) { void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen) { if (io->localaddr == NULL) { - SAFE_ALLOC(io->localaddr, sizeof(sockaddr_un)); + SAFE_ALLOC(io->localaddr, sizeof(sockaddr_u)); } memcpy(io->localaddr, addr, addrlen); } void hio_set_peeraddr (hio_t* io, struct sockaddr* addr, int addrlen) { if (io->peeraddr == NULL) { - SAFE_ALLOC(io->peeraddr, sizeof(sockaddr_un)); + SAFE_ALLOC(io->peeraddr, sizeof(sockaddr_u)); } memcpy(io->peeraddr, addr, addrlen); } diff --git a/event/hloop.c b/event/hloop.c index 37285cf21..6129cfb05 100644 --- a/event/hloop.c +++ b/event/hloop.c @@ -473,12 +473,12 @@ static void hio_socket_init(hio_t* io) { nonblocking(io->fd); // fill io->localaddr io->peeraddr if (io->localaddr == NULL) { - SAFE_ALLOC(io->localaddr, sizeof(sockaddr_un)); + SAFE_ALLOC(io->localaddr, sizeof(sockaddr_u)); } if (io->peeraddr == NULL) { - SAFE_ALLOC(io->peeraddr, sizeof(sockaddr_un)); + SAFE_ALLOC(io->peeraddr, sizeof(sockaddr_u)); } - socklen_t addrlen = sizeof(sockaddr_un); + socklen_t addrlen = sizeof(sockaddr_u); int ret = getsockname(io->fd, io->localaddr, &addrlen); printd("getsockname fd=%d ret=%d errno=%d\n", io->fd, ret, socket_errno()); // NOTE: @@ -487,7 +487,7 @@ static void hio_socket_init(hio_t* io) { // tcp_client/udp_client peeraddr set by hio_setpeeraddr if (io->io_type == HIO_TYPE_TCP || io->io_type == HIO_TYPE_SSL) { // tcp acceptfd - addrlen = sizeof(sockaddr_un); + addrlen = sizeof(sockaddr_u); ret = getpeername(io->fd, io->peeraddr, &addrlen); printd("getpeername fd=%d ret=%d errno=%d\n", io->fd, ret, socket_errno()); } @@ -695,7 +695,7 @@ hio_t* create_tcp_server (hloop_t* loop, const char* host, int port, haccept_cb } hio_t* create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb) { - sockaddr_un peeraddr; + sockaddr_u peeraddr; socklen_t addrlen = sizeof(peeraddr); memset(&peeraddr, 0, addrlen); int ret = sockaddr_assign(&peeraddr, host, port); @@ -727,7 +727,7 @@ hio_t* create_udp_server(hloop_t* loop, const char* host, int port) { // @client: Resolver -> socket -> hio_get -> hio_set_peeraddr hio_t* create_udp_client(hloop_t* loop, const char* host, int port) { - sockaddr_un peeraddr; + sockaddr_u peeraddr; socklen_t addrlen = sizeof(peeraddr); memset(&peeraddr, 0, addrlen); int ret = sockaddr_assign(&peeraddr, host, port); diff --git a/event/nio.c b/event/nio.c index 40fe823cf..b699f7547 100644 --- a/event/nio.c +++ b/event/nio.c @@ -45,7 +45,7 @@ static void nio_accept(hio_t* io) { //printd("nio_accept listenfd=%d\n", io->fd); socklen_t addrlen; accept: - addrlen = sizeof(sockaddr_un); + addrlen = sizeof(sockaddr_u); int connfd = accept(io->fd, io->peeraddr, &addrlen); hio_t* connio = NULL; if (connfd < 0) { @@ -59,7 +59,7 @@ static void nio_accept(hio_t* io) { goto accept_error; } } - addrlen = sizeof(sockaddr_un); + addrlen = sizeof(sockaddr_u); getsockname(connfd, io->localaddr, &addrlen); connio = hio_get(io->loop, connfd); // NOTE: inherit from listenio @@ -105,7 +105,7 @@ static void nio_accept(hio_t* io) { static void nio_connect(hio_t* io) { //printd("nio_connect connfd=%d\n", io->fd); - socklen_t addrlen = sizeof(sockaddr_un); + socklen_t addrlen = sizeof(sockaddr_u); int ret = getpeername(io->fd, io->peeraddr, &addrlen); if (ret < 0) { io->error = socket_errno(); @@ -113,7 +113,7 @@ static void nio_connect(hio_t* io) { goto connect_failed; } else { - addrlen = sizeof(sockaddr_un); + addrlen = sizeof(sockaddr_u); getsockname(io->fd, io->localaddr, &addrlen); /* char localaddrstr[SOCKADDR_STRLEN] = {0}; @@ -176,7 +176,7 @@ static void nio_read(hio_t* io) { case HIO_TYPE_UDP: case HIO_TYPE_IP: { - socklen_t addrlen = sizeof(sockaddr_un); + socklen_t addrlen = sizeof(sockaddr_u); nread = recvfrom(io->fd, buf, len, 0, io->peeraddr, &addrlen); } break; @@ -239,7 +239,7 @@ static void nio_write(hio_t* io) { break; case HIO_TYPE_UDP: case HIO_TYPE_IP: - nwrite = sendto(io->fd, buf, len, 0, io->peeraddr, sizeof(sockaddr_un)); + nwrite = sendto(io->fd, buf, len, 0, io->peeraddr, sizeof(sockaddr_u)); break; default: nwrite = write(io->fd, buf, len); @@ -324,7 +324,7 @@ static void connect_timeout_cb(htimer_t* timer) { } int hio_connect(hio_t* io) { - int ret = connect(io->fd, io->peeraddr, sizeof(sockaddr_un)); + int ret = connect(io->fd, io->peeraddr, sizeof(sockaddr_u)); #ifdef OS_WIN if (ret < 0 && socket_errno() != WSAEWOULDBLOCK) { #else @@ -370,7 +370,7 @@ int hio_write (hio_t* io, const void* buf, size_t len) { break; case HIO_TYPE_UDP: case HIO_TYPE_IP: - nwrite = sendto(io->fd, buf, len, 0, io->peeraddr, sizeof(sockaddr_un)); + nwrite = sendto(io->fd, buf, len, 0, io->peeraddr, sizeof(sockaddr_u)); break; default: nwrite = write(io->fd, buf, len); diff --git a/http/server/HttpServer.cpp b/http/server/HttpServer.cpp index 26e26b885..7e4cfc81f 100644 --- a/http/server/HttpServer.cpp +++ b/http/server/HttpServer.cpp @@ -230,8 +230,8 @@ static void on_accept(hio_t* io) { HttpHandler* handler = new HttpHandler; handler->service = (HttpService*)hevent_userdata(io); handler->files = &s_filecache; - sockaddr_ip((sockaddr_un*)hio_peeraddr(io), handler->ip, sizeof(handler->ip)); - handler->port = sockaddr_port((sockaddr_un*)hio_peeraddr(io)); + sockaddr_ip((sockaddr_u*)hio_peeraddr(io), handler->ip, sizeof(handler->ip)); + handler->port = sockaddr_port((sockaddr_u*)hio_peeraddr(io)); handler->io = io; hevent_set_userdata(io, handler); } diff --git a/protocol/icmp.c b/protocol/icmp.c index 8ba037916..ee8467248 100644 --- a/protocol/icmp.c +++ b/protocol/icmp.c @@ -27,7 +27,7 @@ int ping(const char* host, int cnt) { //min_rtt = MIN(rtt, min_rtt); //max_rtt = MAX(rtt, max_rtt); // gethostbyname -> socket -> setsockopt -> sendto -> recvfrom -> closesocket - sockaddr_un peeraddr; + sockaddr_u peeraddr; socklen_t addrlen = sizeof(peeraddr); memset(&peeraddr, 0, addrlen); int ret = Resolver(host, &peeraddr); From 6d0aac52037fefcb41bb93eaf79693a5b4838fb3 Mon Sep 17 00:00:00 2001 From: CismonX Date: Tue, 5 May 2020 10:59:56 +0800 Subject: [PATCH 3/3] Add evport support. --- event/evport.c | 113 +++++++++++++++++++++++++++++++++++++++++++++- event/iowatcher.h | 2 + readme_cn.md | 1 + 3 files changed, 115 insertions(+), 1 deletion(-) diff --git a/event/evport.c b/event/evport.c index cc4030494..2913412d3 100644 --- a/event/evport.c +++ b/event/evport.c @@ -2,25 +2,136 @@ #ifdef EVENT_PORT +#include "hplatform.h" +#include "hdef.h" +#include "hevent.h" + #include +#define EVENTS_INIT_SIZE 64 + +typedef struct evport_ctx_s { + int port; + int capacity; + int nevents; + port_event_t* events; +} evport_ctx_t; + +static void evport_ctx_resize(evport_ctx_t* evport_ctx, int size) { + int bytes = sizeof(port_event_t) * size; + int oldbytes = sizeof(port_event_t) * evport_ctx->capacity; + evport_ctx->events = (port_event_t*)safe_realloc(evport_ctx->events, bytes, oldbytes); + evport_ctx->capacity = size; +} + int iowatcher_init(hloop_t* loop) { + if (loop->iowatcher) return 0; + evport_ctx_t* evport_ctx; + SAFE_ALLOC_SIZEOF(evport_ctx); + evport_ctx->port = port_create(); + evport_ctx->capacity = EVENTS_INIT_SIZE; + evport_ctx->nevents = 0; + int bytes = sizeof(port_event_t) * evport_ctx->capacity; + SAFE_ALLOC(evport_ctx->events, bytes); + loop->iowatcher = evport_ctx; return 0; } int iowatcher_cleanup(hloop_t* loop) { + if (loop->iowatcher == NULL) return 0; + evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher; + close(evport_ctx->port); + SAFE_FREE(evport_ctx->events); + SAFE_FREE(loop->iowatcher); return 0; } int iowatcher_add_event(hloop_t* loop, int fd, int events) { + if (loop->iowatcher == NULL) { + iowatcher_init(loop); + } + evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher; + hio_t* io = loop->ios.ptr[fd]; + + int evport_events = 0; + if (io->events & HV_READ) { + evport_events |= POLLIN; + } + if (io->events & HV_WRITE) { + evport_events |= POLLOUT; + } + if (events & HV_READ) { + evport_events |= POLLIN; + } + if (events & HV_WRITE) { + evport_events |= POLLOUT; + } + port_associate(evport_ctx->port, PORT_SOURCE_FD, fd, evport_events, NULL); + if (io->events == 0) { + if (evport_ctx->nevents == evport_ctx->capacity) { + evport_ctx_resize(evport_ctx, evport_ctx->capacity * 2); + } + ++evport_ctx->nevents; + } return 0; } int iowatcher_del_event(hloop_t* loop, int fd, int events) { + evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher; + if (evport_ctx == NULL) return 0; + hio_t* io = loop->ios.ptr[fd]; + + int evport_events = 0; + if (io->events & HV_READ) { + evport_events |= POLLIN; + } + if (io->events & HV_WRITE) { + evport_events |= POLLOUT; + } + if (events & HV_READ) { + evport_events &= ~POLLIN; + } + if (events & HV_WRITE) { + evport_events &= ~POLLOUT; + } + if (evport_events == 0) { + port_dissociate(evport_ctx->port, PORT_SOURCE_FD, fd); + --evport_ctx->nevents; + } else { + port_associate(evport_ctx->port, PORT_SOURCE_FD, fd, evport_events, NULL); + } return 0; } int iowatcher_poll_events(hloop_t* loop, int timeout) { - return 0; + evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher; + if (evport_ctx == NULL) return 0; + struct timespec ts, *tp; + if (timeout == INFINITE) { + tp = NULL; + } else { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000; + tp = &ts; + } + unsigned nevents = 1; + port_getn(evport_ctx->port, evport_ctx->events, evport_ctx->capacity, &nevents, tp); + for (int i = 0; i < nevents; ++i) { + int fd = evport_ctx->events[i].portev_object; + int revents = evport_ctx->events[i].portev_events; + hio_t* io = loop->ios.ptr[fd]; + if (io) { + if (revents & POLLIN) { + io->revents |= HV_READ; + } + if (revents & POLLOUT) { + io->revents |= HV_WRITE; + } + EVENT_PENDING(io); + } + // Upon retrieval, the event object is no longer associated with the port. + iowatcher_add_event(loop, fd, io->events); + } + return nevents; } #endif diff --git a/event/iowatcher.h b/event/iowatcher.h index 59afd590d..5ac3fec15 100644 --- a/event/iowatcher.h +++ b/event/iowatcher.h @@ -20,6 +20,8 @@ #define EVENT_KQUEUE #elif defined(OS_BSD) #define EVENT_KQUEUE +#elif defined(OS_SOLARIS) +#define EVENT_PORT #else #define EVENT_SELECT #endif diff --git a/readme_cn.md b/readme_cn.md index 9c5a5525a..a5c1fa24f 100644 --- a/readme_cn.md +++ b/readme_cn.md @@ -291,6 +291,7 @@ sudo echo-servers/benchmark.sh - EVENT_POLL - EVENT_EPOLL (linux only) - EVENT_KQUEUE (mac/bsd) +- EVENT_PORT (solaris) - EVENT_IOCP (windows only) ### http