Commit a3ecca2e authored by Adrian Reber's avatar Adrian Reber Committed by Pavel Emelyanov

Move TCP server/client setup code util.c

The page server already knows how to create a TCP server and client. The
code has been hidden behind static-s in page-xfer.c. This commit moves
the common TCP server/client code to util.c to be able to also use it
in the upcoming remote lazy-server/lazy-client userfaultfd enhanced criu.
Signed-off-by: 's avatarAdrian Reber <areber@redhat.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 5cfd96c4
...@@ -283,4 +283,8 @@ char *xsprintf(const char *fmt, ...) ...@@ -283,4 +283,8 @@ char *xsprintf(const char *fmt, ...)
void print_data(unsigned long addr, unsigned char *data, size_t size); void print_data(unsigned long addr, unsigned char *data, size_t size);
int setup_tcp_server(char *type);
int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk);
int setup_tcp_client(char *addr);
#endif /* __CR_UTIL_H__ */ #endif /* __CR_UTIL_H__ */
...@@ -285,28 +285,11 @@ static int page_server_serve(int sk) ...@@ -285,28 +285,11 @@ static int page_server_serve(int sk)
return ret; return ret;
} }
static int get_sockaddr_in(struct sockaddr_in *addr)
{
memset(addr, 0, sizeof(*addr));
addr->sin_family = AF_INET;
if (!opts.addr)
addr->sin_addr.s_addr = INADDR_ANY;
else if (!inet_aton(opts.addr, &addr->sin_addr)) {
pr_perror("Bad page server address");
return -1;
}
addr->sin_port = opts.port;
return 0;
}
int cr_page_server(bool daemon_mode, int cfd) int cr_page_server(bool daemon_mode, int cfd)
{ {
int sk = -1, ask = -1, ret; int ask = -1;
struct sockaddr_in saddr, caddr; int sk = -1;
socklen_t slen = sizeof(saddr); int ret;
socklen_t clen = sizeof(caddr);
up_page_ids_base(); up_page_ids_base();
...@@ -317,70 +300,13 @@ int cr_page_server(bool daemon_mode, int cfd) ...@@ -317,70 +300,13 @@ int cr_page_server(bool daemon_mode, int cfd)
goto no_server; goto no_server;
} }
pr_info("Starting page server on port %u\n", (int)ntohs(opts.port)); sk = setup_tcp_server("page");
if (sk == -1)
sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sk < 0) {
pr_perror("Can't init page server");
return -1; return -1;
}
if (get_sockaddr_in(&saddr))
goto out;
if (bind(sk, (struct sockaddr *)&saddr, slen)) {
pr_perror("Can't bind page server");
goto out;
}
if (listen(sk, 1)) {
pr_perror("Can't listen on page server socket");
goto out;
}
/* Get socket port in case of autobind */
if (opts.port == 0) {
if (getsockname(sk, (struct sockaddr *)&saddr, &slen)) {
pr_perror("Can't get page server name");
goto out;
}
opts.port = ntohs(saddr.sin_port);
pr_info("Using %u port\n", opts.port);
}
no_server: no_server:
if (daemon_mode) { ret = run_tcp_server(daemon_mode, &ask, cfd, sk);
ret = cr_daemon(1, 0, &ask, cfd); if (ret != 0)
if (ret == -1) { return ret;
pr_err("Can't run in the background\n");
goto out;
}
if (ret > 0) { /* parent task, daemon started */
close_safe(&sk);
if (opts.pidfile) {
if (write_pidfile(ret) == -1) {
pr_perror("Can't write pidfile");
kill(ret, SIGKILL);
waitpid(ret, NULL, 0);
return -1;
}
}
return ret;
}
}
if (sk >= 0) {
ret = ask = accept(sk, (struct sockaddr *)&caddr, &clen);
if (ask < 0)
pr_perror("Can't accept connection to server");
else
pr_info("Accepted connection from %s:%u\n",
inet_ntoa(caddr.sin_addr),
(int)ntohs(caddr.sin_port));
close(sk);
}
if (ask >= 0) if (ask >= 0)
ret = page_server_serve(ask); ret = page_server_serve(ask);
...@@ -390,17 +316,12 @@ no_server: ...@@ -390,17 +316,12 @@ no_server:
return ret; return ret;
out:
close(sk);
return -1;
} }
static int page_server_sk = -1; static int page_server_sk = -1;
int connect_to_page_server(void) int connect_to_page_server(void)
{ {
struct sockaddr_in saddr;
if (!opts.use_page_server) if (!opts.use_page_server)
return 0; return 0;
...@@ -410,23 +331,9 @@ int connect_to_page_server(void) ...@@ -410,23 +331,9 @@ int connect_to_page_server(void)
goto out; goto out;
} }
pr_info("Connecting to server %s:%u\n", page_server_sk = setup_tcp_client(opts.addr);
opts.addr, (int)ntohs(opts.port)); if (page_server_sk == -1)
page_server_sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (page_server_sk < 0) {
pr_perror("Can't create socket");
return -1;
}
if (get_sockaddr_in(&saddr))
return -1;
if (connect(page_server_sk, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
pr_perror("Can't connect to server");
return -1; return -1;
}
out: out:
/* /*
* CORK the socket at the very beginning. As per ANK * CORK the socket at the very beginning. As per ANK
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <sys/sendfile.h> #include <sys/sendfile.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <arpa/inet.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
...@@ -1075,3 +1076,131 @@ void print_data(unsigned long addr, unsigned char *data, size_t size) ...@@ -1075,3 +1076,131 @@ void print_data(unsigned long addr, unsigned char *data, size_t size)
pr_msg("|\n"); pr_msg("|\n");
} }
} }
static int get_sockaddr_in(struct sockaddr_in *addr, char *host)
{
memset(addr, 0, sizeof(*addr));
addr->sin_family = AF_INET;
if (!host)
addr->sin_addr.s_addr = INADDR_ANY;
else if (!inet_aton(host, &addr->sin_addr)) {
pr_perror("Bad server address");
return -1;
}
addr->sin_port = opts.port;
return 0;
}
int setup_tcp_server(char *type)
{
int sk = -1;
struct sockaddr_in saddr;
socklen_t slen = sizeof(saddr);
pr_info("Starting %s server on port %u\n", type, (int)ntohs(opts.port));
sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sk < 0) {
pr_perror("Can't init %s server", type);
return -1;
}
if (get_sockaddr_in(&saddr, opts.addr))
goto out;
if (bind(sk, (struct sockaddr *)&saddr, slen)) {
pr_perror("Can't bind %s server", type);
goto out;
}
if (listen(sk, 1)) {
pr_perror("Can't listen on %s server socket", type);
goto out;
}
/* Get socket port in case of autobind */
if (opts.port == 0) {
if (getsockname(sk, (struct sockaddr *)&saddr, &slen)) {
pr_perror("Can't get %s server name", type);
goto out;
}
opts.port = ntohs(saddr.sin_port);
pr_info("Using %u port\n", opts.port);
}
return sk;
out:
close(sk);
return -1;
}
int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk)
{
int ret;
struct sockaddr_in caddr;
socklen_t clen = sizeof(caddr);
if (daemon_mode) {
ret = cr_daemon(1, 0, ask, cfd);
if (ret == -1) {
pr_err("Can't run in the background\n");
goto out;
}
if (ret > 0) { /* parent task, daemon started */
close_safe(&sk);
if (opts.pidfile) {
if (write_pidfile(ret) == -1) {
pr_perror("Can't write pidfile");
kill(ret, SIGKILL);
waitpid(ret, NULL, 0);
return -1;
}
}
return ret;
}
}
if (sk >= 0) {
ret = *ask = accept(sk, (struct sockaddr *)&caddr, &clen);
if (*ask < 0)
pr_perror("Can't accept connection to server");
else
pr_info("Accepted connection from %s:%u\n",
inet_ntoa(caddr.sin_addr),
(int)ntohs(caddr.sin_port));
close(sk);
}
return 0;
out:
close(sk);
return -1;
}
int setup_tcp_client(char *addr)
{
struct sockaddr_in saddr;
int sk;
pr_info("Connecting to server %s:%u\n", addr, (int)ntohs(opts.port));
sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sk < 0) {
pr_perror("Can't create socket");
return -1;
}
if (get_sockaddr_in(&saddr, addr))
return -1;
if (connect(sk, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
pr_perror("Can't connect to server");
return -1;
}
return sk;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment