ithewei 6 år sedan
förälder
incheckning
bb645744e0
41 ändrade filer med 872 tillägg och 311 borttagningar
  1. 9 11
      Makefile
  2. 7 1
      Makefile.in
  3. 3 0
      README.md
  4. 6 8
      base/array.h
  5. 114 0
      base/hbase.c
  6. 77 0
      base/hbase.h
  7. 5 9
      base/hbuf.h
  8. 1 19
      base/hdef.h
  9. 0 6
      base/hfile.h
  10. 40 14
      base/hplatform.h
  11. 29 14
      base/hsocket.c
  12. 72 5
      base/hsocket.h
  13. 0 39
      base/hstring.cpp
  14. 3 14
      base/hstring.h
  15. 1 1
      base/hthread.h
  16. 1 1
      base/htime.c
  17. 16 1
      base/htime.h
  18. 3 2
      base/hvar.h
  19. 10 8
      base/netinet.h
  20. 6 8
      base/queue.h
  21. 128 0
      configure
  22. 2 1
      event/epoll.c
  23. 44 20
      event/hloop.c
  24. 2 1
      event/iocp.c
  25. 6 7
      event/kqueue.c
  26. 29 37
      event/nio.c
  27. 31 44
      event/overlapio.c
  28. 2 1
      event/poll.c
  29. 2 1
      event/select.c
  30. 9 9
      examples/client.cpp
  31. 5 2
      examples/loop.c
  32. 6 9
      examples/server.cpp
  33. 33 0
      hconfig.h
  34. 1 0
      http/HttpRequest.h
  35. 25 18
      http/server/http_server.cpp
  36. 3 0
      http/server/http_server.h
  37. 1 0
      scripts/cmake.sh
  38. 19 0
      scripts/coredump.sh
  39. 14 0
      scripts/create_pro.sh
  40. 7 0
      scripts/my.cmake
  41. 100 0
      scripts/toolchain.sh

+ 9 - 11
Makefile

@@ -18,28 +18,26 @@ test: prepare
 
 ping:
 	-rm base/hsocket.o
-	$(MAKEF) TARGET=$@ SRCDIRS="" SRCS="examples/ping.c base/hsocket.c base/htime.c base/RAII.cpp" INCDIRS="base" DEFINES="PRINT_DEBUG"
+	$(MAKEF) TARGET=$@ SRCDIRS="" SRCS="examples/ping.c base/hsocket.c base/htime.c base/RAII.cpp" INCDIRS=". base" DEFINES="PRINT_DEBUG"
 
 loop: prepare
 	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
-	cp examples/loop.c $(TMPDIR)/loop.c
+	cp examples/loop.c $(TMPDIR)
 	$(MAKEF) TARGET=$@ SRCDIRS=". base event $(TMPDIR)"
 
 client: prepare
