Skip to content

Commit 721b3f6

Browse files
committed
Missing header.
1 parent 72e4ee1 commit 721b3f6

File tree

5 files changed

+155
-96
lines changed

5 files changed

+155
-96
lines changed

libraries/http_server/http_server/symbols.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
LI_SYMBOL(id)
3636
#endif
3737

38+
#ifndef LI_SYMBOL_ip
39+
#define LI_SYMBOL_ip
40+
LI_SYMBOL(ip)
41+
#endif
42+
3843
#ifndef LI_SYMBOL_linux_epoll
3944
#define LI_SYMBOL_linux_epoll
4045
LI_SYMBOL(linux_epoll)

libraries/http_server/http_server/tcp_server.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#if not defined(_WIN32)
88
#include <netdb.h>
99
#include <netinet/tcp.h>
10+
#include <arpa/inet.h>
1011
#endif
1112

1213
#include <signal.h>

single_headers/lithium.hh

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6554,6 +6554,11 @@ private:
65546554
LI_SYMBOL(id)
65556555
#endif
65566556

6557+
#ifndef LI_SYMBOL_ip
6558+
#define LI_SYMBOL_ip
6559+
LI_SYMBOL(ip)
6560+
#endif
6561+
65576562
#ifndef LI_SYMBOL_linux_epoll
65586563
#define LI_SYMBOL_linux_epoll
65596564
LI_SYMBOL(linux_epoll)
@@ -7223,60 +7228,76 @@ inline int close_socket(socket_type sock) {
72237228
}
72247229

