Skip to content

Commit 5c8c120

Browse files
authored
Feature/support windows unicode paths (#158)
1 parent d7f700a commit 5c8c120

File tree

11 files changed

+615
-55
lines changed

11 files changed

+615
-55
lines changed

CMakeLists.txt

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ set(TRANTOR_SOURCES
7575
trantor/utils/MsgBuffer.cc
7676
trantor/utils/SerialTaskQueue.cc
7777
trantor/utils/TimingWheel.cc
78+
trantor/utils/Utilities.cc
7879
trantor/net/EventLoop.cc
7980
trantor/net/EventLoopThread.cc
8081
trantor/net/EventLoopThreadPool.cc
@@ -91,10 +92,27 @@ set(TRANTOR_SOURCES
9192
trantor/net/inner/TimerQueue.cc
9293
trantor/net/inner/poller/EpollPoller.cc
9394
trantor/net/inner/poller/KQueue.cc)
95+
set(private_headers
96+
trantor/net/inner/Acceptor.h
97+
trantor/net/inner/Connector.h
98+
trantor/net/inner/Poller.h
99+
trantor/net/inner/Socket.h
100+
trantor/net/inner/TcpConnectionImpl.h
101+
trantor/net/inner/Timer.h
102+
trantor/net/inner/TimerQueue.h
103+
trantor/net/inner/poller/EpollPoller.h
104+
trantor/net/inner/poller/KQueue.h)
105+
94106

95107
if(WIN32)
96-
set(TRANTOR_SOURCES ${TRANTOR_SOURCES} trantor/utils/WindowsSupport.cc)
97-
set(TRANTOR_SOURCES ${TRANTOR_SOURCES} third_party/wepoll/Wepoll.c)
108+
set(TRANTOR_SOURCES
109+
${TRANTOR_SOURCES}
110+
third_party/wepoll/Wepoll.c
111+
trantor/utils/WindowsSupport.cc)
112+
set(private_headers
113+
${private_headers}
114+
third_party/wepoll/Wepoll.h
115+
trantor/utils/WindowsSupport.h)
98116
endif(WIN32)
99117

100118
find_package(OpenSSL)
@@ -107,11 +125,20 @@ find_package(c-ares)
107125
if(c-ares_FOUND)
108126
message(STATUS "c-ares found!")
109127
target_link_libraries(${PROJECT_NAME} PRIVATE c-ares_lib)
110-
set(TRANTOR_SOURCES ${TRANTOR_SOURCES} trantor/net/inner/AresResolver.cc)
111-
else()
112-
set(TRANTOR_SOURCES ${TRANTOR_SOURCES} trantor/net/inner/NormalResolver.cc)
113-
endif()
114-
target_sources(${PROJECT_NAME} PRIVATE ${TRANTOR_SOURCES})
128+
set(TRANTOR_SOURCES
129+
${TRANTOR_SOURCES}
130+
trantor/net/inner/AresResolver.cc)
131+
set(private_headers
132+
${private_headers}
133+
trantor/net/inner/AresResolver.h)
134+
else(c-ares_FOUND)
135+
set(TRANTOR_SOURCES
136+
${TRANTOR_SOURCES}
137+
trantor/net/inner/NormalResolver.cc)
138+
set(private_headers
139+
${private_headers}
140+
trantor/net/inner/NormalResolver.h)
141+
endif(c-ares_FOUND)
115142

116143
find_package(Threads)
117144
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads)
@@ -170,13 +197,26 @@ set(public_utils_headers
170197
trantor/utils/ObjectPool.h
171198
trantor/utils/SerialTaskQueue.h
172199
trantor/utils/TaskQueue.h
173-
trantor/utils/TimingWheel.h)
200+
trantor/utils/TimingWheel.h
201+
trantor/utils/Utilities.h)
202+
203+
target_sources(${PROJECT_NAME} PRIVATE
204+
${TRANTOR_SOURCES}
205+
${CMAKE_CURRENT_BINARY_DIR}/exports/trantor/exports.h
206+
${public_net_headers}
207+
${public_utils_headers}
208+
${private_headers})
174209

175210
source_group("Public API"
176211
FILES
212+
${CMAKE_CURRENT_BINARY_DIR}/exports/trantor/exports.h
177213
${public_net_headers}
178214
${public_utils_headers})
179215