-	-rm $(TMPDIR)/*.o $(TMPDIR)/*.c $(TMPDIR)/*.cpp
-	cp examples/client.cpp $(TMPDIR)/client.cpp
+	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
+	cp examples/client.cpp $(TMPDIR)
 	$(MAKEF) TARGET=$@ SRCDIRS=". base event $(TMPDIR)"
 
 server: prepare
-	-rm $(TMPDIR)/*.o $(TMPDIR)/*.c $(TMPDIR)/*.cpp
-	cp examples/server.cpp $(TMPDIR)/server.cpp
+	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
+	cp examples/server.cpp $(TMPDIR)
 	$(MAKEF) TARGET=$@ SRCDIRS=". base event $(TMPDIR)"
 
 httpd: prepare
-	-rm $(TMPDIR)/*.o $(TMPDIR)/*.c $(TMPDIR)/*.cpp
-	cp examples/httpd.cpp $(TMPDIR)/httpd.cpp
-	cp examples/httpd_conf.h $(TMPDIR)/httpd_conf.h
-	cp examples/http_api_test.h $(TMPDIR)/http_api_test.h
+	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
+	cp examples/httpd.cpp examples/httpd_conf.h examples/http_api_test.h $(TMPDIR)
 	$(MAKEF) TARGET=$@ SRCDIRS=". base utils event http http/server $(TMPDIR)"
 
 webbench:
@@ -48,7 +46,7 @@ webbench:
 # curl
 CURL_SRCDIRS := http http/client
 CURL_INCDIRS += base utils http http/client
-CURL_SRCS    += examples/curl.cpp base/hstring.cpp
+CURL_SRCS    += examples/curl.cpp base/hstring.cpp base/hbase.c
 curl:
 	$(MAKEF) TARGET=$@ SRCDIRS="$(CURL_SRCDIRS)" INCDIRS="$(CURL_INCDIRS)" SRCS="$(CURL_SRCS)" DEFINES="CURL_STATICLIB" LIBS="curl"
 

+ 7 - 1
Makefile.in

@@ -62,7 +62,7 @@ endif
 ifeq ($(BUILD_TYPE), DEBUG)
 	DEFAULT_CFLAGS = -g
 endif
-DEFAULT_CFLAGS += -Wall -O3 -fPIC
+DEFAULT_CFLAGS += -Wall -O3 -fPIC -fvisibility=hidden
 ifndef CFLAGS
 CFLAGS := $(DEFAULT_CFLAGS) -std=c99 $(MAKE_CFLAGS)
 endif
@@ -98,9 +98,15 @@ ifeq ($(TARGET_TYPE), SHARED)
 	CPPFLAGS += -DDLL_EXPORTS
 endif
 endif
+
+ifeq ($(TARGET_TYPE), STATIC)
+	CPPFLAGS += -DBUILD_STATIC_LIB
+endif
+
 ifeq ($(BUILD_TYPE), DEBUG)
 	CPPFLAGS += -DDEBUG
 endif
+
 CPPFLAGS += $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(addprefix -I, $(INCDIRS))
 CPPFLAGS += $(addprefix -I, $(SRCDIRS))

+ 3 - 0
README.md

@@ -65,3 +65,6 @@ hw 是一套跨平台c++工具集,类名以H开头
 - make httpd: http服务(包含web service和api service)
 - make curl: 基于libcurl封装http客户端
 - make webbench: http服务压力测试程序
+
+### compile with print debug info
+- make all DEFINES=PRINT_DEBUG

+ 6 - 8
base/array.h

@@ -14,6 +14,8 @@
 #include <stdlib.h> // for malloc,realloc,free
 #include <string.h> // for memset,memmove
 
+#include "hbase.h"
+
 // #include <vector>
 // typedef std::vector<type> atype;
 #define ARRAY_DECL(type, atype) \
@@ -59,27 +61,23 @@ static inline type* atype##_back(atype* p) {\
 static inline void atype##_init(atype* p, int maxsize) {\
     p->size = 0;\
     p->maxsize = maxsize;\
-    size_t bytes = sizeof(type) * maxsize;\
-    p->ptr = (type*)malloc(bytes);\
-    memset(p->ptr, 0, bytes);\
+    SAFE_ALLOC(p->ptr, sizeof(type) * maxsize);\
 }\
+\
 static inline void atype##_clear(atype* p) {\
     p->size = 0;\
     memset(p->ptr, 0, sizeof(type) * p->maxsize);\
 }\
 \
 static inline void atype##_cleanup(atype* p) {\
-    if (p->ptr) {\
-        free(p->ptr);\
-        p->ptr = NULL;\
-    }\
+    SAFE_FREE(p->ptr);\
     p->size = p->maxsize = 0;\
 }\
 \
 static inline void atype##_resize(atype* p, int maxsize) {\
     p->maxsize = maxsize;\
     int bytes = sizeof(type) * maxsize;\
-    p->ptr = (type*)realloc(p->ptr, bytes);\
+    p->ptr = (type*)safe_realloc(p->ptr, bytes);\
 }\
 \
 static inline void atype##_double_resize(atype* p) {\

+ 114 - 0
base/hbase.c

@@ -0,0 +1,114 @@
+#include "hbase.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+unsigned int g_alloc_cnt = 0;
+unsigned int g_free_cnt = 0;
+
+void* safe_malloc(size_t size) {
+    ++g_alloc_cnt;
+    void* ptr = malloc(size);
+    if (!ptr) {
+        fprintf(stderr, "malloc failed!\n");
+        exit(-1);
+    }
+    return ptr;
+}
+
+void* safe_realloc(void* oldptr, size_t size) {
+    ++g_alloc_cnt;
+    ++g_free_cnt;
+    void* ptr = realloc(oldptr, size);
+    if (!ptr) {
+        fprintf(stderr, "realloc failed!\n");
+        exit(-1);
+    }
+    if (!ptr) {
+
+    }
+    return ptr;
+}
+
+void* safe_calloc(size_t nmemb, size_t size) {
+    ++g_alloc_cnt;
+    void* ptr =  calloc(nmemb, size);
+    if (!ptr) {
+        fprintf(stderr, "calloc failed!\n");
+        exit(-1);
+    }
+    return ptr;
+}
+
+void* safe_zalloc(size_t size) {
+    ++g_alloc_cnt;
+    void* ptr = malloc(size);
+    if (!ptr) {
+        fprintf(stderr, "malloc failed!\n");
+        exit(-1);
+    }
+    memset(ptr, 0, size);
+    return ptr;
+}
+
+char* strupper(char* str) {
+    char* p = str;
+    while (*p != '\0') {
+        if (*p >= 'a' && *p <= 'z') {
+            *p &= ~0x20;
+        }
+        ++p;
+    }
+    return str;
+}
+
+char* strlower(char* str) {
+    char* p = str;
+    while (*p != '\0') {
+        if (*p >= 'A' && *p <= 'Z') {
+            *p |= 0x20;
+        }
+        ++p;
+    }
+    return str;
+}
+
+char* strreverse(char* str) {
+    if (str == NULL) return NULL;
+    char* b = str;
+    char* e = str;
+    while(*e) {++e;}
+    --e;
+    char tmp;
+    while (e > b) {
+        tmp = *e;
+        *e = *b;
+        *b = tmp;
+        --e;
+        ++b;
+    }
+    return str;
+}
+
+// n = sizeof(dest_buf)
+char* safe_strncpy(char* dest, const char* src, size_t n) {
+    assert(dest != NULL && src != NULL);
+    char* ret = dest;
+    while (*src != '\0' && --n > 0) {
+        *dest++ = *src++;
+    }
+    return ret;
+}
+
+// n = sizeof(dest_buf)
+char* safe_strncat(char* dest, const char* src, size_t n) {
+    assert(dest != NULL && src != NULL);
+    char* ret = dest;
+    while (*dest) {++dest;--n;}
+    while (*src != '\0' && --n > 0) {
+        *dest++ = *src++;
+    }
+    return ret;
+}
+

+ 77 - 0
base/hbase.h

@@ -0,0 +1,77 @@
+#ifndef HW_BASE_H_
+#define HW_BASE_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+    #define strcasecmp stricmp
+    #define strncasecmp strnicmp
+#else
+    #include <strings.h>
+    #define stricmp     strcasecmp
+    #define strnicmp    strncasecmp
+#endif
+
+#ifdef PRINT_DEBUG
+#define printd printf
+#else
+#define printd(...)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//---------------------safe alloc/free---------------------------
+extern unsigned int g_alloc_cnt;
+extern unsigned int g_free_cnt;
+
+void* safe_malloc(size_t size);
+void* safe_realloc(void* oldptr, size_t size);
+void* safe_calloc(size_t nmemb, size_t size);
+void* safe_zalloc(size_t size);
+
+#define SAFE_ALLOC(ptr, size)\
+    do {\
+        void** pptr = (void**)&(ptr);\
+        *pptr = safe_zalloc(size);\
+        printd("alloc(%p, size=%lu)\tat [%s:%d:%s]\n", ptr, size, __FILE__, __LINE__, __FUNCTION__);\
+    } while(0)
+
+#define SAFE_ALLOC_SIZEOF(ptr)  SAFE_ALLOC(ptr, sizeof(*(ptr)))
+
+#define SAFE_FREE(ptr)\
+    do {\
+        if (ptr) {\
+            printd("free( %p )\tat [%s:%d:%s]\n", ptr, __FILE__, __LINE__, __FUNCTION__);\
+            free(ptr);\
+            ptr = NULL;\
+            ++g_free_cnt;\
+        }\
+    } while(0)
+
+static inline void memcheck() {
+    printf("Memcheck => alloc:%u free:%u\n", g_alloc_cnt, g_free_cnt);
+}
+
+#define MEMCHECK    atexit(memcheck);
+
+//-----------------------------safe string-----------------------
+char* strupper(char* str);
+char* strlower(char* str);
+char* strreverse(char* str);
+
+// strncpy n = sizeof(dest_buf)-1
+// safe_strncpy n = sizeof(dest_buf)
+char* safe_strncpy(char* dest, const char* src, size_t n);
+
+// strncat n = sizeof(dest_buf)-1-strlen(dest)
+// safe_strncpy n = sizeof(dest_buf)
+char* safe_strncat(char* dest, const char* src, size_t n);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // HW_BASE_H_

+ 5 - 9
base/hbuf.h

@@ -65,10 +65,7 @@ public:
 
     void cleanup() {
         if (cleanup_) {
-            if (base) {
-                free(base);
-                base = NULL;
-            }
+            SAFE_FREE(base);
             len = 0;
             cleanup_ = false;
         }
@@ -78,11 +75,10 @@ public:
         if (cap == len) return;
 
         if (base == NULL) {
-            base = (char*)malloc(cap);
-            memset(base, 0, cap);
+            SAFE_ALLOC(base, cap);
         }
         else {
-            base = (char*)realloc(base, cap);
+            base = (char*)safe_realloc(base, cap);
         }
         len = cap;
         cleanup_ = true;
@@ -115,7 +111,7 @@ public:
     void push_front(void* ptr, size_t len) {
         if (len > this->len - _size) {
             this->len = MAX(this->len, len)*2;
-            base = (char*)realloc(base, this->len);
+            base = (char*)safe_realloc(base, this->len);
         }
 
         if (_offset < len) {
@@ -132,7 +128,7 @@ public:
     void push_back(void* ptr, size_t len) {
         if (len > this->len - _size) {
             this->len = MAX(this->len, len)*2;
-            base = (char*)realloc(base, this->len);
+            base = (char*)safe_realloc(base, this->len);
         }
         else if (len > this->len - _offset - _size) {
             // move => start

+ 1 - 19
base/hdef.h

@@ -2,6 +2,7 @@
 #define HW_DEF_H_
 
 #include "hplatform.h"
+#include "hbase.h"
 
 typedef float               float32;
 typedef double              float64;
@@ -139,19 +140,6 @@ typedef void (*procedure_t)(void* userdata);
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 #endif
 
-#ifndef ARRAY_INIT
-#define ARRAY_INIT(type, p, size)\
-    do {\
-        size_t bytes = sizeof(*(p)) * size;\
-        p = (type*)malloc(bytes);\
-        memset(p, 0, bytes);\
-    } while (0)
-#endif
-
-#ifndef ARRAY_RESIZE
-#define ARRAY_RESIZE(type, p, newsize) do {p = (type*)realloc(p, sizeof(*(p)) * newsize);} while(0)
-#endif
-
 #ifndef SAFE_FREE
 #define SAFE_FREE(p)    do {if (p) {free(p); (p) = NULL;}} while(0)
 #endif
@@ -243,12 +231,6 @@ typedef void (*procedure_t)(void* userdata);
 #endif
 #endif
 
-#ifdef PRINT_DEBUG
-#define printd printf
-#else
-#define printd(...)
-#endif
-
 // __cplusplus
 #ifdef __cplusplus
 

+ 0 - 6
base/hfile.h

@@ -1,12 +1,6 @@
 #ifndef HW_FILE_H_
 #define HW_FILE_H_
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
 #include <string>
 
 #include "hdef.h"

+ 40 - 14
base/hplatform.h

@@ -1,6 +1,8 @@
 #ifndef HW_PLATFORM_H_
 #define HW_PLATFORM_H_
 
+#include "hconfig.h"
+
 // OS
 #if defined(WIN64) || defined(_WIN64)
     #define OS_WIN64
@@ -49,6 +51,14 @@
 
 // CC
 // _MSC_VER
+#ifdef _MSC_VER
+#pragma warning (disable: 4100) // unused param
+#pragma warning (disable: 4819) // Unicode
+
+#undef  HAVE_PTHREAD_H
+#define HAVE_PTHREAD_H  0
+#endif
+
 // __MINGW32__
 // __GNUC__
 #ifdef __GNUC__
@@ -58,6 +68,18 @@
 #endif
 // __clang__
 
+#ifndef BUILD_STATIC_LIB
+#ifdef _MSC_VER
+#define EXPORT  __declspec(dllexport)
+#elif defined(__GNUC__)
+#define EXPORT  __attribute__((visibility("default")))
+#else
+#define EXPORT
+#endif
+#else
+#define EXPORT
+#endif
+
 // ARCH
 #if defined(__i386) || defined(__i386__) || defined(_M_IX86)
     #define ARCH_X86
@@ -103,23 +125,21 @@
     #include <direct.h>     // for mkdir,rmdir,chdir,getcwd
     #include <io.h>         // for open,close,read,write,lseek,tell
 
-    #define MKDIR(dir) mkdir(dir)
+    #define MKDIR(dir)      mkdir(dir)
 #else
     #include <unistd.h>
     #include <dirent.h>     // for mkdir,rmdir,chdir,getcwd
     #include <sys/time.h>   // for gettimeofday
 
     // socket
-    #include <sys/types.h>
     #include <sys/socket.h>
     #include <arpa/inet.h>
     #include <netinet/in.h>
     #include <netinet/tcp.h>
     #include <netinet/udp.h>
-    #include <fcntl.h>
     #include <netdb.h>  // for gethostbyname
 
-    #define MKDIR(dir) mkdir(dir, 0777)
+    #define MKDIR(dir)      mkdir(dir, 0777)
 #endif
 
 // ANSI C
@@ -137,8 +157,13 @@
 #include <errno.h>
 #include <signal.h>
 
-// c99
-#if defined(_MSC_VER) && _MSC_VER < 1700
+#if HAVE_STDBOOL_H
+#include <stdbool.h>
+#endif
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif defined(_MSC_VER) && _MSC_VER < 1700
 typedef __int8              int8_t;
 typedef __int16             int16_t;
 typedef __int32             int32_t;
@@ -147,20 +172,21 @@ typedef unsigned __int8     uint8_t;
 typedef unsigned __int16    uint16_t;
 typedef unsigned __int32    uint32_t;
 typedef unsigned __int64    uint64_t;
-#else
-#include <stdbool.h>
-#include <stdint.h>
 #endif
 
-// POSIX C
+#ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
+#endif
+
+#if HAVE_SYS_STAT_H
 #include <sys/stat.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#endif
 
-#ifdef _MSC_VER
-#pragma warning (disable: 4100) // unused param
-#pragma warning (disable: 4819) // Unicode
-#else
+#ifdef HAVE_PTHREAD_H
 #include <pthread.h>
 #endif
 

+ 29 - 14
base/hsocket.c

@@ -2,12 +2,27 @@
 #include "htime.h"
 #include "netinet.h"
 
+char *socket_strerror(int err) {
+#ifdef OS_WIN
+    static char buffer[128];
+
+    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+        FORMAT_MESSAGE_IGNORE_INSERTS |
+        FORMAT_MESSAGE_MAX_WIDTH_MASK,
+        0, err, 0, buffer, sizeof(buffer), NULL);
+
+    return buffer;
+#else
+    return strerror(err);
+#endif
+}
+
 int Listen(int port) {
     // socket -> setsockopt -> bind -> listen
     int listenfd = socket(AF_INET, SOCK_STREAM, 0);
     if (listenfd < 0) {
         perror("socket");
-        return -sockerrno;
+        return -socket_errno();
     }
     struct sockaddr_in localaddr;
     socklen_t addrlen = sizeof(localaddr);
@@ -32,7 +47,7 @@ int Listen(int port) {
     return listenfd;
 error:
     closesocket(listenfd);
-    return sockerrno == 0 ? -1 : -sockerrno;
+    return socket_errno() > 0 ? -socket_errno() : -1;
 }
 
 int Connect(const char* host, int port, int nonblock) {
@@ -53,16 +68,16 @@ int Connect(const char* host, int port, int nonblock) {
     int connfd = socket(AF_INET, SOCK_STREAM, 0);
     if (connfd < 0) {
         perror("socket");
-        return -sockerrno;
+        return -socket_errno();
     }
     if (nonblock) {
         nonblocking(connfd);
     }
     int ret = connect(connfd, (struct sockaddr*)&peeraddr, addrlen);
 #ifdef OS_WIN
-    if (ret < 0 && sockerrno != WSAEWOULDBLOCK) {
+    if (ret < 0 && socket_errno() != WSAEWOULDBLOCK) {
 #else
-    if (ret < 0 && sockerrno != EINPROGRESS) {
+    if (ret < 0 && socket_errno() != EINPROGRESS) {
 #endif
         perror("connect");
         goto error;
@@ -70,22 +85,22 @@ int Connect(const char* host, int port, int nonblock) {
     return connfd;
 error:
     closesocket(connfd);
-    return sockerrno == 0 ? -1 : -sockerrno;
+    return socket_errno() > 0 ? -socket_errno() : -1;
 }
 
 #define PING_TIMEOUT    1000 // ms
 int Ping(const char* host, int cnt) {
     static uint16_t seq = 0;
     char ip[64] = {0};
-    uint64_t start_tick, end_tick;
+    uint32_t start_tick, end_tick;
     uint64_t start_hrtime, end_hrtime;
     int timeout = 0;
     int sendbytes = 64;
     char sendbuf[64];
     char recvbuf[128]; // iphdr + icmp = 84 at least
-    struct icmp* icmp_req = (struct icmp*)sendbuf;
-    struct iphdr* ipheader = (struct iphdr*)recvbuf;
-    struct icmp* icmp_res;
+    icmp_t* icmp_req = (icmp_t*)sendbuf;
+    iphdr_t* ipheader = (iphdr_t*)recvbuf;
+    icmp_t* icmp_res;
     // ping stat
     int send_cnt = 0;
     int recv_cnt = 0;
@@ -118,7 +133,7 @@ int Ping(const char* host, int cnt) {
         if (errno == EPERM) {
             fprintf(stderr, "please use root or sudo to create a raw socket.\n");
         }
-        return -sockerrno;
+        return -socket_errno();
     }
 
     timeout = PING_TIMEOUT;
@@ -137,7 +152,7 @@ int Ping(const char* host, int cnt) {
     icmp_req->icmp_type = ICMP_ECHO;
     icmp_req->icmp_code = 0;
     icmp_req->icmp_id = getpid();
-    for (int i = 0; i < sendbytes - sizeof(struct icmphdr); ++i) {
+    for (int i = 0; i < sendbytes - sizeof(icmphdr_t); ++i) {
         icmp_req->icmp_data[i] = i;
     }
     start_tick = gettick();
@@ -166,7 +181,7 @@ int Ping(const char* host, int cnt) {
         int iphdr_len = ipheader->ihl * 4;
         int icmp_len = nrecv - iphdr_len;
         if (icmp_len == sendbytes) {
-            icmp_res = (struct icmp*)(recvbuf + ipheader->ihl*4);
+            icmp_res = (icmp_t*)(recvbuf + ipheader->ihl*4);
             if (icmp_res->icmp_type == ICMP_ECHOREPLY &&
                 icmp_res->icmp_id == getpid() &&
                 icmp_res->icmp_seq == seq) {
@@ -197,5 +212,5 @@ int Ping(const char* host, int cnt) {
     return ok_cnt;
 error:
     closesocket(sockfd);
-    return sockerrno == 0 ? -1 : -sockerrno;
+    return socket_errno() > 0 ? -socket_errno() : -1;
 }

+ 72 - 5
base/hsocket.h

@@ -10,6 +10,15 @@
 
 BEGIN_EXTERN_C
 
+static inline int socket_errno() {
+#ifdef OS_WIN
+    return WSAGetLastError();
+#else
+    return errno;
+#endif
+}
+char* socket_strerror(int err);
+
 // socket -> setsockopt -> bind -> listen
 // @return sockfd
 int Listen(int port);
@@ -34,16 +43,74 @@ static inline int nonblocking(int sockfd) {
     return ioctlsocket(sockfd, FIONBIO, &nb);
 }
 #define poll        WSAPoll
-#define sockerrno   WSAGetLastError()
-#define NIO_EAGAIN  WSAEWOULDBLOCK
+#undef  EAGAIN
+#define EAGAIN      WSAEWOULDBLOCK
+#undef  EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
 #else
 #define blocking(s)     fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK)
 #define nonblocking(s)  fcntl(s, F_SETFL, fcntl(s, F_GETFL) |  O_NONBLOCK)
 #define closesocket close
-#define sockerrno   errno
-#define NIO_EAGAIN  EAGAIN
 #endif
 
+static inline const char* sockaddr_ntop(const struct sockaddr* addr, char *ip, int len) {
+    if (addr->sa_family == AF_INET) {
+        struct sockaddr_in* sin = (struct sockaddr_in*)addr;
+        return inet_ntop(AF_INET, &sin->sin_addr, ip, len);
+    }
+    else if (addr->sa_family == AF_INET6) {
+        struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
+        return inet_ntop(AF_INET6, &sin6->sin6_addr, ip, len);
+    }
+    return ip;
+}
+
+static inline uint16_t sockaddr_htons(const struct sockaddr* addr) {
+    if (addr->sa_family == AF_INET) {
+        struct sockaddr_in* sin = (struct sockaddr_in*)addr;
+        return htons(sin->sin_port);
+    }
+    else if (addr->sa_family == AF_INET6) {
+        struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
+        return htons(sin6->sin6_port);
+    }
+    return 0;
+}
+
+static inline void sockaddr_printf(const struct sockaddr* addr) {
+    char ip[INET6_ADDRSTRLEN] = {0};
+    int port = 0;
+    if (addr->sa_family == AF_INET) {
+        struct sockaddr_in* sin = (struct sockaddr_in*)addr;
+        inet_ntop(AF_INET, &sin->sin_addr, ip, sizeof(ip));
+        port = htons(sin->sin_port);
+    }
+    else if (addr->sa_family == AF_INET6) {
+        struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
+        inet_ntop(AF_INET6, &sin6->sin6_addr, ip, sizeof(ip));
+        port = htons(sin6->sin6_port);
+    }
+    printf("%s:%d\n", ip, port);
+}
+
+static inline const char* sockaddr_snprintf(const struct sockaddr* addr, char* buf, int len) {
+    int port = 0;
+    if (addr->sa_family == AF_INET) {
+        struct sockaddr_in* sin = (struct sockaddr_in*)addr;
+        inet_ntop(AF_INET, &sin->sin_addr, buf, len);
+        port = htons(sin->sin_port);
+    }
+    else if (addr->sa_family == AF_INET6) {
+        struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr;
+        inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len);
+        port = htons(sin6->sin6_port);
+    }
+    char sport[16] = {0};
+    snprintf(sport, sizeof(sport), ":%d", port);
+    safe_strncat(buf, sport, len);
+    return buf;
+}
+
 static inline int tcp_nodelay(int sockfd, int on DEFAULT(1)) {
     return setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(int));
 }
@@ -60,7 +127,7 @@ static inline int tcp_nopush(int sockfd, int on DEFAULT(1)) {
 
 static inline int tcp_keepalive(int sockfd, int on DEFAULT(1), int delay DEFAULT(60)) {
     if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(int)) != 0) {
-        return sockerrno;
+        return socket_errno();
     }
 
 #ifdef TCP_KEEPALIVE

+ 0 - 39
base/hstring.cpp

@@ -8,45 +8,6 @@
 #include <iostream>
 #include <sstream>
 
-char* strupper(char* str) {
-    char* p = str;
-    while (*p != '\0') {
-        if (*p >= 'a' && *p <= 'z') {
-            *p &= ~0x20;
-        }
-        ++p;
-    }
-    return str;
-}
-
-char* strlower(char* str) {
-    char* p = str;
-    while (*p != '\0') {
-        if (*p >= 'A' && *p <= 'Z') {
-            *p |= 0x20;
-        }
-        ++p;
-    }
-    return str;
-}
-
-char* strreverse(char* str) {
-    if (str == NULL) return NULL;
-    char* b = str;
-    char* e = str;
-    while(*e) {++e;}
-    --e;
-    char tmp;
-    while (e > b) {
-        tmp = *e;
-        *e = *b;
-        *b = tmp;
-        --e;
-        ++b;
-    }
-    return str;
-}
-
 static inline int vscprintf(const char* fmt, va_list ap) {
     return vsnprintf(NULL, 0, fmt, ap);
 }

+ 3 - 14
base/hstring.h

@@ -1,18 +1,11 @@
 #ifndef HW_STRING_H_
 #define HW_STRING_H_
 
-#include <string.h>
-#ifdef _MSC_VER
-    #define strcasecmp stricmp
-    #define strncasecmp strnicmp
-#else
-    #include <strings.h>
-    #define stricmp     strcasecmp
-    #define strnicmp    strncasecmp
-#endif
-
 #include <string>
 #include <vector>
+
+#include "hbase.h"
+
 using std::string;
 typedef std::vector<string> StringList;
 
@@ -27,10 +20,6 @@ public:
 #define SPACE_CHARS     " \t\r\n"
 #define PAIR_CHARS      "{}[]()<>\"\"\'\'``"
 
-char* strupper(char* str);
-char* strlower(char* str);
-char* strreverse(char* str);
-
 string asprintf(const char* fmt, ...);
 StringList split(const string& str, char delim);
 string trim(const string& str, const char* chars = SPACE_CHARS);

+ 1 - 1
base/hthread.h

@@ -17,7 +17,7 @@
 static inline int gettid() {
     return syscall(SYS_gettid);
 }
-#else
+#elif HAVE_PTHREAD_H
 #define gettid  pthread_self
 #endif
 

+ 1 - 1
base/htime.c

@@ -31,7 +31,7 @@ inline unsigned long long gethrtime() {
         return count.QuadPart / (double)s_freq * 1000000;
     }
     return 0;
-#elif defined(OS_LINUX)
+#elif HAVE_CLOCK_GETTIME
     struct timespec ts;
     clock_gettime(CLOCK_MONOTONIC, &ts);
     return ts.tv_sec*(unsigned long long)1000000 + ts.tv_nsec / 1000;

+ 16 - 1
base/htime.h

@@ -29,6 +29,21 @@ typedef struct datetime_s {
 static inline void sleep(unsigned int s) {
     Sleep(s*1000);
 }
+
+static inline void usleep(unsigned int us) {
+    Sleep(us/1000);
+}
+
+#include <sys/timeb.h>
+static inline int gettimeofday(struct timeval *tv, struct timeval *tz) {
+  struct _timeb timebuffer;
+
+  _ftime( &timebuffer );
+
+  tv->tv_sec = (long) timebuffer.time;
+  tv->tv_usec = timebuffer.millitm * 1000;
+  return 0;
+}
 #endif
 
 static inline void msleep(unsigned int ms) {
@@ -43,7 +58,7 @@ static inline void msleep(unsigned int ms) {
 static inline unsigned int gettick() {
 #ifdef OS_WIN
     return GetTickCount();
-#elif defined(OS_LINUX)
+#elif HAVE_CLOCK_GETTIME
     struct timespec ts;
     clock_gettime(CLOCK_MONOTONIC, &ts);
     return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;

+ 3 - 2
base/hvar.h

@@ -37,8 +37,9 @@ class HVar {
     HVar(void* ptr) {data.ptr = ptr; type = POINTER;}
 
     ~HVar() {
-        if (type == STRING) {
-            SAFE_FREE(data.str);
+        if (type == STRING && data.str) {
+            free(data.str);
+            data.str = NULL;
         }
     }
 

+ 10 - 8
base/netinet.h

@@ -3,6 +3,7 @@
 
 #include "hplatform.h"
 
+/*
 #ifdef OS_UNIX
 #include <netinet/in.h>
 #include <netinet/ip.h>
@@ -14,10 +15,11 @@ typedef struct udphdr   udphdr_t;
 typedef struct tcphdr   tcphdr_t;
 
 typedef struct icmphdr  icmphdr_t;
-typedef struct icmp     icmp;
+typedef struct icmp     icmp_t;
 #else
+*/
 // sizeof(iphdr_t) = 20
