Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Florian Fischer
emper-echo-server
Commits
0d20ba85
Commit
0d20ba85
authored
Nov 05, 2020
by
Florian Fischer
Browse files
add cpp variant
parent
bc4c70ac
Changes
3
Hide whitespace changes
Inline
Side-by-side
meson.build
View file @
0d20ba85
...
...
@@ -8,6 +8,8 @@ project('emper-echo-server', 'c', 'cpp',
'werror=true',
])
add_project_arguments('-Wno-non-virtual-dtor', language: 'cpp')
run_target('iwyu', command: 'tools/check-iwyu')
conf_data = configuration_data()
...
...
src/emper-echo-server.cpp
0 → 100644
View file @
0d20ba85
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright © 2020 Florian Fischer
#include
<errno.h>
#include
<netinet/in.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<sys/socket.h>
#include
<unistd.h>
#include
"AsyncLibrary.hpp"
#include
"Common.hpp"
#include
"Fiber.hpp"
#include
"Runtime.hpp"
#include
"config.h"
static
int
port
=
12345
;
[[
noreturn
]]
static
void
die
(
const
char
*
msg
)
{
perror
(
msg
);
exit
(
EXIT_FAILURE
);
}
#define BUF_MAX 4096
void
client_func
(
void
*
arg
)
{
int
client_fd
=
*
(
int
*
)
arg
;
free
(
arg
);
char
buf
[
BUF_MAX
];
for
(;;)
{
#ifdef USE_ASYNC_IO
ssize_t
bytes_recv
=
io
::
sync_recv
(
client_fd
,
(
void
*
)
&
buf
,
BUF_MAX
,
MSG_WAITALL
);
#else
ssize_t
bytes_recv
=
recv
(
client_fd
,
(
void
*
)
&
buf
,
BUF_MAX
,
MSG_WAITALL
);
#endif
// socket was shutdown
if
(
unlikely
(
bytes_recv
==
0
))
{
return
;
}
if
(
unlikely
(
bytes_recv
==
-
1
))
{
perror
(
"recv failed"
);
if
(
errno
!=
EINTR
)
{
return
;
}
}
// send echo
ssize_t
bytes_send
=
0
;
while
(
bytes_send
<
bytes_recv
)
{
#ifdef USE_ASYNC_IO
ssize_t
new_bytes_send
=
io
::
sync_send
(
client_fd
,
buf
,
bytes_recv
-
bytes_send
,
MSG_NOSIGNAL
);
#else
ssize_t
new_bytes_send
=
send
(
client_fd
,
buf
,
bytes_recv
-
bytes_send
,
MSG_NOSIGNAL
);
#endif
// socket was shutdown
if
(
unlikely
(
bytes_send
==
0
))
{
return
;
}
if
(
unlikely
(
new_bytes_send
==
-
1
))
{
if
(
errno
!=
EINTR
)
{
perror
(
"send failed"
);
return
;
}
}
bytes_send
+=
new_bytes_send
;
}
}
}
#define BACKLOG 5
static
void
welcome_func
()
{
int
sockfd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
sockfd
==
-
1
)
{
die
(
"socket failed"
);
}
struct
sockaddr_in
servaddr
;
memset
(
&
servaddr
,
0
,
sizeof
(
servaddr
));
// NOLINT
// assign IP, PORT
servaddr
.
sin_family
=
AF_INET
;
servaddr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
servaddr
.
sin_port
=
htons
(
port
);
int
reuseaddr
=
1
;
if
(
setsockopt
(
sockfd
,
SOL_SOCKET
,
SO_REUSEADDR
,
&
reuseaddr
,
sizeof
(
reuseaddr
))
==
-
1
)
{
die
(
"setsockopt failed"
);
}
if
(
bind
(
sockfd
,
(
struct
sockaddr
*
)
&
servaddr
,
sizeof
(
servaddr
))
==
-
1
)
{
die
(
"bind failed"
);
}
if
(
listen
(
sockfd
,
BACKLOG
)
!=
0
)
{
die
(
"listen failed"
);
}
Runtime
*
runtime
=
Runtime
::
getRuntime
();
for
(;;)
{
#ifdef USE_ASYNC_IO
int
client_fd
=
io
::
sync_accept
(
sockfd
,
(
struct
sockaddr
*
)
&
servaddr
,
sizeof
(
servaddr
));
#else
socklen_t
address_len
=
sizeof
(
servaddr
);
int
client_fd
=
accept
(
sockfd
,
(
struct
sockaddr
*
)
&
servaddr
,
&
address_len
);
#endif
if
(
unlikely
(
client_fd
<
0
))
{
perror
(
"accept failed"
);
}
int
*
passable_fd
=
reinterpret_cast
<
int
*>
(
malloc
(
sizeof
(
int
)));
if
(
unlikely
(
!
passable_fd
))
{
die
(
"allocating passable fd failed"
);
}
*
passable_fd
=
client_fd
;
Fiber
*
client_fiber
=
Fiber
::
from
(
client_func
,
(
void
*
)
passable_fd
);
runtime
->
schedule
(
*
client_fiber
);
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
if
(
argc
>
2
)
{
const
int
decimal
=
10
;
port
=
(
int
)
strtol
(
argv
[
1
],
nullptr
,
decimal
);
}
Runtime
runtime
;
Fiber
*
welcome_fiber
=
Fiber
::
from
(
&
welcome_func
);
runtime
.
schedule
(
*
welcome_fiber
);
runtime
.
waitUntilFinished
();
}
src/meson.build
View file @
0d20ba85
configure_file(output: 'config.h', configuration: conf_data)
include_dir = include_directories('.')
inc = include_directories('.')
cpp_exe = executable('emper-echo-server',
'emper-echo-server.cpp',
include_directories : [inc],
dependencies: dependencies)
emper_c = emper_proj.get_variable('emper_c')
emper_library_include = emper_proj.get_variable('emper_library_include')
sources = ['emper-echo-server.c']
exe = executable('emper-echo-server',
sources,
include_directories : [include_dir, emper_library_include],
c_exe = executable('emper-echo-server-c',
'emper-echo-server.c',
include_directories : [inc],
dependencies: dependencies,
link_with: emper_c)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment