More wip - TCP, repeated fps, meson / cmake, subproject wrap

server-patch1
Witold Baryluk 3 years ago
parent 5680fff171
commit bc523e7191

@ -145,20 +145,23 @@ configure() {
meson build/meson64 --libdir lib/mangohud/lib --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true -Dld_libdir_abs=true $@ ${CONFIGURE_OPTS}
fi
if [[ ! -f "build/meson32/build.ninja" ]]; then
export CC="gcc -m32"
export CXX="g++ -m32"
export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH_32}"
export LLVM_CONFIG="/usr/bin/llvm-config32"
CC="gcc -m32" \
CFLAGS="-m32"
CXX="g++ -m32" \
CCCFLAGS="-m32"
PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH_32}" \
LLVM_CONFIG="/usr/bin/llvm-config32" \
meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false -Dld_libdir_prefix=true -Dld_libdir_abs=true $@ ${CONFIGURE_OPTS}
fi
}
build() {
if [[ ! -f "build/meson64/build.ninja" ]]; then
if [[ ! -f "build/meson64/build.ninja" ]] || [[ ! -f "build/meson32/build.ninja" ]]; then
configure $@
fi
DESTDIR="$PWD/build/release" ninja -C build/meson32 install
DESTDIR="$PWD/build/release" ninja -C build/meson64 install
DESTDIR="$PWD/build/release" ninja -v -C build/meson64 install
DESTDIR="$PWD/build/release" ninja -v -C build/meson32 install
}
package() {

@ -20,7 +20,9 @@ msg_in.ParseFromString(data)
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib, Gdk, Gio
from gi.repository import Gtk, GLib, Gdk, Gio, GObject
GObject.threads_init()
screen = Gdk.Screen.get_default()
gtk_provider = Gtk.CssProvider()
@ -48,7 +50,8 @@ fps_label = builder.get_object("fps")
app_name_label = builder.get_object("app_name")
api_label = builder.get_object("api")
SOCKET_NAME = "/tmp/9Lq7BNBnBycd6nxy.socket"
SOCKET_NAME = "/tmp/mangohud_server.socket"
ADDRESS = ("localhost", 9869)
import socket
@ -68,26 +71,45 @@ def recv(sock):
return msg
thread = None
stop = False
def connection_thread():
global thread
with socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM | socket.SOCK_CLOEXEC) as sock:
sock.connect(SOCKET_NAME)
stop_ev = threading.Event()
while True:
msg = pb.Message(protocol_version=1, client_type=pb.ClientType.GUI)
send(sock, msg)
def thread_loop(sock):
while not stop and not stop_ev.is_set():
msg = pb.Message(protocol_version=1, client_type=pb.ClientType.GUI)
send(sock, msg)
msg = recv(sock)
print(msg)
msg = recv(sock)
print(msg)
fps = msg.fps
GLib.idle_add(fps_label.set_text, f"{fps:.3f}")
program_name = msg.program_name
GLib.idle_add(app_name_label.set_text, f"{program_name}")
GLib.idle_add(api_label.set_text, f"")
fps = msg.fps
GLib.idle_add(fps_label.set_text, f"{fps:.3f}")
program_name = msg.program_name
GLib.idle_add(app_name_label.set_text, f"{program_name}")
GLib.idle_add(api_label.set_text, f"")
time.sleep(0.05)
time.sleep(0.05)
def connection_thread():
global thread
if True:
addresses = socket.getaddrinfo(ADDRESS[0], ADDRESS[1], proto=socket.IPPROTO_TCP)
assert addresses
address = addresses[0] # (family, type, proto, canonname, sockaddr)
family, type_, proto, canonname, sockaddr = address
assert type_ == socket.SOCK_STREAM
print(f"Connecting to {address}")
with socket.socket(family=family, type=socket.SOCK_STREAM | socket.SOCK_CLOEXEC, proto=proto) as sock:
sock.connect(sockaddr)
thread_loop(sock)
sock.close()
else:
print(f"Connecting to {SOCKET_NAME}")
with socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM | socket.SOCK_CLOEXEC) as sock:
sock.connect(SOCKET_NAME)
thread_loop(sock)
sock.close()
print("Disconnected")
thread = None
@ -100,7 +122,7 @@ def connect(button):
print("Connecting...")
# button.label.set_text("Connecting...")
thread = threading.Thread(target=connection_thread)
thread.daemon = True
# thread.daemon = True # This means to not wait for the thread on exit. Just kill it.
thread.start()
handlers = {
@ -110,9 +132,13 @@ handlers = {
builder.connect_signals(handlers)
window = builder.get_object("window_main")
window.show_all()
window.connect("destroy", Gtk.main_quit)
window.show_all()
Gtk.main()
stop = True
stop_ev.set()

File diff suppressed because one or more lines are too long

@ -59,6 +59,7 @@ if ['windows', 'mingw'].contains(host_machine.system())
)
endif
if is_unixy
vklayer_files += files(
'cpu.cpp',
@ -69,8 +70,6 @@ if is_unixy
'elfhacks.cpp',
'real_dlsym.cpp',
'pci_ids.cpp',
'server/common.c',
'server/mangohud.pb.c',
)
opengl_files = files(
@ -142,6 +141,8 @@ if is_unixy
endif
endif
subdir('server')
link_args = cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro', '-Wl,--exclude-libs,ALL'])
# meson fails to check version-script so just force add
link_args += '-Wl,--version-script,@0@'.format(join_paths(meson.current_source_dir(), 'mangohud.version'))
@ -173,8 +174,9 @@ vklayer_mesa_overlay = shared_library(
dep_pthread,
dep_vulkan,
windows_deps],
include_directories : [inc_common],
link_args : link_args + ['-lprotobuf-nanopb'],
include_directories : [inc_common, 'server'],
link_with : [rpc_common],
link_args : link_args,
install_dir : libdir_mangohud,
install : true
)

@ -6,7 +6,19 @@ set -x
nanopb_generator.py -s type:FT_POINTER mangohud.proto
protoc --python_out=../gui/protos mangohud.proto
#protoc --nanopb_out=./ mangohud.proto
# Instead of -lprotobuf-nanopb
# try these:
# -L/usr/local/lib -lprotobuf-nanopb
# -L/usr/local/lib64 -lprotobuf-nanopb
# /usr/local/lib/libprotobuf-nanopb.a
# /usr/local/lib64/libprotobuf-nanopb.a
# /usr/local/lib32/libprotobuf-nanopb.a
#
# You will need to specifiy proper versions for 64-bit and 32-bit build.
#
# On Debian and Ubuntu, you can just use `-lprotobuf-nanopb`, gcc will find it on its own from standard locations.
# We compile both 64-bit and 32-bit versions, to detect for example incorrect
# use of fprintf string formats (i.e. %ld instead of using %zu for size_t).
@ -18,4 +30,3 @@ g++ -Wall -g -O2 -o client-demo client_demo.cpp common.c mangohud.pb.c -lprotobu
g++ -m32 -Wall -g -O2 -o client-demo_32 client_demo.cpp common.c mangohud.pb.c -lprotobuf-nanopb
ldd client-demo | grep -E 'libgcc_s\.so|libstdc\+\+\.so' && echo "Warning: Linked to C++ runtime"

@ -33,7 +33,7 @@
#define NOTNULL __attribute__ ((nonnull))
#define NOTHROW __attribute__ ((nothrow))
// TODO(baryluk_: Set __attribute((visibility("hidden")) on some?
// TODO(baryluk): Set __attribute((visibility("hidden")) on some?
// static
int set_nonblocking(int fd) {
@ -64,9 +64,14 @@ int client_connect(struct ClientState* client_state) {
if (client_state->fd == 0) {
// Create local socket.
//int data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
retry_socket:
data_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); // | SOCK_NONBLOCK, 0);
// Note: For TCP sockets (AF_INET, AF_INET6 + SOCK_STREAM) we might want SOCK_KEEPALIVE.
if (data_socket == -1) {
if (errno == EINTR) {
goto retry_socket;
}
perror("socket");
return errno; // socket
}
@ -94,11 +99,17 @@ int client_connect(struct ClientState* client_state) {
assert(strlen(SOCKET_NAME) < sizeof(addr.sun_path));
strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);
retry_connect:
if (connect(data_socket, (const struct sockaddr *)&addr,
sizeof(addr)) != 0) {
perror("connect");
DEBUG(fprintf(stderr, "The server is down?\n"));
goto error_2;
if (errno != EINPROGRESS) {
if (errno == EINTR) {
goto retry_connect;
}
perror("connect");
DEBUG(fprintf(stderr, "The server is down?\n"));
goto error_2;
}
}
if (set_nonblocking(data_socket)) {

@ -56,7 +56,9 @@ extern "C" {
// Note: On Linux, the length must be less than 108 bytes
// (including a NULL terminator).
// Some implementations have it as short as 92 bytes.
#define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
//
// TODO(baryluk): Use dynamic name with uid / user.
#define SOCKET_NAME "/tmp/mangohud_server.socket"
#define MUST_USE_RESULT __attribute__ ((warn_unused_result))
#define COLD __attribute__ ((cold))

@ -0,0 +1,24 @@
#!/usr/bin/env python3
import sys
from subprocess import call
from os.path import dirname
from os import makedirs
protoc_path = sys.argv[1]
gen_path = sys.argv[2]
proto_file = sys.argv[3]
options_file = sys.argv[4]
build_dir = sys.argv[5]
source_dir = dirname(proto_file)
makedirs(build_dir, exist_ok=True)
cmdline = [protoc_path, '--plugin=protoc-gen-nanopb=' + gen_path,
'-I' + source_dir,
'--nanopb_out=' + '-f ' + options_file + ':' + build_dir,
proto_file]
sys.stderr.write(" ".join(cmdline) + "\n")
exit(call(cmdline))

@ -208,6 +208,8 @@ typedef struct _Message {
struct _CpuInfoApp *app_cpu_info;
struct _MemInfoApp *app_mem_info;
ClientType *client_type;
pb_size_t clients_count;
struct _Message *clients;
} Message;
typedef struct _RenderInfo {
@ -236,7 +238,7 @@ extern "C" {
#endif
/* Initializer values for message structs */
#define Message_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL}
#define Message_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL}
#define Alive_init_default {NULL}
#define Architecture_init_default {NULL, NULL, NULL, NULL, NULL, NULL}
#define RenderInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL}
@ -255,7 +257,7 @@ extern "C" {
#define GpuInfoApp_init_default {NULL, NULL}
#define CpuInfoApp_init_default {NULL, NULL, NULL}
#define MemInfoApp_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
#define Message_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL}
#define Message_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL}
#define Alive_init_zero {NULL}
#define Architecture_init_zero {NULL, NULL, NULL, NULL, NULL, NULL}
#define RenderInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL}
@ -407,6 +409,7 @@ extern "C" {
#define Message_app_cpu_info_tag 71
#define Message_app_mem_info_tag 73
#define Message_client_type_tag 100
#define Message_clients_tag 200
#define RenderInfo_opengl_tag 1
#define RenderInfo_vulkan_tag 2
#define RenderInfo_opengl_version_tag 10
@ -449,7 +452,8 @@ X(a, POINTER, OPTIONAL, MESSAGE, mem_info, 63) \
X(a, POINTER, REPEATED, MESSAGE, app_gpu_info, 70) \
X(a, POINTER, OPTIONAL, MESSAGE, app_cpu_info, 71) \
X(a, POINTER, OPTIONAL, MESSAGE, app_mem_info, 73) \
X(a, POINTER, SINGULAR, UENUM, client_type, 100)
X(a, POINTER, SINGULAR, UENUM, client_type, 100) \
X(a, POINTER, REPEATED, MESSAGE, clients, 200)
#define Message_CALLBACK NULL
#define Message_DEFAULT NULL
#define Message_alive_MSGTYPE Alive
@ -468,6 +472,7 @@ X(a, POINTER, SINGULAR, UENUM, client_type, 100)
#define Message_app_gpu_info_MSGTYPE GpuInfoApp
#define Message_app_cpu_info_MSGTYPE CpuInfoApp
#define Message_app_mem_info_MSGTYPE MemInfoApp
#define Message_clients_MSGTYPE Message
#define Alive_FIELDLIST(X, a) \
X(a, POINTER, SINGULAR, UINT32, dummy, 1)

@ -88,6 +88,11 @@ message Message {
CpuInfoApp app_cpu_info = 71; // I.e. CPU usage and number of threads by app.
MemInfoApp app_mem_info = 73; // I.e. MEM, stack, swap used by app.
// This is sent to GUI client when they ask for info about all
// connected clients.
repeated Message clients = 200;
// Note.
};

@ -0,0 +1,58 @@
cmake = import('cmake')
nanopb = dependency('nanopb', version : '>=0.4.2', method : 'cmake', modules : ['nanopb::protobuf-nanopb-static'], required : false)
must_regenerate_pb = nanopb.found()
if not nanopb.found()
opt_var = cmake.subproject_options()
opt_var.add_cmake_defines({
#'-DCMAKE_C_COMPILER=' + ,
'nanopb_BUILD_GENERATOR': true,
'BUILD_SHARED_LIBS': false,
'CMAKE_C_FLAGS': '-DPB_ENABLE_MALLOC',
'CMAKE_POSITION_INDEPENDENT_CODE': true,
})
nanopb_proj = cmake.subproject('nanopb', options: opt_var)
nanopb = nanopb_proj.dependency('protobuf-nanopb-static')
endif
rpc_common_sources = files('common.c')
if must_regenerate_pb
protoc = find_program('protoc')
protoc_gen_nanopb = find_program('protoc-gen-nanopb')
gen_pb_py = meson.current_source_dir() + '/gen-pb.py'
mangohud_pb = custom_target('gen-pb',
input : ['mangohud.proto', 'mangohud.options'],
output : ['mangohud.pb.c', 'mangohud.pb.h'],
command : [gen_pb_py, protoc.path(), protoc_gen_nanopb.path(), '@INPUT0@', '@INPUT1@', meson.current_build_dir()])
rpc_common_sources += mangohud_pb
else
rpc_common_sources += 'mangohud.pb.c'
endif
#mangohud_pb = nanopb('mangohud.proto')
rpc_common = static_library(
'common',
rpc_common_sources,
c_args : [
pre_args,
],
cpp_args : [
pre_args,
],
dependencies : [
nanopb,
],
#link_args : ['-lprotobuf-nanopb'],
)
#executable('server', ['server.cpp'], link_with : rpc_common, dependencies : nanopb, install : true)
executable('server', ['server.cpp'], link_with : rpc_common, install : true)
#executable('server', ['server.cpp'], dependencies : [rpc_common, nanopb], install : true)
#executable('client-demo', ['client_demo.cpp'], link_with : rpc_common, dependencies : nanopb)

@ -0,0 +1,18 @@
#!/bin/sh
# This file is used to invoke nanopb_generator.py as a plugin
# to protoc on Linux and other *nix-style systems.
# Use it like this:
# protoc --plugin=nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto
#
# Note that if you use the binary package of nanopb, the protoc
# path is already set up properly and there is no need to give
# --plugin= on the command line.
NANOPB_PATH="../../subprojects/nanopb/generator"
if [ -x "${NANOPB_PATH}/nanopb_generator.py" ]; then
exec python3 "${NANOPB_PATH}/nanopb_generator.py" --protoc-plugin
else
# Try in default PATH.
exec "nanopb_generator.py" --protoc-plugin
fi

@ -11,12 +11,16 @@
#include <fcntl.h>
#include <vector>
#include <signal.h>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <cinttypes>
#include <arpa/inet.h>
#include <netinet/in.h>
#ifndef PB_ENABLE_MALLOC
#define PB_ENABLE_MALLOC
#endif
#include <pb.h>
#include <pb_encode.h>
#include <pb_decode.h>
@ -180,12 +184,17 @@ static void sigint_handler(int sig, siginfo_t *info, void *ucontext) {
static int loop() {
// Create local socket.
retry_unix_socket:
// int connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
int connection_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (connection_socket == -1) {
int connection_unix_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (connection_unix_socket == -1) {
if (errno == EINTR) {
goto retry_unix_socket;
}
return errno; // socket
}
{
struct sockaddr_un name;
memset(&name, 0, sizeof(name));
@ -195,8 +204,8 @@ static int loop() {
strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);
int retry = 1;
retry_bind:
if (bind(connection_socket, (const struct sockaddr *)&name,
retry_unix_bind:
if (bind(connection_unix_socket, (const struct sockaddr *)&name,
sizeof(name)) != 0) {
if (errno == EADDRINUSE && retry > 0) {
retry = 0;
@ -204,28 +213,108 @@ retry_bind:
// sizeof(addr));
unlink(SOCKET_NAME);
goto retry_bind;
goto retry_unix_bind;
}
return errno; // bind
}
}
// AF_INET6 or PF_INET6?
int connection_tcp_socket = socket(AF_INET6, SOCK_STREAM, 0);
if (connection_tcp_socket == -1) {
if (errno == EINTR) {
goto retry_unix_socket;
}
return errno; // socket
}
{
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(sockaddr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(9869);
//addr.sin6_addr = IN6ADDR_ANY_INIT;
addr.sin6_addr = in6addr_any;
if (listen(connection_socket, 20) != 0) {
int retry = 1;
retry_tcp_bind:
if (bind(connection_tcp_socket, (const struct sockaddr *)&addr,
sizeof(addr)) != 0) {
if (errno == EADDRINUSE && retry > 0) {
retry = 0;
//if (connect(data_socket, (const struct sockaddr *) &addr,
// sizeof(addr));
goto retry_tcp_bind;
}
return errno; // bind
}
}
{
int reuse = 1;
setsockopt(connection_tcp_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
}
//{
//int timestamp = 1;
//setsockopt(connection_tcp_socket, SOL_SOCKET, SO_TIMESTAMP, &timestampe, sizeof(timestamp));
//}
if (listen(connection_unix_socket, 20) != 0) {
return errno; // listen
}
fprintf(stderr, "Listening on UNIX socket %s\n", SOCKET_NAME);
if (listen(connection_tcp_socket, 20) != 0) {
return errno; // listen
}
{
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(sockaddr));
socklen_t addr_len = sizeof(addr);
if (getsockname(connection_tcp_socket, (sockaddr*)&addr, &addr_len) == -1) {
perror("getsockname");
}
assert(addr_len <= sizeof(addr));
char addr_str[INET6_ADDRSTRLEN];
addr_str[0] = '\0';
if (inet_ntop(AF_INET6, &addr.sin6_addr, addr_str, sizeof(addr_str))) {
fprintf(stderr, "Listening on TCP socket %s port %d\n", addr_str, ntohs(addr.sin6_port));
} else {
perror("inet_ntop");
}
}
int epollfd = epoll_create1(EPOLL_CLOEXEC);
if (epollfd < 0) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
int dummy_ptr = 0;
int unix_socket_dummy_ptr = 0;
int tcp_socket_dummy_ptr = 0;
{
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = (void*)&unix_socket_dummy_ptr;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connection_unix_socket, &ev) == -1) {
perror("epoll_ctl: connection_socket");
exit(EXIT_FAILURE);
}
}
{
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = (void*)&dummy_ptr;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connection_socket, &ev) == -1) {
ev.data.ptr = (void*)&tcp_socket_dummy_ptr;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, connection_tcp_socket, &ev) == -1) {
perror("epoll_ctl: connection_socket");
exit(EXIT_FAILURE);
}
@ -247,15 +336,98 @@ retry_bind:
}
for (int n = 0; n < nfds; n++) {
if (events[n].data.ptr == &dummy_ptr) {
int data_socket = accept(connection_socket, NULL, NULL);
if (events[n].data.ptr == &unix_socket_dummy_ptr ||
events[n].data.ptr == &tcp_socket_dummy_ptr) {
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(sockaddr));
socklen_t addr_size = sizeof(addr);
int data_socket =
events[n].data.ptr == &unix_socket_dummy_ptr
? accept(connection_unix_socket, NULL, NULL)
: accept4(connection_tcp_socket, (sockaddr*)&addr, &addr_size, SOCK_CLOEXEC);
// accept4(connection_tcp_socket, NULL, NULL, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (data_socket == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
}
if (events[n].data.ptr == &tcp_socket_dummy_ptr) {
if (errno == ENETDOWN || errno == EPROTO ||
errno == ENOPROTOOPT || errno == EHOSTDOWN ||
errno == ENONET || errno == EHOSTUNREACH ||
errno == EOPNOTSUPP || errno == ENETUNREACH) {
continue;
}
}
// EPERM Firewall rules forbid connection. (Linux)
perror("accept");
return errno; // accept
}
fprintf(stderr, "Client connect started\n");
/*
accept4() is a nonstandard Linux extension.
On Linux, the new socket returned by accept() does not inherit file
status flags such as O_NONBLOCK and O_ASYNC from the listening
socket. This behavior differs from the canonical BSD sockets
implementation. Portable programs should not rely on inheritance or
noninheritance of file status flags and always explicitly set all
required flags on the socket returned from accept().
*/
if (events[n].data.ptr == &tcp_socket_dummy_ptr) {
char addr_str[INET6_ADDRSTRLEN];
addr_str[0] = '\0';
if (inet_ntop(AF_INET6, &addr.sin6_addr, addr_str, sizeof(addr_str))) {
fprintf(stderr, "TCP connection from %s port %d\n", addr_str, ntohs(addr.sin6_port));
} else {
perror("inet_ntop");
}
}
if (events[n].data.ptr == &tcp_socket_dummy_ptr) {
{
int keepalive = 1;
setsockopt(data_socket, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive));
}
{
struct linger no_linger;
no_linger.l_onoff = 0;
no_linger.l_linger = 0; // seconds
setsockopt(data_socket, SOL_SOCKET, SO_LINGER, &no_linger, sizeof(no_linger));
}
{
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
socklen_t addr_len = sizeof(addr);
if (getpeername(data_socket, (sockaddr*)&addr, &addr_len) == -1) {
perror("getpeername");
exit(EXIT_FAILURE);
}
assert(addr_len == sizeof(struct sockaddr_in6));
char addr_str[INET6_ADDRSTRLEN];
addr_str[0] = '\0';
if (inet_ntop(AF_INET6, &addr.sin6_addr, addr_str, sizeof(addr_str))) {
fprintf(stderr, "TCP connection from %s port %d\n", addr_str, ntohs(addr.sin6_port));
} else {
perror("inet_ntop");
}
}
}
// IP_TOS , IPTOS_LOWDELAY
if (set_nonblocking(data_socket)) {
goto error_1;
}
@ -375,12 +547,18 @@ error_1:
}
server_states.clear();
if (close(connection_socket) != 0) {
perror("close: connection_socket");
close_tcp_socket:
if (close(connection_tcp_socket) != 0) {
perror("close: connection_tcp_socket");
}
close_unix_socket:
if (close(connection_unix_socket) != 0) {
perror("close: connection_unix_socket");
}
if (unlink(SOCKET_NAME) != 0) {
perror("unlink: socket file");
perror("unlink: unix_socket file");
}
return 0;

@ -0,0 +1,4 @@
[wrap-git]
directory = nanopb
url = https://github.com/nanopb/nanopb
revision = 0.4.4
Loading…
Cancel
Save