Browse Source

Merge pull request #4 from CismonX/solaris

Add support for Oracle Solaris
ithewei 5 years ago
parent
commit
81a305d299
15 changed files with 157 additions and 37 deletions
  1. 1 1
      README.md
  2. 0 1
      base/hmutex.h
  3. 2 0
      base/hplatform.h
  4. 3 3
      base/hsocket.c
  5. 12 12
      base/hsocket.h
  6. 2 0
      base/htime.c
  7. 3 0
      base/htime.h
  8. 112 1
      event/evport.c
  9. 2 2
      event/hevent.c
  10. 6 6
      event/hloop.c
  11. 2 0
      event/iowatcher.h
  12. 8 8
      event/nio.c
  13. 2 2
      http/server/HttpServer.cpp
  14. 1 1
      protocol/icmp.c
  15. 1 0
      readme_cn.md

+ 1 - 1
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

+ 0 - 1
base/hmutex.h

@@ -193,7 +193,6 @@ END_EXTERN_C
 #ifdef __cplusplus
 #include <mutex>
 #include <condition_variable>
-using std::mutex;
 // NOTE: test std::timed_mutex incorrect in some platforms, use htimed_mutex_t
 // using std::timed_mutex;
 using std::condition_variable;

+ 2 - 0
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

+ 3 - 3
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 @@ error:
 
 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);

+ 12 - 12
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;

+ 2 - 0
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;

+ 3 - 0
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);

+ 112 - 1
event/evport.c

@@ -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

+ 2 - 2
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);
 }

+ 6 - 6
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);

+ 2 - 0
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

+ 8 - 8
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 @@ accept:
             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 @@ accept_error:
 
 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 @@ read:
     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 @@ write:
         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 @@ try_write:
             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);

+ 2 - 2
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);
 }

+ 1 - 1
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);

+ 1 - 0
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