72257230
// Helper to create a TCP/UDP server socket.
7226-
static socket_type create_and_bind(int port, int socktype) {
7227-
struct addrinfo hints;
7228-
struct addrinfo *result, *rp;
7231+
static socket_type create_and_bind(const char* ip, int port, int socktype) {
72297232
int s;
7230-
72317233
socket_type sfd;
72327234

7233-
char port_str[20];
7234-
snprintf(port_str, sizeof(port_str), "%d", port);
7235-
memset(&hints, 0, sizeof(struct addrinfo));
7236-
7237-
// On windows, setting up the dual-stack mode (ipv4/ipv6 on the same socket).
7238-
// https://docs.microsoft.com/en-us/windows/win32/winsock/dual-stack-sockets
7239-
hints.ai_family = AF_INET6;
7240-
hints.ai_socktype = socktype; /* We want a TCP socket */
7241-
hints.ai_flags = AI_PASSIVE; /* All interfaces */
7242-
7243-
s = getaddrinfo(NULL, port_str, &hints, &result);
7244-
if (s != 0) {
7245-
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
7246-
return -1;
7247-
}
7248-
7249-
for (rp = result; rp != NULL; rp = rp->ai_next) {
7250-
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
7251-
if (sfd == -1)
7252-
continue;
7253-
7254-
// Turn of IPV6_V6ONLY to accept ipv4.
7255-
// https://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
7256-
int ipv6only = 0;
7257-
if(setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)) != 0)
7258-
{
7259-
std::cerr << "FATAL ERROR: setsockopt error when setting IPV6_V6ONLY to 0: " << strerror(errno)
7260-
<< std::endl;
7235+
if (ip == nullptr) {
7236+
// No IP address was specified, find an appropriate one
7237+
struct addrinfo hints;
7238+
struct addrinfo *result, *rp;
7239+
7240+
char port_str[20];
7241+
snprintf(port_str, sizeof(port_str), "%d", port);
7242+
memset(&hints, 0, sizeof(struct addrinfo));
7243+
7244+
// On windows, setting up the dual-stack mode (ipv4/ipv6 on the same socket).
7245+
// https://docs.microsoft.com/en-us/windows/win32/winsock/dual-stack-sockets
7246+
hints.ai_family = AF_INET6;
7247+
hints.ai_socktype = socktype; /* We want a TCP socket */
7248+
hints.ai_flags = AI_PASSIVE; /* All interfaces */
7249+
7250+
s = getaddrinfo(NULL, port_str, &hints, &result);
7251+
if (s != 0) {
7252+
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
7253+
return -1;
72617254
}
72627255

7263-
s = bind(sfd, rp->ai_addr, int(rp->ai_addrlen));
7264-
if (s == 0) {
7265-
/* We managed to bind successfully! */
7266-
break;
7256+
for (rp = result; rp != NULL; rp = rp->ai_next) {
7257+
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
7258+
if (sfd == -1)
7259+
continue;
7260+
7261+
// Turn of IPV6_V6ONLY to accept ipv4.
7262+
// https://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
7263+
int ipv6only = 0;
7264+
if(setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)) != 0)
7265+
{
7266+
std::cerr << "FATAL ERROR: setsockopt error when setting IPV6_V6ONLY to 0: " << strerror(errno)
7267+
<< std::endl;
7268+
}
7269+
7270+
s = bind(sfd, rp->ai_addr, int(rp->ai_addrlen));
7271+
if (s == 0) {
7272+
/* We managed to bind successfully! */
7273+
break;
7274+
}
7275+
else {
7276+
close_socket(sfd);
7277+
}
72677278
}
7268-
else {
7269-
close_socket(sfd);
7279+
7280+
if (rp == NULL) {
7281+
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
7282+
return -1;
72707283
}
7271-
}
72727284

7273-
if (rp == NULL) {
7274-
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
7275-
return -1;
7285+
freeaddrinfo(result);
7286+
} else {
7287+
// Use the user specified IP address
7288+
struct sockaddr_in addr;
7289+
addr.sin_family = AF_INET;
7290+
addr.sin_addr.s_addr = inet_addr(ip);
7291+
addr.sin_port = port;
7292+
7293+
s = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
7294+
if (s != 0) {
7295+
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
7296+
close_socket(sfd);
7297+
return -1;
7298+
}
72767299
}
72777300

7278-
freeaddrinfo(result);
7279-
72807301
#if _WIN32
72817302
u_long set_on = 1;
72827303
auto ret = ioctlsocket(sfd, (long)FIONBIO, &set_on);
@@ -7735,7 +7756,7 @@ void async_fiber_context::reassign_fd_to_this_fiber(int fd) {
77357756
}
77367757

77377758
template <typename H>
7738-
void start_tcp_server(int port, int socktype, int nthreads, H conn_handler,
7759+
void start_tcp_server(std::string ip, int port, int socktype, int nthreads, H conn_handler,
77397760
std::string ssl_key_path = "", std::string ssl_cert_path = "",
77407761
std::string ssl_ciphers = "") {
77417762

@@ -7770,7 +7791,8 @@ void start_tcp_server(int port, int socktype, int nthreads, H conn_handler,
77707791
#endif
77717792

77727793
// Start the server threads.
7773-
int server_fd = impl::create_and_bind(port, socktype);
7794+
const char *listen_ip = !ip.empty() ? ip.c_str() : nullptr;
7795+
int server_fd = impl::create_and_bind(listen_ip, port, socktype);
77747796
std::vector<std::thread> ths;
77757797
for (int i = 0; i < nthreads; i++)
77767798
ths.push_back(std::thread([&] {
@@ -10125,6 +10147,8 @@ void http_serve(api<http_request, http_response> api, int port, O... opts) {
1012510147

1012610148
int nthreads = get_or(options, s::nthreads, std::thread::hardware_concurrency());
1012710149

10150+
std::string ip = get_or(options, s::ip, "");
10151+
1012810152
auto handler = [api](auto& ctx) {
1012910153
http_request rq{ctx};
1013010154
http_response resp(ctx);
@@ -10157,11 +10181,11 @@ void http_serve(api<http_request, http_response> api, int port, O... opts) {
1015710181
std::string ssl_key = options.ssl_key;
1015810182
std::string ssl_cert = options.ssl_certificate;
1015910183
std::string ssl_ciphers = get_or(options, s::ssl_ciphers, "");
10160-
start_tcp_server(port, SOCK_STREAM, nthreads,
10184+
start_tcp_server(ip, port, SOCK_STREAM, nthreads,
1016110185
http_async_impl::make_http_processor(std::move(handler)), ssl_key,
1016210186
ssl_cert, ssl_ciphers);
1016310187
} else {
10164-
start_tcp_server(port, SOCK_STREAM, nthreads,
10188+
start_tcp_server(ip, port, SOCK_STREAM, nthreads,
1016510189
http_async_impl::make_http_processor(std::move(handler)));
1016610190
}
1016710191
date_thread->join();

single_headers/lithium_http_server.hh

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,6 +3374,11 @@ private:
33743374
LI_SYMBOL(id)
33753375
#endif
33763376

3377+
#ifndef LI_SYMBOL_ip
3378+
#define LI_SYMBOL_ip
3379+
LI_SYMBOL(ip)
3380+
#endif
3381+
33773382
#ifndef LI_SYMBOL_linux_epoll
33783383
#define LI_SYMBOL_linux_epoll
33793384
LI_SYMBOL(linux_epoll)
@@ -4043,60 +4048,76 @@ inline int close_socket(socket_type sock) {
40434048
}
40444049

40454050
// Helper to create a TCP/UDP server socket.
4046-
static socket_type create_and_bind(int port, int socktype) {
4047-
struct addrinfo hints;
4048-
struct addrinfo *result, *rp;
4051+
static socket_type create_and_bind(const char* ip, int port, int socktype) {
40494052
int s;
4050-
40514053
socket_type sfd;
40524054

4053-
char port_str[20];
4054-
snprintf(port_str, sizeof(port_str), "%d", port);
4055-
memset(&hints, 0, sizeof(struct addrinfo));
4056-
4057-
// On windows, setting up the dual-stack mode (ipv4/ipv6 on the same socket).
4058-
// https://docs.microsoft.com/en-us/windows/win32/winsock/dual-stack-sockets
4059-
hints.ai_family = AF_INET6;
4060-
hints.ai_socktype = socktype; /* We want a TCP socket */
4061-
hints.ai_flags = AI_PASSIVE; /* All interfaces */
4062-
4063-
s = getaddrinfo(NULL, port_str, &hints, &result);
4064-
if (s != 0) {
4065-
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
4066-
return -1;
4067-
}
4068-
4069-
for (rp = result; rp != NULL; rp = rp->ai_next) {
4070-
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
4071-
if (sfd == -1)
4072-
continue;
4073-
4074-
// Turn of IPV6_V6ONLY to accept ipv4.
4075-
// https://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
4076-
int ipv6only = 0;
4077-
if(setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)) != 0)
4078-
{
4079-
std::cerr << "FATAL ERROR: setsockopt error when setting IPV6_V6ONLY to 0: " << strerror(errno)
4080-
<< std::endl;
4055+
if (ip == nullptr) {
4056+
// No IP address was specified, find an appropriate one
4057+
struct addrinfo hints;
4058+
struct addrinfo *result, *rp;
4059+
4060+
char port_str[20];
4061+
snprintf(port_str, sizeof(port_str), "%d", port);
4062+
memset(&hints, 0, sizeof(struct addrinfo));
4063+
4064+
// On windows, setting up the dual-stack mode (ipv4/ipv6 on the same socket).
4065+
// https://docs.microsoft.com/en-us/windows/win32/winsock/dual-stack-sockets
4066+
hints.ai_family = AF_INET6;
4067+
hints.ai_socktype = socktype; /* We want a TCP socket */
4068+
hints.ai_flags = AI_PASSIVE; /* All interfaces */
4069+
4070+
s = getaddrinfo(NULL, port_str, &hints, &result);
4071+
if (s != 0) {
4072+
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
4073+
return -1;
40814074
}
40824075

4083-
s = bind(sfd, rp->ai_addr, int(rp->ai_addrlen));
4084-
if (s == 0) {
4085-
/* We managed to bind successfully! */
4086-
break;
4076+
for (rp = result; rp != NULL; rp = rp->ai_next) {
4077+
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
4078+
if (sfd == -1)
4079+
continue;
4080+
4081+
// Turn of IPV6_V6ONLY to accept ipv4.
4082+
// https://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
4083+
int ipv6only = 0;
4084+
if(setsockopt(sfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)) != 0)
4085+
{
4086+
std::cerr << "FATAL ERROR: setsockopt error when setting IPV6_V6ONLY to 0: " << strerror(errno)
4087+
<< std::endl;
4088+
}
4089+
4090+
s = bind(sfd, rp->ai_addr, int(rp->ai_addrlen));
4091+
if (s == 0) {
4092+
/* We managed to bind successfully! */
4093+
break;
4094+
}
4095+
else {
4096+
close_socket(sfd);
4097+
}
40874098
}
4088-
else {
4089-
close_socket(sfd);
4099+
4100+
if (rp == NULL) {
4101+
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
4102+
return -1;
40904103
}
4091-
}
40924104

4093-
if (rp == NULL) {
4094-
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
4095-
return -1;
4105+
freeaddrinfo(result);
4106+
} else {
4107+
// Use the user specified IP address
4108+
struct sockaddr_in addr;
4109+
addr.sin_family = AF_INET;
4110+
addr.sin_addr.s_addr = inet_addr(ip);
4111+
addr.sin_port = port;
4112+
4113+
s = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
4114+
if (s != 0) {
4115+
fprintf(stderr, "Could not bind: %s\n", strerror(errno));
4116+
close_socket(sfd);
4117+
return -1;
4118+
}
40964119
}
40974120

4098-
freeaddrinfo(result);
4099-
41004121
#if _WIN32
41014122
u_long set_on = 1;
41024123
auto ret = ioctlsocket(sfd, (long)FIONBIO, &set_on);
@@ -4555,7 +4576,7 @@ void async_fiber_context::reassign_fd_to_this_fiber(int fd) {
45554576
}
45564577

45574578
template <typename H>
4558-
void start_tcp_server(int port, int socktype, int nthreads, H conn_handler,
4579+
void start_tcp_server(std::string ip, int port, int socktype, int nthreads, H conn_handler,
45594580
std::string ssl_key_path = "", std::string ssl_cert_path = "",
45604581
std::string ssl_ciphers = "") {
45614582

@@ -4590,7 +4611,8 @@ void start_tcp_server(int port, int socktype, int nthreads, H conn_handler,
45904611
#endif
45914612

45924613
// Start the server threads.
4593-
int server_fd = impl::create_and_bind(port, socktype);
4614+
const char *listen_ip = !ip.empty() ? ip.c_str() : nullptr;
4615+
int server_fd = impl::create_and_bind(listen_ip, port, socktype);
45944616
std::vector<std::thread> ths;
45954617
for (int i = 0; i < nthreads; i++)
45964618
ths.push_back(std::thread([&] {
@@ -6945,6 +6967,8 @@ void http_serve(api<http_request, http_response> api, int port, O... opts) {
69456967

69466968
int nthreads = get_or(options, s::nthreads, std::thread::hardware_concurrency());
69476969

6970+
std::string ip = get_or(options, s::ip, "");
6971+
69486972
auto handler = [api](auto& ctx) {
69496973
http_request rq{ctx};
69506974
http_response resp(ctx);
@@ -6977,11 +7001,11 @@ void http_serve(api<http_request, http_response> api, int port, O... opts) {
69777001
std::string ssl_key = options.ssl_key;
69787002
std::string ssl_cert = options.ssl_certificate;
69797003
std::string ssl_ciphers = get_or(options, s::ssl_ciphers, "");
6980-
start_tcp_server(port, SOCK_STREAM, nthreads,
7004+
start_tcp_server(ip, port, SOCK_STREAM, nthreads,
69817005
http_async_impl::make_http_processor(std::move(handler)), ssl_key,
69827006
ssl_cert, ssl_ciphers);
69837007
} else {
6984-
start_tcp_server(port, SOCK_STREAM, nthreads,
7008+
start_tcp_server(ip, port, SOCK_STREAM, nthreads,
69857009
http_async_impl::make_http_processor(std::move(handler)));
69867010
}
69877011
date_thread->join();

single_headers/symbols.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@
125125
LI_SYMBOL(id)
126126
#endif
127127

128+
#ifndef LI_SYMBOL_ip
129+
#define LI_SYMBOL_ip
130+
LI_SYMBOL(ip)
131+
#endif
132+
128133
#ifndef LI_SYMBOL_json_encoded
129134
#define LI_SYMBOL_json_encoded
130135
LI_SYMBOL(json_encoded)

0 commit comments

Comments
 (0)