-typedef struct iphdr {
+typedef struct iphdr_s {
 #if BYTE_ORDER == LITTLE_ENDIAN
     uint8_t     ihl:4; // ip header length
     uint8_t     version:4;
@@ -40,7 +42,7 @@ typedef struct iphdr {
 } iphdr_t;
 
 // sizeof(udphdr_t) = 8
-typedef struct udphdr {
+typedef struct udphdr_s {
     uint16_t    source; // source port
     uint16_t    dest;   // dest   port
     uint16_t    len;    // udp length
@@ -48,7 +50,7 @@ typedef struct udphdr {
 } udphdr_t;
 
 // sizeof(tcphdr_t) = 20
-typedef struct tcphdr {
+typedef struct tcphdr_s {
     uint16_t    source; // source port
     uint16_t    dest;   // dest   port
     uint32_t    seq;    // sequence
@@ -97,7 +99,7 @@ typedef struct tcphdr {
 #define ICMP_ADDRESSREPLY	18	/* Address Mask Reply		*/
 
 // sizeof(icmphdr_t) = 8
-typedef struct icmphdr {
+typedef struct icmphdr_s {
     uint8_t     type;   // message type
     uint8_t     code;   // type sub-code
     uint16_t    checksum;
@@ -114,7 +116,7 @@ typedef struct icmphdr {
     } un;
 } icmphdr_t;
 
-typedef struct icmp {
+typedef struct icmp_s {
     uint8_t     icmp_type;
     uint8_t     icmp_code;
     uint16_t    icmp_cksum;
@@ -171,8 +173,8 @@ typedef struct icmp {
 #define	icmp_radv	icmp_dun.id_radv
 #define	icmp_mask	icmp_dun.id_mask
 #define	icmp_data	icmp_dun.id_data
-} icmp;
-#endif
+} icmp_t;
+//#endif
 
 static inline uint16_t checksum(uint8_t* buf, int len) {
     unsigned int sum = 0;

+ 6 - 8
base/queue.h

@@ -10,6 +10,8 @@
 #include <stdlib.h> // for malloc,realloc,free
 #include <string.h> // for memset,memmove
 
+#include "hbase.h"
+
 // #include <deque>
 // typedef std::deque<type> qtype;
 #define QUEUE_DECL(type, qtype) \
@@ -49,10 +51,9 @@ static inline void qtype##_init(qtype* p, int maxsize) {\
     p->_offset = 0;\
     p->size = 0;\
     p->maxsize = maxsize;\
-    size_t bytes = sizeof(type) * maxsize;\
-    p->ptr = (type*)malloc(bytes);\
-    memset(p->ptr, 0, bytes);\
+    SAFE_ALLOC(p->ptr, sizeof(type) * maxsize);\
 }\
+\
 static inline void qtype##_clear(qtype* p) {\
     p->_offset = 0;\
     p->size = 0;\
@@ -60,17 +61,14 @@ static inline void qtype##_clear(qtype* p) {\
 }\
 \
 static inline void qtype##_cleanup(qtype* p) {\
-    if (p->ptr) {\
-        free(p->ptr);\
-        p->ptr = NULL;\
-    }\
+    SAFE_FREE(p->ptr);\
     p->_offset = p->size = p->maxsize = 0;\
 }\
 \
 static inline void qtype##_resize(qtype* p, int maxsize) {\
     p->maxsize = maxsize;\
     int bytes = sizeof(type) * maxsize;\
-    p->ptr = (type*)realloc(p->ptr, bytes);\
+    p->ptr = (type*)safe_realloc(p->ptr, bytes);\
 }\
 \
 static inline void qtype##_double_resize(qtype* p) {\

+ 128 - 0
configure

@@ -0,0 +1,128 @@
+#!/bin/bash
+
+confile=hconfig.h
+# start confile
+cat << END > $confile
+#ifndef HW_CONFIG_H_
+#define HW_CONFIG_H_
+
+END
+
+# Checks for compiler
+echo "checking for compiler..."
+if [ $CROSS_COMPILE ]; then
+    $CC  = ${CROSS_COMPILE}gcc
+    $CXX = ${CROSS_COMPILE}g++
+fi
+
+if [ ! $CC ]; then
+    CC=gcc
+    CXX=g++
+fi
+CC_VERSION=`$CC --version 2>&1 | head -n 1`
+
+echo "CC  = $CC"
+echo "CXX = $CXX"
+echo "$CC_VERSION"
+
+# shell functions
+
+write_define() {
+cat << END >> hconfig.h
+#ifndef $macro
+#define $macro $value
+#endif
+
+END
+}
+
+mkdir tmp 2>/dev/null
+check_header() {
+echo -n "checking for $header... "
+rm tmp/check 2>/dev/null
+cat << END > tmp/check.c
+#include <$header>
+
+int main() {
+    return 0;
+}
+
+END
+$CC -o tmp/check tmp/check.c 2>/dev/null
+if [ -x tmp/check ]; then
+    value=1
+    echo "yes"
+else
+    value=0
+    echo "no"
+fi
+macro=HAVE_$(echo $header | tr a-z./ A-Z__)
+write_define
+}
+
+check_funtion() {
+echo -n "checking for $function... "
+rm tmp/check 2>/dev/null
+cat << END > tmp/check.c
+#include <$header>
+
+int $function(void** pp) {return 0;}
+int main() {
+    void* p;
+    return $function(&p);
+}
+
+END
+$CC -o tmp/check tmp/check.c 2>/dev/null
+if [ -x tmp/check ]; then
+    value=0
+    echo "no"
+else
+    value=1
+    echo "yes"
+fi
+macro=HAVE_$(echo $function | tr a-z A-Z)
+write_define
+}
+
+# Checks for os
+echo "checking for os..."
+HOST_OS=`uname -s`
+HOST_ARCH=`uname -m`
+TARGET_PLATFORM=`$CC -v 2>&1 | grep Target | sed 's/Target: //'`
+TARGET_ARCH=`echo $TARGET_PLATFORM | awk -F'-' '{print $1}'`
+
+case $TARGET_PLATFORM in
+    *mingw*) TARGET_OS=Windows ;;
+    *android*) TARGET_OS=Android ;;
+    *) TARGET_OS=Linux ;;
+esac
+
+echo "HOST_OS         = $HOST_OS"
+echo "HOST_ARCH       = $HOST_ARCH"
+echo "TARGET_PLATFORM = $TARGET_PLATFORM"
+echo "TARGET_OS       = $TARGET_OS"
+echo "TARGET_ARCH     = $TARGET_ARCH"
+
+# Checks for programs
+
+# Checks for libraries
+
+# Checks for header files
+header=stdint.h && check_header
+header=stdbool.h && check_header
+header=sys/types.h && check_header
+header=sys/stat.h && check_header
+header=fcntl.h && check_header
+header=pthread.h && check_header
+
+# Checks for functions
+function=clock_gettime && header=time.h && check_funtion
+
+# end confile
+cat << END >> $confile
+#endif // HW_CONFIG_H_
+
+END
+
+echo "configure done."

+ 2 - 1
event/epoll.c

@@ -20,7 +20,8 @@ typedef struct epoll_ctx_s {
 
 int iowatcher_init(hloop_t* loop) {
     if (loop->iowatcher) return 0;
-    epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)malloc(sizeof(epoll_ctx_t));
+    epoll_ctx_t* epoll_ctx;
+    SAFE_ALLOC_SIZEOF(epoll_ctx);
     epoll_ctx->epfd = epoll_create(EVENTS_INIT_SIZE);
     events_init(&epoll_ctx->events, EVENTS_INIT_SIZE);
     loop->iowatcher = epoll_ctx;

+ 44 - 20
event/hloop.c

@@ -13,6 +13,7 @@
 
 static void hio_init(hio_t* io);
 static void hio_deinit(hio_t* io);
+static void hio_reset(hio_t* io);
 static void hio_free(hio_t* io);
 
 static int timers_compare(const struct heap_node* lhs, const struct heap_node* rhs) {
@@ -43,7 +44,7 @@ next:
 destroy:
         node = node->next;
         list_del(node->prev);
-        free(idle);
+        SAFE_FREE(idle);
     }
     return nidles;
 }
@@ -80,7 +81,7 @@ static int hloop_process_timers(hloop_t* loop) {
         continue;
 destroy:
         heap_dequeue(&loop->timers);
-        free(timer);
+        SAFE_FREE(timer);
     }
     return ntimers;
 }
@@ -151,7 +152,7 @@ process_timers:
             nidles= hloop_process_idles(loop);
         }
     }
