Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion base/hmutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ END_EXTERN_C
#ifdef __cplusplus
#include <mutex>
#include <condition_variable>
using std::mutex;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This global scope using-declaration conflicts with another mutex typedef in <sys/mutex.h> on Solaris. Removed as it's not used anywhere in the project.

// NOTE: test std::timed_mutex incorrect in some platforms, use htimed_mutex_t
// using std::timed_mutex;
using std::condition_variable;
Expand Down
2 changes: 2 additions & 0 deletions base/hplatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions base/hsocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
24 changes: 12 additions & 12 deletions base/hsocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,23 @@ typedef union {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sockaddr_un;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the "un" here means "union", however, in <sys/un.h>, there is a sockaddr_un for Unix domains sockets where "un" means "Unix". On Solaris, <sys/un.h> is included by <sys/socket.h>, resulting in compilation error.

This issue also concerns Linux or BSD if libhv's going to support Unix domain sockets in the future. This conflict is not specific to Solaris, for sockaddr_un conforms to IEEE Std 1003.1-2008, and platforms like Linux and BSD also use that name.

Renaming to sockaddr_u is recommended.

} 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);
}
Expand All @@ -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);
Expand All @@ -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);
}
Expand All @@ -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) {
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions base/htime.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ unsigned int gettick() {
#endif
}

#ifndef OS_SOLARIS
unsigned long long gethrtime() {
#ifdef OS_WIN
static LONGLONG s_freq = 0;
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions base/htime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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().
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solaris has built-in gethrtime() in <sys/time.h> for high resolution time support, and also returns nanoseconds. Use that instead.

// us
unsigned long long gethrtime();
#endif

datetime_t datetime_now();
time_t datetime_mktime(datetime_t* dt);
Expand Down
113 changes: 112 additions & 1 deletion event/evport.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,136 @@

#ifdef EVENT_PORT

#include "hplatform.h"
#include "hdef.h"
#include "hevent.h"

#include <port.h>

#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
4 changes: 2 additions & 2 deletions event/hevent.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
12 changes: 6 additions & 6 deletions event/hloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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());
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions event/iowatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading