2 #include "WaitForExec.hpp"
3 #include "WaitForConn.hpp"
5 #include <netinet/in.h>
7 #include <sys/socket.h>
18 auto Server::createArgv() {
19 auto i
= 0, port
= -1, socket
= -1;
20 auto arr
= new char *[str_args
.size() + dyn_args
.size()*2 + 2] {
21 strdup(binary
.c_str())
24 for (auto &arg
: str_args
) {
25 arr
[++i
] = strdup(arg
.c_str());
28 } else if (arg
== "-s") {
32 for (auto &arg
: dyn_args
) {
33 arr
[++i
] = strdup(arg
.first
.c_str());
34 arr
[++i
] = strdup(arg
.second(arg
.first
).c_str());
35 if (arg
.first
== "-p") {
37 } else if (arg
.first
== "-s") {
45 socket_or_port
= arr
[socket
];
46 } else if (port
> -1) {
47 socket_or_port
= stoi(arr
[port
]);
49 socket_or_port
= 11211;
56 optional
<WaitForConn::conn_t
> Server::createSocket() {
57 sockaddr_storage addr
;
61 if (holds_alternative
<string
>(socket_or_port
)) {
62 const auto path
= get
<string
>(socket_or_port
);
63 const auto safe
= path
.c_str();
64 const auto zlen
= path
.length() + 1;
65 const auto ulen
= sizeof(sockaddr_un
) - sizeof(sa_family_t
);
68 cerr
<< "Server::isListening socket(): path too long '" << path
<< "'\n";
72 if (0 > (sock
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_NONBLOCK
|SOCK_CLOEXEC
, 0))) {
73 perror("Server::isListening socket()");
77 auto sa
= reinterpret_cast<sockaddr_un
*>(&addr
);
78 sa
->sun_family
= AF_UNIX
;
79 strncpy(sa
->sun_path
, safe
, zlen
);
83 if (0 > (sock
= socket(AF_INET
, SOCK_STREAM
|SOCK_NONBLOCK
|SOCK_CLOEXEC
, 0))) {
84 perror("Server::isListening socket()");
88 const auto port
= get
<int>(socket_or_port
);
89 auto sa
= reinterpret_cast<struct sockaddr_in
*>(&addr
);
90 sa
->sin_family
= AF_INET
;
91 sa
->sin_port
= htons(static_cast<unsigned short>(port
)),
92 sa
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
97 return optional
<WaitForConn::conn_t
>{make_tuple(sock
, addr
, size
)};
100 optional
<pid_t
> Server::start() {
105 WaitForExec wait_for_exec
;
107 switch (pid
= fork()) {
109 execvp(binary
.c_str(), createArgv());
112 perror("Server::start fork() & exec()");
116 if (!wait_for_exec()) {
117 cerr
<< "Server::start exec(): incomplete\n";
123 bool Server::isListening(int max_timeout
) {
124 auto conn
= createSocket();
130 WaitForConn wait_for_conn
{
132 Poll
{POLLOUT
, 2, max_timeout
}
134 return wait_for_conn();
137 bool Server::stop() {
141 if (signalled
[SIGTERM
]) {
142 return signal(SIGKILL
);
144 return signal(SIGTERM
);
148 bool Server::signal(int signo
) {
152 signalled
[signo
] += 1;
153 return 0 <= kill(pid
, signo
);
156 bool Server::check() {
160 bool Server::wait(int flags
) {
161 if (pid
&& pid
== waitpid(pid
, &status
, flags
)) {
168 bool Server::tryWait() {
169 return wait(WNOHANG
);