Skip to content

Commit 93a5197

Browse files
Get client process id over ip/port when server runs on UNIX socket. (#1418)
* handle socket options for UNIX socket same as others * set FD_CLOEXEC by default * invoke `socket_options` callback if set * Offer Client info even on UNIX socket based Server HTTP Request header "REMOTE_PORT" contains client process id if possible when Server works on UNIX socket. * retrigger checks * retrigger checks * add support macOS Co-authored-by: Changbin Park <[email protected]>
1 parent ad7edc7 commit 93a5197

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

httplib.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2601,6 +2601,9 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
26012601
hints.ai_addrlen = static_cast<socklen_t>(
26022602
sizeof(addr) - sizeof(addr.sun_path) + addrlen);
26032603

2604+
fcntl(sock, F_SETFD, FD_CLOEXEC);
2605+
if (socket_options) { socket_options(sock); }
2606+
26042607
if (!bind_or_connect(sock, hints)) {
26052608
close_socket(sock);
26062609
sock = INVALID_SOCKET;
@@ -2871,6 +2874,24 @@ inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
28712874

28722875
if (!getpeername(sock, reinterpret_cast<struct sockaddr *>(&addr),
28732876
&addr_len)) {
2877+
#ifndef _WIN32
2878+
if (addr.ss_family == AF_UNIX) {
2879+
#if defined(__linux__)
2880+
struct ucred ucred;
2881+
socklen_t len = sizeof(ucred);
2882+
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) {
2883+
port = ucred.pid;
2884+
}
2885+
#elif defined(SOL_LOCAL) && defined(SO_PEERPID) // __APPLE__
2886+
pid_t pid;
2887+
socklen_t len = sizeof(pid);
2888+
if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) {
2889+
port = pid;
2890+
}
2891+
#endif
2892+
return;
2893+
}
2894+
#endif
28742895
get_remote_ip_and_port(addr, addr_len, ip, port);
28752896
}
28762897
}

test/test.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5344,6 +5344,31 @@ TEST_F(UnixSocketTest, pathname) {
53445344
t.join();
53455345
}
53465346

5347+
#if defined(__linux__) \
5348+
|| /* __APPLE__ */ (defined(SOL_LOCAL) && defined(SO_PEERPID))
5349+
TEST_F(UnixSocketTest, PeerPid) {
5350+
httplib::Server svr;
5351+
std::string remote_port_val;
5352+
svr.Get(pattern_, [&](const httplib::Request &req, httplib::Response &res) {
5353+
res.set_content(content_, "text/plain");
5354+
remote_port_val = req.get_header_value("REMOTE_PORT");
5355+
});
5356+
5357+
std::thread t {[&] {
5358+
ASSERT_TRUE(svr.set_address_family(AF_UNIX).listen(pathname_, 80)); }};
5359+
while (!svr.is_running()) {
5360+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
5361+
}
5362+
ASSERT_TRUE(svr.is_running());
5363+
5364+
client_GET(pathname_);
5365+
EXPECT_EQ(std::to_string(getpid()), remote_port_val);
5366+
5367+
svr.stop();
5368+
t.join();
5369+
}
5370+
#endif
5371+
53475372
#ifdef __linux__
53485373
TEST_F(UnixSocketTest, abstract) {
53495374
constexpr char svr_path[] {"\x00httplib-server.sock"};

0 commit comments

Comments
 (0)