Skip to content
Open
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
11 changes: 6 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test/lab/*
test/e2e/build/*
test/e2e/server.pid
build/*
tools/builder/finish
desktop.ini
test/lab/*
test/e2e/build/*
test/e2e/server.pid
build/*
tools/builder/finish
21 changes: 16 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ set(lib_src
./src/core/compat/nq_string_util.cpp
./src/core/compat/nq_url_canon_icu.cpp

# platform specific sources
./src/core/platform/nq_jni_android.cpp
./src/core/platform/nq_reachability.cpp
./src/core/platform/nq_reachability_android.cpp
./src/core/platform/nq_platform_thread_win.cpp
)
set(lib_mm_src
./src/core/compat/nq_foundation_util.mm
Expand All @@ -79,14 +81,18 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/tools/deps/third_party/ssl.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/deps/third_party/pb.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/tools/deps/third_party/cares.cmake)
# setup group specific compiler flags
set_source_files_properties(${cares_src} PROPERTIES COMPILE_FLAGS "-DHAVE_CONFIG_H -D_GNU_SOURCE")
if (NQ_WINDOWS)
set_source_files_properties(${cares_src} PROPERTIES COMPILE_FLAGS "-D_GNU_SOURCE -DCARES_BUILDING_LIBRARY")
else()
set_source_files_properties(${cares_src} PROPERTIES COMPILE_FLAGS "-DHAVE_CONFIG_H -D_GNU_SOURCE -DCARES_BUILDING_LIBRARY")
endif()
# define common sources
set(src ${lib_src} ${net_src} ${common_src} ${zlib_src} ${ssl_src} ${pb_src} ${cares_src})



# target settings
if (IOS OR NQ_OSX_BUNDLE OR NQ_OSX)
if (NQ_IOS OR NQ_OSX_BUNDLE OR NQ_OSX)
find_library(core_foundation CoreFoundation)
find_library(cocoa Cocoa)
find_library(iokit IOKit)
Expand All @@ -110,14 +116,19 @@ if (IOS OR NQ_OSX_BUNDLE OR NQ_OSX)
add_library(nq STATIC ${nqsrc})
target_link_libraries(nq ${core_foundation} ${cocoa} ${iokit} ${security} ${system_configuration})
endif()
elseif (ANDROID)
elseif (NQ_ANDROID)
include_directories(ext/cares/config/linux)
set(nqsrc ${src} ${android_src})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ENABLE_EPOLL__")
add_library(nq SHARED ${nqsrc})
target_link_libraries(nq "-lc++_static -llog")
elseif (WINDOWS)
messsage(FATAL_ERROR, "TODO(iyatomi): add windows build instruction")
elseif (NQ_WINDOWS)
include_directories(ext/cares/config/windows)
set(nqsrc ${src} ${win_src})
# windows seems to use CXX_FLAGS for .c files
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOPENSSL_NO_ASM -D__ENABLE_IOCP__")
add_library(nq SHARED ${nqsrc})
target_link_libraries(nq wsock32 ws2_32 winmm imagehlp dbghelp)
elseif (NQ_LINUX)
include_directories(ext/cares/config/linux)
set(nqsrc ${src} ${linux_src})
Expand Down
9 changes: 7 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ DEBUG=False
TEST_DEBUG=True
TEST_SVHOST=127.0.0.1
JOB=4
WINDOWS_GENERATOR=Visual Studio 15 2017

define ct_run
docker run --rm -v `pwd`:/naquid $(BUILDER_IMAGE) sh -c "cd /naquid && $1"
Expand Down Expand Up @@ -40,6 +41,10 @@ linux:
linux_sh:
docker run --name nqsh --rm -ti --privileged --add-host test.qrpc.io:$(TEST_SVHOST) -v `pwd`:/naquid naquid/meta-builder bash || docker exec -ti nqsh bash

windows:
-@mkdir -p build/windows
cd build/windows && cmake -G '$(WINDOWS_GENERATOR)' -DDEBUG:BOOLEAN=$(DEBUG) -DCMAKE_TOOLCHAIN_FILE=$(BUILD_SETTING_PATH)/windows.cmake $(RELATIVE_PROJECT_ROOT)

ios:
-@mkdir -p build/ios.v7
-@mkdir -p build/ios.64
Expand All @@ -53,8 +58,8 @@ android:
-@mkdir -p build/android.v7
-@mkdir -p build/android.64
-@mkdir -p build/android
cd build/android.v7 && cmake -DDEBUG:BOOLEAN=$(DEBUG) -DCMAKE_TOOLCHAIN_FILE=$(ANDROID_NDK)/build/cmake/android.toolchain.cmake -DANDROID_ABI="armeabi-v7a" -DANDROID_NATIVE_API_LEVEL=android-16 -DANDROID_STL=c++_static $(RELATIVE_PROJECT_ROOT) && make -j$(JOB)
cd build/android.64 && cmake -DDEBUG:BOOLEAN=$(DEBUG) -DCMAKE_TOOLCHAIN_FILE=$(ANDROID_NDK)/build/cmake/android.toolchain.cmake -DANDROID_ABI="arm64-v8a" -DANDROID_NATIVE_API_LEVEL=android-16 -DANDROID_STL=c++_static $(RELATIVE_PROJECT_ROOT) && make -j$(JOB)
cd build/android.v7 && cmake -DDEBUG:BOOLEAN=$(DEBUG) -DNQ_ANDROID:BOOLEAN=True -DCMAKE_TOOLCHAIN_FILE=$(ANDROID_NDK)/build/cmake/android.toolchain.cmake -DANDROID_ABI="armeabi-v7a" -DANDROID_NATIVE_API_LEVEL=android-16 -DANDROID_STL=c++_static $(RELATIVE_PROJECT_ROOT) && make -j$(JOB)
cd build/android.64 && cmake -DDEBUG:BOOLEAN=$(DEBUG) -DNQ_ANDROID:BOOLEAN=True -DCMAKE_TOOLCHAIN_FILE=$(ANDROID_NDK)/build/cmake/android.toolchain.cmake -DANDROID_ABI="arm64-v8a" -DANDROID_NATIVE_API_LEVEL=android-16 -DANDROID_STL=c++_static $(RELATIVE_PROJECT_ROOT) && make -j$(JOB)
mv build/android.v7/lib$(LIB).so build/android/lib$(LIB)-armv7.so
mv build/android.64/lib$(LIB).so build/android/lib$(LIB)-arm64.so

Expand Down
7 changes: 1 addition & 6 deletions src/basis/endian.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
#pragma once

#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

#include <algorithm>

#include "basis/defs.h"
#include "basis/syscall.h"

namespace nq {
struct Endian {
Expand Down
2 changes: 1 addition & 1 deletion src/basis/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace logger {
long sec, nsec;
clock::now(sec, nsec);
char tsbuff[32];
sprintf(tsbuff, "%ld.%09ld", sec, nsec);
snprintf(tsbuff, sizeof(tsbuff), "%ld.%09ld", sec, nsec);
mj["_ts"] = tsbuff; //((double)sec) + (((double)nsec) / (1000 * 1000 * 1000));
mj["_id"] = id();
mj["_lv"] = log_level_[lv];
Expand Down
171 changes: 86 additions & 85 deletions src/basis/loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,99 +6,100 @@
#include "basis/io_processor.h"

namespace nq {
class Loop : public LoopImpl, IoProcessor {
IoProcessor **processors_;
int max_nfd_;
LoopImpl::Timeout timeout_;
public:
static const int kMinimumProcessorArraySize = 16;
typedef LoopImpl::Event Event;
Loop() : LoopImpl(), processors_(nullptr), max_nfd_(-1) {}
~Loop() { Close(); }
template <class T> T *ProcessorAt(int fd) { return (T *)processors_[fd]; }
inline int Open(int max_nfd, uint64_t timeout_ns = 1000 * 1000) {
if (max_nfd < kMinimumProcessorArraySize) {
max_nfd = kMinimumProcessorArraySize;
}
max_nfd_ = max_nfd; //TODO: use getrlimit if max_nfd omitted
ToTimeout(timeout_ns, timeout_);
processors_ = (IoProcessor**)std::malloc(sizeof(IoProcessor*) * max_nfd_);
memset(processors_, 0, sizeof(IoProcessor*) * max_nfd_);
return LoopImpl::Open(max_nfd_);
}
inline void Close() {
if (processors_ != nullptr) {
delete []processors_;
class Loop : public LoopImpl, IoProcessor {
IoProcessor **processors_;
int max_nfd_;
LoopImpl::Timeout timeout_;
public:
static const int kMinimumProcessorArraySize = 16;
static const int kWindowsHardFdLimit = 1024;
typedef LoopImpl::Event Event;
Loop() : LoopImpl(), processors_(nullptr), max_nfd_(-1) {}
~Loop() { Close(); }
template <class T> T *ProcessorAt(int fd) { return (T *)processors_[fd]; }
inline int Open(int max_nfd, uint64_t timeout_ns = 1000 * 1000) {
if (max_nfd < kMinimumProcessorArraySize) {
max_nfd = kMinimumProcessorArraySize;
}
max_nfd_ = max_nfd; //TODO: use getrlimit if max_nfd omitted
ToTimeout(timeout_ns, timeout_);
processors_ = (IoProcessor**)std::malloc(sizeof(IoProcessor*) * max_nfd_);
memset(processors_, 0, sizeof(IoProcessor*) * max_nfd_);
return LoopImpl::Open(max_nfd_);
}
inline void Close() {
if (processors_ != nullptr) {
delete []processors_;
processors_ = nullptr;
}
LoopImpl::Close();
}
inline int Add(Fd fd, IoProcessor *h, uint32_t flags) {
int r = h->OnOpen(fd);
if (r < 0) { return r; }
}
LoopImpl::Close();
}
inline int Add(Fd fd, IoProcessor *h, uint32_t flags) {
int r = h->OnOpen(fd);
if (r < 0) { return r; }
CheckAndGrow(fd);
ASSERT(processors_[fd] == nullptr);
processors_[fd] = h;
return LoopImpl::Add(fd, flags);
}
inline int Mod(Fd fd, uint32_t flags) {
ASSERT(fd < max_nfd_ && processors_[fd] != nullptr);
return LoopImpl::Mod(fd, flags);
}
inline int Del(Fd fd) {
ASSERT(fd < max_nfd_ && processors_[fd] != nullptr);
int r = LoopImpl::Del(fd);
if (r >= 0) {
auto h = processors_[fd];
processors_[fd] = nullptr;
h->OnClose(fd);
}
return r;
}
inline int ForceDelWithCheck(Fd fd, IoProcessor *proc) {
if (processors_[fd] == proc) {
if (Del(fd) < 0) {
auto h = processors_[fd];
processors_[fd] = nullptr;
h->OnClose(fd);
}
return NQ_OK;
} else {
return NQ_EGOAWAY; //already fd reused
}
}
inline void Poll() {
Event list[max_nfd_];
int n_list = LoopImpl::Wait(list, max_nfd_, timeout_);
if (n_list <= 0) {
return;
}
for (int i = 0; i < n_list; i++) {
const auto &ev = list[i];
Fd fd = LoopImpl::From(ev);
auto h = processors_[fd];
if (LoopImpl::Closed(ev)) {
processors_[fd] = nullptr;
h->OnClose(fd);
continue;
}
h->OnEvent(fd, ev);
}
}
public: //IoProcessor
void OnEvent(Fd fd, const Event &e) override { Poll(); }
int OnOpen(Fd) override { return NQ_OK; }
void OnClose(Fd) override {}
ASSERT(processors_[fd] == nullptr);
processors_[fd] = h;
return LoopImpl::Add(fd, flags);
}
inline int Mod(Fd fd, uint32_t flags) {
ASSERT(fd < max_nfd_ && processors_[fd] != nullptr);
return LoopImpl::Mod(fd, flags);
}
inline int Del(Fd fd) {
ASSERT(fd < max_nfd_ && processors_[fd] != nullptr);
int r = LoopImpl::Del(fd);
if (r >= 0) {
auto h = processors_[fd];
processors_[fd] = nullptr;
h->OnClose(fd);
}
return r;
}
inline int ForceDelWithCheck(Fd fd, IoProcessor *proc) {
if (processors_[fd] == proc) {
if (Del(fd) < 0) {
auto h = processors_[fd];
processors_[fd] = nullptr;
h->OnClose(fd);
}
return NQ_OK;
} else {
return NQ_EGOAWAY; //already fd reused
}
}
inline void Poll() {
ALLOCA(list, Event, max_nfd_);
int n_list = LoopImpl::Wait(list, max_nfd_, timeout_);
if (n_list <= 0) {
return;
}
for (int i = 0; i < n_list; i++) {
const auto &ev = list[i];
Fd fd = LoopImpl::From(ev);
auto h = processors_[fd];
if (LoopImpl::Closed(ev)) {
processors_[fd] = nullptr;
h->OnClose(fd);
continue;
}
h->OnEvent(fd, ev);
}
}
public: //IoProcessor
void OnEvent(Fd fd, const Event &e) override { Poll(); }
int OnOpen(Fd) override { return NQ_OK; }
void OnClose(Fd) override {}

inline void CheckAndGrow(Fd fd) {
if ((int)fd >= max_nfd_) {
inline void CheckAndGrow(Fd fd) {
if ((int)fd >= max_nfd_) {
int old = max_nfd_;
do {
max_nfd_ <<= 1;
} while (max_nfd_ < (int)fd);
processors_ = (IoProcessor**)std::realloc(processors_, max_nfd_ * sizeof(IoProcessor*));
memset(processors_ + old, 0, sizeof(IoProcessor*) * (max_nfd_ - old));
}
}
};
}
};
}
66 changes: 65 additions & 1 deletion src/basis/loop_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,71 @@ namespace internal {
}
typedef internal::Kqueue LoopImpl;
}
#elif defined(__ENABLE_IOCP__)
namespace nq {
namespace internal {
class IOCP {
protected:
HANDLE fd_;
public:
constexpr static uint32_t EV_READ = 0x01;
constexpr static uint32_t EV_WRITE = 0x02;
typedef struct {
Fd fd;
uint32_t flags;
const char *rb;
socklen_t rb_size;
} Event;
typedef ULONGLONG Timeout;

IOCP() : fd_(INVALID_HANDLE_VALUE) {}

//instance method
inline int Open(int max_nfd) {
fd_ = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0);
return fd_ != INVALID_HANDLE_VALUE ? NQ_ESYSCALL : NQ_OK;
}
inline void Close() {
if (fd_ != INVALID_HANDLE_VALUE) {
CloseHandle(fd_);
fd_ = INVALID_HANDLE_VALUE;
}
}
inline int Errno() { return Syscall::Errno(); }
inline bool EAgain() { return Syscall::EAgain(); }
inline int Add(Fd d, uint32_t flag) {
ASSERT(false);
return NQ_OK;
}
inline int Mod(Fd d, uint32_t flag) {
ASSERT(false);
return NQ_OK;
}
inline int Del(Fd d) {
ASSERT(false);
return NQ_OK;
}
inline int Wait(Event *ev, int size, Timeout &to) {
ASSERT(false);
return NQ_OK;
}

//static method
static inline void InitEvent(Event &e, Fd fd = INVALID_FD) {
e.fd = fd; e.flags = 0;
}
static inline Fd From(const Event &e) { return e.fd; }
static inline bool Readable(const Event &e) { return false; }
static inline bool Writable(const Event &e) { return false; }
/* TODO: not sure about this check */
static inline bool Closed(const Event &e) { return false; }
static inline void ToTimeout(uint64_t timeout_ns, Timeout &to) {
to = timeout_ns / (1000 * 1000);
}
};
}
typedef internal::IOCP LoopImpl;
}
#else //TODO: windows
#error no suitable poller function
//#error no suitable poller function
#endif
Loading