Skip to content

Commit

Permalink
Add support for Microsoft Visual C++
Browse files Browse the repository at this point in the history
  • Loading branch information
filimonov committed Jan 20, 2022
1 parent b36c87f commit afdb9d2
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 34 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/windows_msvc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Windows

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
BUILD_TYPE: Release
GTEST_FILTER: --gtest_filter=-"*"
CLICKHOUSE_USER: clickhouse_cpp_cicd
CLICKHOUSE_PASSWORD: clickhouse_cpp_cicd
#
# CLICKHOUSE_HOST: localhost
# CLICKHOUSE_PORT: 9000
# CLICKHOUSE_USER: default
# CLICKHOUSE_PASSWORD:
# CLICKHOUSE_DB: default
#
# CLICKHOUSE_SECURE_HOST: github.demo.trial.altinity.cloud
# CLICKHOUSE_SECURE_PORT: 9440
# CLICKHOUSE_SECURE_USER: demo
# CLICKHOUSE_SECURE_PASSWORD: demo
# CLICKHOUSE_SECURE_DB: default
#
# CLICKHOUSE_SECURE2_HOST: gh-api.clickhouse.tech
# CLICKHOUSE_SECURE2_PORT: 9440
# CLICKHOUSE_SECURE2_USER: explorer
# CLICKHOUSE_SECURE2_PASSWORD:
# CLICKHOUSE_SECURE2_DB: default

jobs:
build:
runs-on: windows-latest

steps:
- uses: actions/checkout@v2
- uses: ilammy/msvc-dev-cmd@v1

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Start tls offoader proxy
shell: bash
# that mimics non-secure clickhouse running on localhost
# by tunneling queries to remote tls server
# (needed because we can't start real clickhouse instance on windows)
run: |
choco install wget
wget https://github.com/filimonov/go-tlsoffloader/releases/download/v0.1.2/go-tlsoffloader_0.1.2_Windows_x86_64.tar.gz
tar -xvzf go-tlsoffloader_0.1.2_Windows_x86_64.tar.gz
./go-tlsoffloader.exe -l localhost:9000 -b github.demo.trial.altinity.cloud:9440 &
- name: Test
working-directory: ${{github.workspace}}/build/ut
run: Release\clickhouse-cpp-ut.exe "${{env.GTEST_FILTER}}"
2 changes: 2 additions & 0 deletions clickhouse/base/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#if defined(_win32_) || defined(_win64_)
# define _win_
# define _WIN32_WINNT 0x0600 // The WSAPoll function is defined on Windows Vista and later.
# define WIN32_LEAN_AND_MEAN 1 // don't include too much header automatically
#endif

#if defined(_linux_) || defined (_darwin_)
Expand Down
77 changes: 55 additions & 22 deletions clickhouse/base/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,33 @@
# include <netinet/tcp.h>
# include <signal.h>
# include <unistd.h>
# include <netinet/tcp.h>
#endif

namespace clickhouse {

#if defined(_win_)
char const* windowsErrorCategory::name() const noexcept {
return "WindowsSocketError";
}

std::string windowsErrorCategory::message(int c) const {
char error[UINT8_MAX];
auto len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, static_cast<DWORD>(c), 0, error, sizeof(error), nullptr);
if (len == 0) {
return "unknown";
}
while (len && (error[len - 1] == '\r' || error[len - 1] == '\n')) {
--len;
}
return std::string(error, len);
}

windowsErrorCategory const& windowsErrorCategory::category() {
static windowsErrorCategory c;
return c;
}
#endif

namespace {

class LocalNames : public std::unordered_set<std::string> {
Expand All @@ -37,6 +59,22 @@ class LocalNames : public std::unordered_set<std::string> {
}
};

inline int getSocketErrorCode() {
#if defined(_win_)
return WSAGetLastError();
#else
return errno;
#endif
}

const std::error_category& getErrorCategory() noexcept {
#if defined(_win_)
return windowsErrorCategory::category();
#else
return std::system_category();
#endif
}

void SetNonBlock(SOCKET fd, bool value) {
#if defined(_unix_)
int flags;
Expand All @@ -55,8 +93,7 @@ void SetNonBlock(SOCKET fd, bool value) {
return ioctl(fd, FIOBIO, &flags);
#endif
if (ret == -1) {
throw std::system_error(
errno, std::system_category(), "fail to set nonblocking mode");
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to set nonblocking mode");
}
#elif defined(_win_)
unsigned long inbuf = value;
Expand All @@ -68,8 +105,7 @@ void SetNonBlock(SOCKET fd, bool value) {
}

if (WSAIoctl(fd, FIONBIO, &inbuf, sizeof(inbuf), &outbuf, sizeof(outbuf), &written, 0, 0) == SOCKET_ERROR) {
throw std::system_error(
errno, std::system_category(), "fail to set nonblocking mode");
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to set nonblocking mode");
}
#endif
}
Expand All @@ -94,16 +130,21 @@ SOCKET SocketConnect(const NetworkAddress& addr) {
SetNonBlock(s, true);

if (connect(s, res->ai_addr, (int)res->ai_addrlen) != 0) {
int err = errno;
if (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK) {
int err = getSocketErrorCode();
if (
err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK
#if defined(_win_)
|| err == WSAEWOULDBLOCK || err == WSAEINPROGRESS
#endif
) {
pollfd fd;
fd.fd = s;
fd.events = POLLOUT;
fd.revents = 0;
ssize_t rval = Poll(&fd, 1, 5000);

if (rval == -1) {
throw std::system_error(errno, std::system_category(), "fail to connect");
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to connect");
}
if (rval > 0) {
socklen_t len = sizeof(err);
Expand All @@ -122,11 +163,9 @@ SOCKET SocketConnect(const NetworkAddress& addr) {
}
}
if (last_err > 0) {
throw std::system_error(last_err, std::system_category(), "fail to connect");
throw std::system_error(last_err, getErrorCategory(), "fail to connect");
}
throw std::system_error(
errno, std::system_category(), "fail to connect"
);
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to connect");
}

} // namespace
Expand Down Expand Up @@ -156,7 +195,7 @@ NetworkAddress::NetworkAddress(const std::string& host, const std::string& port)
const int error = getaddrinfo(host.c_str(), port.c_str(), &hints, &info_);

if (error) {
throw std::system_error(errno, std::system_category());
throw std::system_error(getSocketErrorCode(), getErrorCategory());
}
}

Expand Down Expand Up @@ -262,14 +301,10 @@ size_t SocketInput::DoRead(void* buf, size_t len) {
}

if (ret == 0) {
throw std::system_error(
errno, std::system_category(), "closed"
);
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "closed");
}

throw std::system_error(
errno, std::system_category(), "can't receive string data"
);
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "can't receive string data");
}