-    printd("blocktime=%d nios=%d ntimers=%d nidles=%d nactives=%d npendings=%d\n", blocktime, nios, ntimers, nidles, loop->nactives, loop->npendings);
+    //printd("blocktime=%d nios=%d ntimers=%d nidles=%d nactives=%d npendings=%d\n", blocktime, nios, ntimers, nidles, loop->nactives, loop->npendings);
     return hloop_process_pendings(loop);
 }
 
@@ -174,27 +175,31 @@ int hloop_init(hloop_t* loop) {
 
 void hloop_cleanup(hloop_t* loop) {
     // pendings
+    printd("cleanup pendings...\n");
     for (int i = 0; i < HEVENT_PRIORITY_SIZE; ++i) {
         loop->pendings[i] = NULL;
     }
     // idles
+    printd("cleanup idles...\n");
     struct list_node* node = loop->idles.next;
     hidle_t* idle;
     while (node != &loop->idles) {
         idle = IDLE_ENTRY(node);
         node = node->next;
-        free(idle);
+        SAFE_FREE(idle);
     }
     list_init(&loop->idles);
     // timers
+    printd("cleanup timers...\n");
     htimer_t* timer;
     while (loop->timers.root) {
-        timer = TIMER_ENTRY(node);
+        timer = TIMER_ENTRY(loop->timers.root);
         heap_dequeue(&loop->timers);
-        free(timer);
+        SAFE_FREE(timer);
     }
     heap_init(&loop->timers, NULL);
     // ios
+    printd("cleanup ios...\n");
     for (int i = 0; i < loop->ios.maxsize; ++i) {
         hio_t* io = loop->ios.ptr[i];
         if (io) {
@@ -204,7 +209,7 @@ void hloop_cleanup(hloop_t* loop) {
     io_array_cleanup(&loop->ios);
     // iowatcher
     iowatcher_cleanup(loop);
-};
+}
 
 int hloop_run(hloop_t* loop) {
     loop->loop_cnt = 0;
@@ -223,7 +228,7 @@ int hloop_run(hloop_t* loop) {
     loop->end_hrtime = gethrtime();
     hloop_cleanup(loop);
     return 0;
-};
+}
 
 int hloop_stop(hloop_t* loop) {
     loop->status = HLOOP_STATUS_STOP;
@@ -245,8 +250,8 @@ int hloop_resume(hloop_t* loop) {
 }
 
 hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
-    hidle_t* idle = (hidle_t*)malloc(sizeof(hidle_t));
-    memset(idle, 0, sizeof(hidle_t));
+    hidle_t* idle;
+    SAFE_ALLOC_SIZEOF(idle);
     idle->event_type = HEVENT_TYPE_IDLE;
     idle->priority = HEVENT_LOWEST_PRIORITY;
     idle->repeat = repeat;
@@ -264,8 +269,8 @@ void hidle_del(hidle_t* idle) {
 
 htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint64_t timeout, uint32_t repeat) {
     if (timeout == 0)   return NULL;
-    htimeout_t* timer = (htimeout_t*)malloc(sizeof(htimeout_t));
-    memset(timer, 0, sizeof(htimeout_t));
+    htimeout_t* timer;
+    SAFE_ALLOC_SIZEOF(timer);
     timer->event_type = HEVENT_TYPE_TIMEOUT;
     timer->priority = HEVENT_HIGHEST_PRIORITY;
     timer->repeat = repeat;
@@ -295,8 +300,8 @@ htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
     if (minute > 59 || hour > 23 || day > 31 || week > 6 || month > 12) {
         return NULL;
     }
-    hperiod_t* timer = (hperiod_t*)malloc(sizeof(hperiod_t));
-    memset(timer, 0, sizeof(hperiod_t));
+    hperiod_t* timer;
+    SAFE_ALLOC_SIZEOF(timer);
     timer->event_type = HEVENT_TYPE_PERIOD;
     timer->priority = HEVENT_HIGH_PRIORITY;
     timer->repeat = repeat;
@@ -326,6 +331,19 @@ void hio_init(hio_t* io) {
     //write_queue_init(&io->write_queue, 4);;
 }
 
+void hio_reset(hio_t* io) {
+    io->accept = io->connect = io->closed = 0;
+    io->error = 0;
+    io->events = io->revents = 0;
+    io->read_cb = NULL;
+    io->write_cb = NULL;
+    io->close_cb = 0;
+    io->accept_cb = 0;
+    io->connect_cb = 0;
+    io->event_index[0] = io->event_index[1] = -1;
+    io->hovlp = NULL;
+}
+
 void hio_deinit(hio_t* io) {
     offset_buf_t* pbuf = NULL;
     while (!write_queue_empty(&io->write_queue)) {
@@ -341,10 +359,11 @@ void hio_free(hio_t* io) {
     hio_deinit(io);
     SAFE_FREE(io->localaddr);
     SAFE_FREE(io->peeraddr);
-    free(io);
+    SAFE_FREE(io);
 }
 
 hio_t* hio_add(hloop_t* loop, hio_cb cb, int fd, int events) {
+    printd("hio_add fd=%d events=%d\n", fd, events);
     if (loop->ios.maxsize == 0) {
         io_array_init(&loop->ios, IO_ARRAY_INIT_SIZE);
     }
@@ -356,13 +375,17 @@ hio_t* hio_add(hloop_t* loop, hio_cb cb, int fd, int events) {
 
     hio_t* io = loop->ios.ptr[fd];
     if (io == NULL) {
-        io = (hio_t*)malloc(sizeof(hio_t));
-        memset(io, 0, sizeof(hio_t));
+        SAFE_ALLOC_SIZEOF(io);
         loop->ios.ptr[fd] = io;
+        hio_init(io);
     }
 
-    if (!io->active || io->destroy) {
-        hio_init(io);
+    if (io->destroy) {
+        io->destroy = 0;
+        hio_reset(io);
+    }
+
+    if (!io->active) {
         EVENT_ADD(loop, io, cb);
         loop->nios++;
     }
@@ -377,13 +400,14 @@ hio_t* hio_add(hloop_t* loop, hio_cb cb, int fd, int events) {
 }
 
 void hio_del(hio_t* io, int events) {
+    printd("hio_del fd=%d io->events=%d events=%d\n", io->fd, io->events, events);
     if (io->destroy) return;
     iowatcher_del_event(io->loop, io->fd, events);
     io->events &= ~events;
     if (io->events == 0) {
         io->loop->nios--;
-        hio_deinit(io);
         EVENT_DEL(io);
+        hio_deinit(io);
     }
 }
 

+ 2 - 1
event/iocp.c

@@ -13,7 +13,8 @@ typedef struct iocp_ctx_s {
 
 int iowatcher_init(hloop_t* loop) {
     if (loop->iowatcher)    return 0;
-    iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)malloc(sizeof(iocp_ctx_t));
+    iocp_ctx_t* iocp_ctx;
+    SAFE_ALLOC_SIZEOF(iocp_ctx);
     iocp_ctx->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
     loop->iowatcher = iocp_ctx;
     return 0;

+ 6 - 7
event/kqueue.c

@@ -25,22 +25,21 @@ typedef struct kqueue_ctx_s {
 
 static void kqueue_ctx_resize(kqueue_ctx_t* kqueue_ctx, int size) {
     int bytes = sizeof(struct kevent) * size;
-    kqueue_ctx->changes = (struct kevent*)realloc(kqueue_ctx->changes, bytes);
-    kqueue_ctx->events = (struct kevent*)realloc(kqueue_ctx->events, bytes);
+    kqueue_ctx->changes = (struct kevent*)safe_realloc(kqueue_ctx->changes, bytes);
+    kqueue_ctx->events = (struct kevent*)safe_realloc(kqueue_ctx->events, bytes);
     kqueue_ctx->capacity = size;
 }
 
 int iowatcher_init(hloop_t* loop) {
     if (loop->iowatcher) return 0;
-    kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)malloc(sizeof(kqueue_ctx_t));
+    kqueue_ctx_t* kqueue_ctx;
+    SAFE_ALLOC_SIZEOF(kqueue_ctx);
     kqueue_ctx->kqfd = kqueue();
     kqueue_ctx->capacity = EVENTS_INIT_SIZE;
     kqueue_ctx->nchanges = 0;
     int bytes = sizeof(struct kevent) * kqueue_ctx->capacity;
-    kqueue_ctx->changes = (struct kevent*)malloc(bytes);
-    memset(kqueue_ctx->changes, 0, bytes);
-    kqueue_ctx->events = (struct kevent*)malloc(bytes);
-    memset(kqueue_ctx->events, 0, bytes);
+    SAFE_ALLOC(kqueue_ctx->changes, bytes);
+    SAFE_ALLOC(kqueue_ctx->events, bytes);
     loop->iowatcher = kqueue_ctx;
     return 0;
 }

+ 29 - 37
event/nio.c

@@ -6,38 +6,34 @@ static void nio_accept(hio_t* io) {
     //printd("nio_accept listenfd=%d\n", io->fd);
     socklen_t addrlen;
     if (io->localaddr == NULL) {
-        io->localaddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
+        SAFE_ALLOC(io->localaddr, sizeof(struct sockaddr_in6));
     }
     if (io->peeraddr == NULL) {
-        io->peeraddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
+        SAFE_ALLOC(io->peeraddr, sizeof(struct sockaddr_in6));
     }
 accept:
-    addrlen = sizeof(struct sockaddr_in);
+    addrlen = sizeof(struct sockaddr_in6);
     int connfd = accept(io->fd, io->peeraddr, &addrlen);
     if (connfd < 0) {
-        if (sockerrno == NIO_EAGAIN) {
+        if (socket_errno() == EAGAIN) {
             //goto accept_done;
             return;
         }
         else {
-            io->error = sockerrno;
+            io->error = socket_errno();
             perror("accept");
             goto accept_error;
         }
     }
 
-    addrlen = sizeof(struct sockaddr_in);
+    addrlen = sizeof(struct sockaddr_in6);
     getsockname(connfd, io->localaddr, &addrlen);
     if (io->accept_cb) {
-        struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-        struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-        char localip[64];
-        char peerip[64];
-        inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-        inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-        printd("accept listenfd=%d connfd=%d [%s:%d] <= [%s:%d]\n", io->fd, connfd,
-                localip, ntohs(localaddr->sin_port),
-                peerip, ntohs(peeraddr->sin_port));
+        char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+        char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+        printd("accept listenfd=%d connfd=%d [%s] <= [%s]\n", io->fd, connfd,
+                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
         printd("accept_cb------\n");
         io->accept_cb(io, connfd);
         printd("accept_cb======\n");
@@ -54,30 +50,26 @@ static void nio_connect(hio_t* io) {
     int state = 0;
     socklen_t addrlen;
     if (io->localaddr == NULL) {
-        io->localaddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
-        addrlen = sizeof(struct sockaddr_in);
+        SAFE_ALLOC(io->localaddr, sizeof(struct sockaddr_in6));
+        addrlen = sizeof(struct sockaddr_in6);
         getsockname(io->fd, io->localaddr, &addrlen);
     }
     if (io->peeraddr == NULL) {
-        io->peeraddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
+        SAFE_ALLOC(io->peeraddr, sizeof(struct sockaddr_in6));
     }
-    addrlen = sizeof(struct sockaddr_in);
+    addrlen = sizeof(struct sockaddr_in6);
     int ret = getpeername(io->fd, io->peeraddr, &addrlen);
     if (ret < 0) {
-        io->error = sockerrno;
-        printd("connect failed: %s: %d\n", strerror(sockerrno), sockerrno);
+        io->error = socket_errno();
+        printd("connect failed: %s: %d\n", strerror(socket_errno()), socket_errno());
         state = 0;
     }
     else {
-        struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-        struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-        char localip[64];
-        char peerip[64];
-        inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-        inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-        printd("connect connfd=%d [%s:%d] => [%s:%d]\n", io->fd,
-                localip, ntohs(localaddr->sin_port),
-                peerip, ntohs(peeraddr->sin_port));
+        char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+        char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+        printd("connect connfd=%d [%s] => [%s]\n", io->fd,
+                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
         state = 1;
     }
     if (io->connect_cb) {
@@ -104,12 +96,12 @@ read:
 #endif
     //printd("read retval=%d\n", nread);
     if (nread < 0) {
-        if (sockerrno == NIO_EAGAIN) {
+        if (socket_errno() == EAGAIN) {
             //goto read_done;
             return;
         }
         else {
-            io->error = sockerrno;
+            io->error = socket_errno();
             perror("read");
             goto read_error;
         }
@@ -149,12 +141,12 @@ write:
 #endif
     //printd("write retval=%d\n", nwrite);
     if (nwrite < 0) {
-        if (sockerrno == NIO_EAGAIN) {
+        if (socket_errno() == EAGAIN) {
             //goto write_done;
             return;
         }
         else {
-            io->error = sockerrno;
+            io->error = socket_errno();
             perror("write");
             goto write_error;
         }
@@ -267,13 +259,13 @@ try_write:
 #endif
         //printd("write retval=%d\n", nwrite);
         if (nwrite < 0) {
-            if (sockerrno == NIO_EAGAIN) {
+            if (socket_errno() == EAGAIN) {
                 nwrite = 0;
                 goto enqueue;
             }
             else {
                 perror("write");
-                io->error = sockerrno;
+                io->error = socket_errno();
                 goto write_error;
             }
         }
@@ -297,7 +289,7 @@ enqueue:
         rest.len = len;
         rest.offset = nwrite;
         // NOTE: free in nio_write;
-        rest.base = (char*)malloc(rest.len);
+        SAFE_ALLOC(rest.base, rest.len);
         if (rest.base == NULL) return io;
         memcpy(rest.base, (char*)buf, rest.len);
         if (io->write_queue.maxsize == 0) {

+ 31 - 44
event/overlapio.c

@@ -20,16 +20,14 @@ int post_acceptex(hio_t* listenio, hoverlapped_t* hovlp) {
         return WSAGetLastError();
     }
     if (hovlp == NULL) {
-        hovlp = (hoverlapped_t*)malloc(sizeof(hoverlapped_t));
-        memset(hovlp, 0, sizeof(hoverlapped_t));
-        hovlp->buf.len = 20 + (sizeof(SOCKADDR_IN) + 16) * 2;
-        hovlp->buf.buf = (char*)malloc(hovlp->buf.len);
-        memset(hovlp->buf.buf, 0, hovlp->buf.len);
+        SAFE_ALLOC_SIZEOF(hovlp);
+        hovlp->buf.len = 20 + sizeof(struct sockaddr_in6) * 2;
+        SAFE_ALLOC(hovlp->buf.buf, hovlp->buf.len);
     }
     hovlp->fd = connfd;
     hovlp->event = READ_EVENT;
     hovlp->io = listenio;
-    if (AcceptEx(listenio->fd, connfd, hovlp->buf.buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16,
+    if (AcceptEx(listenio->fd, connfd, hovlp->buf.buf, 0, sizeof(struct sockaddr_in6), sizeof(struct sockaddr_in6),
         &dwbytes, &hovlp->ovlp) != TRUE) {
         int err = WSAGetLastError();
         if (err != ERROR_IO_PENDING) {
@@ -42,8 +40,7 @@ int post_acceptex(hio_t* listenio, hoverlapped_t* hovlp) {
 
 int post_recv(hio_t* io, hoverlapped_t* hovlp) {
     if (hovlp == NULL) {
-        hovlp = (hoverlapped_t*)malloc(sizeof(hoverlapped_t));
-        memset(hovlp, 0, sizeof(hoverlapped_t));
+        SAFE_ALLOC_SIZEOF(hovlp);
     }
     hovlp->fd = io->fd;
     hovlp->event = READ_EVENT;
@@ -83,26 +80,22 @@ static void on_acceptex_complete(hio_t* io) {
     struct sockaddr* ppeeraddr = NULL;
     socklen_t localaddrlen;
     socklen_t peeraddrlen;
-    GetAcceptExSockaddrs(hovlp->buf.buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16,
+    GetAcceptExSockaddrs(hovlp->buf.buf, 0, sizeof(struct sockaddr_in6), sizeof(struct sockaddr_in6),
         &plocaladdr, &localaddrlen, &ppeeraddr, &peeraddrlen);
     if (io->localaddr == NULL) {
-        io->localaddr = (struct sockaddr*)malloc(localaddrlen);
+        SAFE_ALLOC(io->localaddr, localaddrlen);
     }
     memcpy(io->localaddr, plocaladdr, localaddrlen);
     if (io->peeraddr == NULL) {
-        io->peeraddr = (struct sockaddr*)malloc(peeraddrlen);
+        SAFE_ALLOC(io->peeraddr, peeraddrlen);
     }
     memcpy(io->peeraddr, ppeeraddr, peeraddrlen);
     if (io->accept_cb) {
-        struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-        struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-        char localip[64];
-        char peerip[64];
-        inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-        inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-        printd("accept listenfd=%d connfd=%d [%s:%d] <= [%s:%d]\n", listenfd, connfd,
-                localip, ntohs(localaddr->sin_port),
-                peerip, ntohs(peeraddr->sin_port));
+        char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+        char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+        printd("accept listenfd=%d connfd=%d [%s] <= [%s]\n", listenfd, connfd,
+                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
         setsockopt(connfd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (const char*)&listenfd, sizeof(int));
         printd("accept_cb------\n");
         io->accept_cb(io, connfd);
@@ -117,25 +110,21 @@ static void on_connectex_complete(hio_t* io) {
     int state = hovlp->error == 0 ? 1 : 0;
     if (state == 1) {
         if (io->localaddr == NULL) {
-            io->localaddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
+            SAFE_ALLOC(io->localaddr, sizeof(struct sockaddr_in6));
         }
         if (io->peeraddr == NULL) {
-            io->peeraddr = (struct sockaddr*)malloc(sizeof(struct sockaddr_in));
+            SAFE_ALLOC(io->peeraddr, sizeof(struct sockaddr_in6));
         }
         setsockopt(io->fd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
-        socklen_t addrlen = sizeof(struct sockaddr_in);
+        socklen_t addrlen = sizeof(struct sockaddr_in6);
         getsockname(io->fd, io->localaddr, &addrlen);
-        addrlen = sizeof(struct sockaddr_in);
+        addrlen = sizeof(struct sockaddr_in6);
         getpeername(io->fd, io->peeraddr, &addrlen);
-        struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-        struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-        char localip[64];
-        char peerip[64];
-        inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-        inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-        printd("connect connfd=%d [%s:%d] => [%s:%d]\n", io->fd,
-                localip, ntohs(localaddr->sin_port),
-                peerip, ntohs(peeraddr->sin_port));
+        char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+        char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+        printd("connect connfd=%d [%s] => [%s]\n", io->fd,
+                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
     }
     else {
         io->error = hovlp->error;
@@ -186,8 +175,7 @@ static void on_wsasend_complete(hio_t* io) {
 end:
     if (io->hovlp) {
         SAFE_FREE(hovlp->buf.buf);
-        free(io->hovlp);
-        io->hovlp = NULL;
+        SAFE_FREE(io->hovlp);
     }
 }
 
@@ -283,8 +271,8 @@ hio_t* hconnect (hloop_t* loop, const char* host, int port, hconnect_cb connect_
         goto error;
     }
     // NOTE: free on_connectex_complete
-    hoverlapped_t* hovlp = (hoverlapped_t*)malloc(sizeof(hoverlapped_t));
-    memset(hovlp, 0, sizeof(hoverlapped_t));
+    hoverlapped_t* hovlp;
+    SAFE_ALLOC_SIZEOF(hovlp);
     hovlp->fd = connfd;
     hovlp->event = WRITE_EVENT;
     hovlp->io = io;
@@ -324,13 +312,13 @@ try_send:
     nwrite = send(fd, buf, len, 0);
     //printd("write retval=%d\n", nwrite);
     if (nwrite < 0) {
-        if (sockerrno == NIO_EAGAIN) {
+        if (socket_errno() == EAGAIN) {
             nwrite = 0;
             goto WSASend;
         }
         else {
             perror("write");
-            io->error = sockerrno;
+            io->error = socket_errno();
             goto write_error;
         }
     }
@@ -348,13 +336,13 @@ try_send:
     }
 WSASend:
     {
-        hoverlapped_t* hovlp = (hoverlapped_t*)malloc(sizeof(hoverlapped_t));
-        memset(hovlp, 0, sizeof(hoverlapped_t));
+        hoverlapped_t* hovlp;
+        SAFE_ALLOC_SIZEOF(hovlp);
         hovlp->fd = fd;
         hovlp->event = WRITE_EVENT;
         hovlp->buf.len = len - nwrite;
         // NOTE: free on_send_complete
-        hovlp->buf.buf = (char*)malloc(hovlp->buf.len);
+        SAFE_ALLOC(hovlp->buf.buf, hovlp->buf.len);
         memcpy(hovlp->buf.buf, buf + nwrite, hovlp->buf.len);
         hovlp->io = io;
         DWORD dwbytes = 0;
@@ -405,8 +393,7 @@ void   hclose   (hio_t* io) {
         if (hovlp->buf.buf != io->readbuf.base) {
             SAFE_FREE(hovlp->buf.buf);
         }
-        free(io->hovlp);
-        io->hovlp = NULL;
+        SAFE_FREE(io->hovlp);
     }
     if (io->close_cb) {
         printd("close_cb------\n");

+ 2 - 1
event/poll.c

@@ -25,7 +25,8 @@ typedef struct poll_ctx_s {
 
 int iowatcher_init(hloop_t* loop) {
     if (loop->iowatcher)   return 0;
-    poll_ctx_t* poll_ctx = (poll_ctx_t*)malloc(sizeof(poll_ctx_t));
+    poll_ctx_t* poll_ctx;
+    SAFE_ALLOC_SIZEOF(poll_ctx);
     pollfds_init(&poll_ctx->fds, FDS_INIT_SIZE);
     loop->iowatcher = poll_ctx;
     return 0;

+ 2 - 1
event/select.c

@@ -20,7 +20,8 @@ typedef struct select_ctx_s {
 
 int iowatcher_init(hloop_t* loop) {
     if (loop->iowatcher) return 0;
-    select_ctx_t* select_ctx = (select_ctx_t*)malloc(sizeof(select_ctx_t));
+    select_ctx_t* select_ctx;
+    SAFE_ALLOC_SIZEOF(select_ctx);
     select_ctx->max_fd = -1;
     FD_ZERO(&select_ctx->readfds);
     FD_ZERO(&select_ctx->writefds);

+ 9 - 9
examples/client.cpp

@@ -1,4 +1,6 @@
 #include "hloop.h"
+#include "hbase.h"
+#include "hsocket.h"
 
 #define RECV_BUFSIZE    4096
 static char readbuf[RECV_BUFSIZE];
@@ -44,15 +46,11 @@ void on_connect(hio_t* io, int state) {
         printf("error=%d:%s\n", io->error, strerror(io->error));
         return;
     }
-    struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-    struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-    char localip[64];
-    char peerip[64];
-    inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-    inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-    printf("connect connfd=%d [%s:%d] => [%s:%d]\n", io->fd,
-            localip, ntohs(localaddr->sin_port),
-            peerip, ntohs(peeraddr->sin_port));
+    char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+    char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+    printf("connect connfd=%d [%s] => [%s]\n", io->fd,
+            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
 
     // NOTE: just on loop, readbuf can be shared.
     hio_t* iostdin = hread(io->loop, 0, readbuf, RECV_BUFSIZE, on_stdin);
@@ -73,6 +71,8 @@ int main(int argc, char** argv) {
     const char* host = argv[1];
     int port = atoi(argv[2]);
 
+    MEMCHECK;
+
     hloop_t loop;
     hloop_init(&loop);
     //hidle_add(&loop, on_idle, INFINITE);

+ 5 - 2
examples/loop.c

@@ -1,4 +1,5 @@
 #include "hloop.h"
+#include "hbase.h"
 
 void on_idle(hidle_t* idle) {
     printf("on_idle: event_id=%lu\tpriority=%d\tuserdata=%ld\n", idle->event_id, idle->priority, (long)idle->userdata);
@@ -16,6 +17,8 @@ void cron_hourly(htimer_t* timer) {
 }
 
 int main() {
+    MEMCHECK;
+
     hloop_t loop;
     hloop_init(&loop);
     for (int i = HEVENT_LOWEST_PRIORITY; i <= HEVENT_HIGHEST_PRIORITY; ++i) {
@@ -23,11 +26,11 @@ int main() {
         idle->priority = i;
     }
     for (int i = 1; i <= 10; ++i) {
-        htimer_t* timer = htimer_add(&loop, on_timer, i*1000, i);
+        htimer_t* timer = htimer_add(&loop, on_timer, i*1000, 3);
         timer->userdata = (void*)i;
     }
     int minute = time(NULL)%3600/60;
-    htimer_add_period(&loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);
+    htimer_add_period(&loop, cron_hourly, minute+1, -1, -1, -1, -1, 1);
     hloop_run(&loop);
     return 0;
 }

+ 6 - 9
examples/server.cpp

@@ -1,4 +1,5 @@
 #include "hloop.h"
+#include "hsocket.h"
 
 #define RECV_BUFSIZE    4096
 static char readbuf[RECV_BUFSIZE];
@@ -31,15 +32,11 @@ void on_read(hio_t* io, void* buf, int readbytes) {
 
 void on_accept(hio_t* io, int connfd) {
     printf("on_accept listenfd=%d connfd=%d\n", io->fd, connfd);
-    struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-    struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-    char localip[64];
-    char peerip[64];
-    inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-    inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-    printf("accept listenfd=%d connfd=%d [%s:%d] <= [%s:%d]\n", io->fd, connfd,
-            localip, ntohs(localaddr->sin_port),
-            peerip, ntohs(peeraddr->sin_port));
+    char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+    char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+    printf("accept listenfd=%d connfd=%d [%s] <= [%s]\n", io->fd, connfd,
+            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
 
     // one loop can use one readbuf
     hio_t* connio = hread(io->loop, connfd, readbuf, RECV_BUFSIZE, on_read);

+ 33 - 0
hconfig.h

@@ -0,0 +1,33 @@
+#ifndef HW_CONFIG_H_
+#define HW_CONFIG_H_
+
+#ifndef HAVE_STDINT_H
+#define HAVE_STDINT_H 1
+#endif
+
+#ifndef HAVE_STDBOOL_H
+#define HAVE_STDBOOL_H 1
+#endif
+
+#ifndef HAVE_SYS_TYPES_H
+#define HAVE_SYS_TYPES_H 1
+#endif
+
+#ifndef HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H 1
+#endif
+
+#ifndef HAVE_FCNTL_H
+#define HAVE_FCNTL_H 1
+#endif
+
+#ifndef HAVE_PTHREAD_H
+#define HAVE_PTHREAD_H 1
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+#define HAVE_CLOCK_GETTIME 1
+#endif
+
+#endif // HW_CONFIG_H_
+

+ 1 - 0
http/HttpRequest.h

@@ -1,6 +1,7 @@
 #ifndef HTTP_REQUEST_H_
 #define HTTP_REQUEST_H_
 
+#include <time.h>
 #include <string.h>
 
 #include <string>

+ 25 - 18
http/server/http_server.cpp

@@ -121,15 +121,13 @@ static void on_close(hio_t* io) {
 
 static void on_accept(hio_t* io, int connfd) {
     //printf("on_accept listenfd=%d connfd=%d\n", io->fd, connfd);
-    //struct sockaddr_in* localaddr = (struct sockaddr_in*)io->localaddr;
-    struct sockaddr_in* peeraddr = (struct sockaddr_in*)io->peeraddr;
-    //char localip[64];
-    //char peerip[64];
-    //inet_ntop(localaddr->sin_family, &localaddr->sin_addr, localip, sizeof(localip));
-    //inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, peerip, sizeof(peerip));
-    //printd("accept listenfd=%d connfd=%d [%s:%d] <= [%s:%d]\n", io->fd, connfd,
-            //localip, ntohs(localaddr->sin_port),
-            //peerip, ntohs(peeraddr->sin_port));
+    /*
+    char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
+    char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
+    printf("accept listenfd=%d connfd=%d [%s] <= [%s]\n", io->fd, connfd,
+            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+    */
 
     nonblocking(connfd);
     HBuf* buf = (HBuf*)io->loop->userdata;
@@ -140,8 +138,8 @@ static void on_accept(hio_t* io, int connfd) {
     HttpHandler* handler = new HttpHandler;
     handler->service = (HttpService*)io->userdata;
     handler->files = &s_filecache;
-    inet_ntop(peeraddr->sin_family, &peeraddr->sin_addr, handler->srcip, sizeof(handler->srcip));
-    handler->srcport = ntohs(peeraddr->sin_port);
+    sockaddr_ntop(io->peeraddr, handler->srcip, sizeof(handler->srcip));
+    handler->srcport = sockaddr_htons(io->peeraddr);
     handler->io = connio;
     connio->userdata = handler;
 }
@@ -171,10 +169,14 @@ void fflush_log(hidle_t* idle) {
     hlog_fflush();
 }
 
+// for implement http_server_stop
+static hloop_t* s_loop = NULL;
+
 static void worker_proc(void* userdata) {
     http_server_t* server = (http_server_t*)userdata;
     int listenfd = server->listenfd;
     hloop_t loop;
+    s_loop = &loop;
     hloop_init(&loop);
     // one loop one readbuf.
     HBuf readbuf;
@@ -218,10 +220,6 @@ int http_server_run(http_server_t* server, int wait) {
         g_worker_processes_num = server->worker_processes;
         int bytes = g_worker_processes_num * sizeof(proc_ctx_t);
         g_worker_processes = (proc_ctx_t*)malloc(bytes);
-        if (g_worker_processes == NULL) {
-            perror("malloc");
-            abort();
-        }
         memset(g_worker_processes, 0, bytes);
         for (int i = 0; i < g_worker_processes_num; ++i) {
             proc_ctx_t* ctx = g_worker_processes + i;
@@ -231,11 +229,20 @@ int http_server_run(http_server_t* server, int wait) {
             ctx->proc_userdata = server;
             spawn_proc(ctx);
         }
+        if (wait) {
+            master_init(NULL);
+            master_proc(NULL);
+        }
     }
 
-    if (wait) {
-        master_init(NULL);
-        master_proc(NULL);
+    return 0;
+}
+
+// for SDK, just use for singleton
+int http_server_stop(http_server_t* server) {
+    if (s_loop) {
+        hloop_stop(s_loop);
+        s_loop = NULL;
     }
     return 0;
 }

+ 3 - 0
http/server/http_server.h

@@ -42,4 +42,7 @@ int main() {
  */
 int http_server_run(http_server_t* server, int wait = 1);
 
+// for SDK, just use for singleton
+int http_server_stop(http_server_t* server);
+
 #endif

+ 1 - 0
scripts/cmake.sh

@@ -0,0 +1 @@
+cmake .. -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_SYSTEM_NAME=$H_TARGET_OS -DCMAKE_SYSTEM_PROCESSOR=$H_TARGET_ARCH

+ 19 - 0
scripts/coredump.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+print_conf() {
+    echo /proc/sys/kernel/core_uses_pid
+    cat /proc/sys/kernel/core_uses_pid
+    echo /proc/sys/kernel/core_pattern
+    cat /proc/sys/kernel/core_pattern
+    echo /proc/sys/fs/suid_dumpable
+    cat /proc/sys/fs/suid_dumpable
+}
+
+print_conf
+echo "1" > /proc/sys/kernel/core_uses_pid
+echo "/tmp/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
+echo "1" > /proc/sys/fs/suid_dumpable
+print_conf
+
+ulimit -c unlimited
+ulimit -a

+ 14 - 0
scripts/create_pro.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+mkdir -p include lib src bin doc etc 3rd/include 3rd/lib dist
+touch README.md BUILD.md RELEASE.md CHANGELOG.md Makefile .gitignore
+git init
+
+# personal
+git submodule add https://github.com/ithewei/hw.git src/hw
+cp src/hw/.gitignore .
+cp src/hw/Makefile .
+cp -r src/hw/etc/* etc
+cp src/hw/main.cpp.tmpl src/main.cpp
+
+make

+ 7 - 0
scripts/my.cmake

@@ -0,0 +1,7 @@
+set(CMAKE_C_COMPILER $CC)
+set(CMAKE_CXX_COMPILER $CXX)
+
+set(CMAKE_SYSTEM_NAME $H_TARGET_OS)
+set(CMAKE_SYSTEM_PROCESSOR $H_TARGET_ARCH)
+
+add_definitions(-D_WIN32_WINNT=0x600)

+ 100 - 0
scripts/toolchain.sh

@@ -0,0 +1,100 @@
+#!/bin/bash
+
+print_help() {
+cat <<EOF
+Usage: command
+
+command:
+    export CROSS_COMPILE
+    unset
+
+example:
+    source ./toolchain.sh export arm-linux-androideabi
+    source ./toolchain.sh unset
+
+EOF
+}
+
+main() {
+    if [ $# -lt 1 ]; then
+        print_help
+        return
+    fi
+    COMMAND=$1
+
+    if [ $COMMAND = "export" ]; then
+        if [ $# -lt 2 ]; then
+            print_help
+            return
+        fi
+        CROSS_COMPILE=$2
+        if [ ${CROSS_COMPILE:${#CROSS_COMPILE}-1:1} != "-" ]; then
+            CROSS_COMPILE=${CROSS_COMPILE}-
+        fi
+        echo "CROSS_COMPILE=$CROSS_COMPILE"
+        export CROSS_COMPILE=${CROSS_COMPILE}
+        export CC=${CROSS_COMPILE}gcc
+        export CXX=${CROSS_COMPILE}g++
+        export AR=${CROSS_COMPILE}ar
+        export AS=${CROSS_COMPILE}as
+        export LD=${CROSS_COMPILE}ld
+        export STRIP=${CROSS_COMPILE}strip
+        export RANLIB=${CROSS_COMPILE}ranlib
+        export NM=${CROSS_COMPILE}nm
+
+        HOST_OS=`uname -s`
+        HOST_ARCH=`uname -m`
+        TARGET_PLATFORM=`$CC -v 2>&1 | grep Target | sed 's/Target: //'`
+        TARGET_ARCH=`echo $TARGET_PLATFORM | awk -F'-' '{print $1}'`
+
+        case $TARGET_PLATFORM in
+            *mingw*) TARGET_OS=Windows ;;
+            *android*) TARGET_OS=Android ;;
+            *) TARGET_OS=Linux ;;
+        esac
+        # TARGET_OS,TARGET_ARCH used by make
+        export H_HOST_OS=$HOST_OS
+        export H_HOST_ARCH=$HOST_ARCH
+        export H_TARGET_OS=$TARGET_OS
+        export H_TARGET_ARCH=$TARGET_ARCH
+        export HOST=$TARGET_PLATFORM
+    elif [ $COMMAND = "unset" ]; then
+        unset  CROSS_COMPILE
+        unset  CC
+        unset  CXX
+        unset  AR
+        unset  AS
+        unset  LD
+        unset  STRIP
+        unset  RANLIB
+        unset  NM
+
+        unset  HOST_OS
+        unset  HOST_ARCH
+        unset  TARGET_OS
+        unset  TARGET_ARCH
+        unset  HOST
+    else
+        print_help
+        return
+    fi
+}
+
+main $@
+echo "CC     =   $CC"
+echo "CXX    =   $CXX"
+if [ $CC ]; then
+CC_VERSION=`$CC --version 2>&1 | head -n 1`
+echo "$CC_VERSION"
+fi
+echo "AR     =   $AR"
+echo "AS     =   $AS"
+echo "LD     =   $LD"
+echo "STRIP  =   $STRIP"
+echo "RANLIB =   $RANLIB"
+echo "NM     =   $NM"
+
+echo "H_HOST_OS     = $HOST_OS"
+echo "H_HOST_ARCH   = $HOST_ARCH"
+echo "H_TARGET_OS   = $TARGET_OS"
+echo "H_TARGET_ARCH = $TARGET_ARCH"