216+
source_group("Private Headers"
217+
FILES
218+
${private_headers})
219+
180220
install(TARGETS trantor
181221
# IMPORTANT: Add the trantor library to the "export-set"
182222
EXPORT TrantorTargets

trantor/net/TcpConnection.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,16 @@ class TRANTOR_EXPORT TcpConnection
6666
virtual void sendFile(const char *fileName,
6767
size_t offset = 0,
6868
size_t length = 0) = 0;
69-
#ifdef _WIN32
7069
/**
7170
* @brief Send a file to the peer.
7271
*
73-
* @param fileName in UCS-2 (windows only)
72+
* @param fileName in wide string (eg. windows native UCS-2)
7473
* @param offset
7574
* @param length
7675
*/
7776
virtual void sendFile(const wchar_t *fileName,
7877
size_t offset = 0,
7978
size_t length = 0) = 0;
80-
#endif // WIN32
8179

8280
/**
8381
* @brief Get the local address of the connection.

trantor/net/inner/TcpConnectionImpl.cc

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "TcpConnectionImpl.h"
1616
#include "Socket.h"
1717
#include "Channel.h"
18+
#include <trantor/utils/Utilities.h>
1819
#ifdef __linux__
1920
#include <sys/sendfile.h>
2021
#endif
@@ -1271,17 +1272,7 @@ void TcpConnectionImpl::sendFile(const char *fileName,
12711272
{
12721273
assert(fileName);
12731274
#ifdef _WIN32
1274-
// Convert UTF-8 file path to UCS-2
1275-
int nSizeNeeded = ::MultiByteToWideChar(
1276-
CP_UTF8, 0, fileName, (int)strnlen_s(fileName, MAX_PATH), NULL, 0);
1277-
std::wstring wFileName(nSizeNeeded, 0);
1278-
::MultiByteToWideChar(CP_UTF8,
1279-
0,
1280-
fileName,
1281-
(int)strnlen_s(fileName, MAX_PATH),
1282-
&wFileName[0],
1283-
nSizeNeeded);
1284-
sendFile(wFileName.c_str(), offset, length);
1275+
sendFile(utils::toNativePath(fileName).c_str(), offset, length);
12851276
#else // _WIN32
12861277
int fd = open(fileName, O_RDONLY);
12871278

@@ -1307,12 +1298,14 @@ void TcpConnectionImpl::sendFile(const char *fileName,
13071298
#endif // _WIN32
13081299
}
13091300

1310-
#ifdef _WIN32
13111301
void TcpConnectionImpl::sendFile(const wchar_t *fileName,
13121302
size_t offset,
13131303
size_t length)
13141304
{
13151305
assert(fileName);
1306+
#ifndef _WIN32
1307+
sendFile(utils::toNativePath(fileName).c_str(), offset, length);
1308+
#else // _WIN32
13161309
FILE *fp;
13171310
#ifndef _MSC_VER
13181311
fp = _wfopen(fileName, L"rb");
@@ -1339,8 +1332,8 @@ void TcpConnectionImpl::sendFile(const wchar_t *fileName,
13391332
}
13401333

13411334
sendFile(fp, offset, length);
1342-
}
13431335
#endif // _WIN32
1336+
}
13441337

13451338
#ifndef _WIN32
13461339
void TcpConnectionImpl::sendFile(int sfd, size_t offset, size_t length)

trantor/net/inner/TcpConnectionImpl.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,9 @@ class TcpConnectionImpl : public TcpConnection,
115115
virtual void sendFile(const char *fileName,
116116
size_t offset = 0,
117117
size_t length = 0) override;
118-
#ifdef _WIN32
119118
virtual void sendFile(const wchar_t *fileName,
120119
size_t offset = 0,
121120
size_t length = 0) override;
122-
#endif // WIN32
123121

124122
virtual const InetAddress &localAddr() const override
125123
{

trantor/tests/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ add_executable(dns_test DnsTest.cc)
1919
add_executable(delayed_ssl_server_test DelayedSSLServerTest.cc)
2020
add_executable(delayed_ssl_client_test DelayedSSLClientTest.cc)
2121
add_executable(run_on_quit_test RunOnQuitTest.cc)
22+
add_executable(path_conversion_test PathConversionTest.cc)
2223
set(targets_list
2324
ssl_server_test
2425
ssl_client_test
@@ -40,7 +41,8 @@ set(targets_list
4041
dns_test
4142
delayed_ssl_server_test
4243
delayed_ssl_client_test
43-
run_on_quit_test)
44+
run_on_quit_test
45+
path_conversion_test)
4446

4547
set_property(TARGET ${targets_list} PROPERTY CXX_STANDARD 14)
4648
set_property(TARGET ${targets_list} PROPERTY CXX_STANDARD_REQUIRED ON)

trantor/tests/PathConversionTest.cc

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <trantor/utils/Utilities.h>
2+
#include <trantor/utils/Logger.h>
3+
#include <stdlib.h>
4+
5+
int main()
6+
{
7+
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
8+
LOG_DEBUG << "PathConversion utils test!";
9+
10+
#ifdef _WIN32
11+
std::string utf8PathStandard("C:/Temp/\xE4\xB8\xAD\xE6\x96\x87");
12+
std::string utf8PathAlt("C:\\Temp\\\xE4\xB8\xAD\xE6\x96\x87");
13+
std::wstring widePathStandard(L"C:\\Temp\\\u4E2D\u6587");
14+
std::wstring widePathAlt(L"C:/Temp/\u4E2D\u6587");
15+
std::string utf8WidePathStandard{utf8PathAlt};
16+
std::string utf8WidePathAlt{utf8PathStandard};
17+
#else // _WIN32
18+
std::string utf8PathStandard("/tmp/\xE4\xB8\xAD\xE6\x96\x87");
19+
std::string utf8PathAlt(
20+
"\\tmp\\\xE4\xB8\xAD\xE6\x96\x87"); // Invalid, won't be changed
21+
std::wstring widePathStandard(L"/tmp/\u4E2D\u6587");
22+
std::wstring widePathAlt(L"\\tmp\\\u4E2D\u6587");
23+
std::string utf8WidePathStandard{utf8PathStandard};
24+
std::string utf8WidePathAlt{utf8PathAlt};
25+
#endif // _WIN32
26+
27+
// 1. Check from/to UTF-8
28+
#ifdef _WIN32
29+
if (utf8PathAlt != trantor::utils::toUtf8(widePathStandard))
30+
#else // _WIN32
31+
if (utf8PathStandard != trantor::utils::toUtf8(widePathStandard))
32+
#endif // _WIN32
33+
LOG_ERROR << "Error converting " << utf8WidePathStandard
34+
<< " from wide string to utf-8";
35+
#ifdef _WIN32
36+
if (utf8PathStandard != trantor::utils::toUtf8(widePathAlt))
37+
#else // _WIN32
38+
if (utf8PathAlt != trantor::utils::toUtf8(widePathAlt))
39+
#endif // _WIN32
40+
LOG_ERROR << "Error converting " << utf8WidePathAlt
41+
<< " from wide string to utf-8";
42+
#ifdef _WIN32
43+
if (widePathAlt != trantor::utils::fromUtf8(utf8PathStandard))
44+
#else // _WIN32
45+
if (widePathStandard != trantor::utils::fromUtf8(utf8PathStandard))
46+
#endif // _WIN32
47+
LOG_ERROR << "Error converting " << utf8PathStandard
48+
<< " from utf-8 to wide string";
49+
#ifdef _WIN32
50+
if (widePathStandard != trantor::utils::fromUtf8(utf8PathAlt))
51+
#else // _WIN32
52+
if (widePathAlt != trantor::utils::fromUtf8(utf8PathAlt))
53+
#endif // _WIN32
54+
LOG_ERROR << "Error converting " << utf8PathAlt
55+
<< " from utf-8 to wide string";
56+
57+
// 2. Check path conversion. Note: The directory separator should be changed
58+
// on Windows only
59+
if (utf8PathStandard != trantor::utils::fromWidePath(widePathStandard))
60+
LOG_ERROR << "Error converting " << utf8WidePathStandard
61+
<< " from wide path to utf-8";
62+
#ifdef _WIN32
63+
if (utf8PathStandard != trantor::utils::fromWidePath(widePathAlt))
64+
#else // _WIN32
65+
if (utf8PathAlt != trantor::utils::fromWidePath(widePathAlt))
66+
#endif // _WIN32
67+
LOG_ERROR << "Error converting " << utf8WidePathAlt
68+
<< " from wide path to utf-8";
69+
if (widePathStandard != trantor::utils::toWidePath(utf8PathStandard))
70+
LOG_ERROR << "Error converting " << utf8WidePathStandard
71+
<< " from utf-8 to wide path";
72+
#ifdef _WIN32
73+
if (widePathStandard != trantor::utils::toWidePath(utf8PathAlt))
74+
#else // _WIN32
75+
if (widePathAlt != trantor::utils::toWidePath(utf8PathAlt))
76+
#endif // _WIN32
77+
LOG_ERROR << "Error converting " << utf8PathAlt
78+
<< " from utf-8 to wide path";
79+
80+
// 3. From/to native path
81+
auto nativePath1 = trantor::utils::toNativePath(widePathStandard);
82+
auto nativePath2 = trantor::utils::toNativePath(utf8PathStandard);
83+
if (nativePath1 != nativePath2)
84+
LOG_ERROR << "Error converting " << utf8PathStandard
85+
<< " to native path";
86+
if (utf8PathStandard != trantor::utils::fromNativePath(nativePath1))
87+
LOG_ERROR << "Error converting " << utf8PathStandard
88+
<< " from native to utf-8 path";
89+
}

trantor/unittests/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ add_executable(msgbuffer_unittest MsgBufferUnittest.cc)
33
add_executable(inetaddress_unittest InetAddressUnittest.cc)
44
add_executable(date_unittest DateUnittest.cc)
55
add_executable(split_string_unittest splitStringUnittest.cc)
6+
add_executable(string_encoding_unittest stringEncodingUnittest.cc)
67
set(UNITTEST_TARGETS
78
msgbuffer_unittest
89
inetaddress_unittest
910
date_unittest
10-
split_string_unittest)
11+
split_string_unittest
12+
string_encoding_unittest)
1113
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD 14)
1214
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON)
1315
set_property(TARGET ${UNITTEST_TARGETS} PROPERTY CXX_EXTENSIONS OFF)

0 commit comments

Comments
 (0)