bool SocketInput::Skip(size_t /*bytes*/) {
Expand All @@ -292,9 +327,7 @@ size_t SocketOutput::DoWrite(const void* data, size_t len) {
#endif

if (::send(s_, (const char*)data, (int)len, flags) != (int)len) {
throw std::system_error(
errno, std::system_category(), "fail to send " + std::to_string(len) + " bytes of data"
);
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to send " + std::to_string(len) + " bytes of data");
}

return len;
Expand Down
15 changes: 13 additions & 2 deletions clickhouse/base/socket.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#include "platform.h"
#include "input.h"
#include "output.h"
#include "platform.h"

#include <cstddef>
#include <string>
Expand All @@ -24,7 +24,7 @@
#endif

#include <memory>

#include <system_error>

struct addrinfo;

Expand All @@ -47,6 +47,17 @@ class NetworkAddress {
struct addrinfo* info_;
};

#if defined(_win_)

class windowsErrorCategory : public std::error_category {
public:
char const* name() const noexcept override final;
std::string message(int c) const override final;

static windowsErrorCategory const& category();
};

#endif

class Socket {
public:
Expand Down
2 changes: 1 addition & 1 deletion tests/simple/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ADD_EXECUTABLE (simple-test
)

TARGET_LINK_LIBRARIES (simple-test
clickhouse-cpp-lib
clickhouse-cpp-lib-static
)

IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
Expand Down
2 changes: 1 addition & 1 deletion ut/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ ADD_EXECUTABLE (clickhouse-cpp-ut
)

TARGET_LINK_LIBRARIES (clickhouse-cpp-ut
clickhouse-cpp-lib
clickhouse-cpp-lib-static
gtest-lib
)
IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
Expand Down
29 changes: 24 additions & 5 deletions ut/tcp_server.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
#include "tcp_server.h"

#include <iostream>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64)
# include <winsock2.h>
#else
# include <netinet/in.h>
# include <sys/socket.h>
# include <unistd.h>
#endif

#include <thread>
#include <unistd.h>

namespace clickhouse {

Expand All @@ -23,7 +29,7 @@ LocalTcpServer::~LocalTcpServer() {
void LocalTcpServer::start() {
//setup a socket
sockaddr_in servAddr;
bzero((char*)&servAddr, sizeof(servAddr));
memset((char*)&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port_);
Expand All @@ -33,7 +39,14 @@ void LocalTcpServer::start() {
throw std::runtime_error("Error establishing server socket");
}
int enable = 1;
if (setsockopt(serverSd_, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) {

#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64)
auto res = setsockopt(serverSd_, SOL_SOCKET, SO_REUSEADDR, (const char*)&enable, sizeof(enable));
#else
auto res = setsockopt(serverSd_, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
#endif

if (res < 0) {
std::cerr << "setsockopt(SO_REUSEADDR) failed" << std::endl;
}
//bind the socket to its local address
Expand All @@ -47,8 +60,14 @@ void LocalTcpServer::start() {

void LocalTcpServer::stop() {
if(serverSd_ > 0) {

#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN64)
shutdown(serverSd_, SD_BOTH);
closesocket(serverSd_);
#else
shutdown(serverSd_, SHUT_RDWR);
close(serverSd_);
#endif
serverSd_ = -1;
}
}
Expand Down
5 changes: 2 additions & 3 deletions ut/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ struct Timer
private:
static auto Now()
{
struct timespec ts;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
return std::chrono::nanoseconds(ts.tv_sec * 1000000000LL + ts.tv_nsec);
std::chrono::nanoseconds ns = std::chrono::high_resolution_clock::now().time_since_epoch();
return ns;
}

private:
Expand Down

0 comments on commit afdb9d2

Please sign in to comment.