Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
f1cac1c5
Commit
f1cac1c5
authored
Mar 03, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove socket_had_rd_shutdown_event
parent
b82ff29c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
364 additions
and
432 deletions
+364
-432
libcaf_io/caf/io/network/default_multiplexer.hpp
libcaf_io/caf/io/network/default_multiplexer.hpp
+62
-278
libcaf_io/src/default_multiplexer.cpp
libcaf_io/src/default_multiplexer.cpp
+302
-154
No files found.
libcaf_io/caf/io/network/default_multiplexer.hpp
View file @
f1cac1c5
...
...
@@ -111,7 +111,7 @@ namespace network {
constexpr
int
ec_interrupted_syscall
=
EINTR
;
#endif
// poll
x
s epoll backend
// poll
v
s epoll backend
#if ! defined(CAF_LINUX) || defined(CAF_POLL_IMPL) // poll() multiplexer
# ifdef CAF_WINDOWS
// From the MSDN: If the POLLPRI flag is set on a socket for the Microsoft
...
...
@@ -181,10 +181,10 @@ bool try_accept(native_socket& result, native_socket fd);
class
default_multiplexer
;
/// A socket IO event handler.
/// A socket I
/
O event handler.
class
event_handler
{
public:
event_handler
(
default_multiplexer
&
dm
);
event_handler
(
default_multiplexer
&
dm
,
native_socket
fd
);
virtual
~
event_handler
();
...
...
@@ -198,7 +198,9 @@ public:
virtual
void
removed_from_loop
(
operation
op
)
=
0
;
/// Returns the native socket handle for this handler.
virtual
native_socket
fd
()
const
=
0
;
inline
native_socket
fd
()
const
{
return
fd_
;
}
/// Returns the `multiplexer` this acceptor belongs to.
inline
default_multiplexer
&
backend
()
{
...
...
@@ -215,46 +217,32 @@ public:
eventbf_
=
value
;
}
protected:
default_multiplexer
&
backend_
;
int
eventbf_
;
};
/// Low-level socket type used as default.
class
default_socket
{
public:
using
socket_type
=
default_socket
;
default_socket
(
default_multiplexer
&
parent
,
native_socket
sock
=
invalid_native_socket
);
default_socket
(
default_socket
&&
other
);
default_socket
&
operator
=
(
default_socket
&&
other
);
~
default_socket
();
void
close_read
();
inline
native_socket
fd
()
const
{
return
fd_
;
/// Checks whether `close_read` has been called.
inline
bool
read_channel_closed
()
const
{
return
read_channel_closed_
;
}
inline
native_socket
native_handle
()
const
{
return
fd_
;
}
/// Closes the read channel of the underlying socket.
void
close_read_channel
();
inline
default_multiplexer
&
backend
()
{
return
parent_
;
}
protected:
void
set_fd_flags
();
private:
default_multiplexer
&
parent_
;
int
eventbf_
;
native_socket
fd_
;
bool
read_channel_closed_
;
default_multiplexer
&
backend_
;
};
/// Low-level socket type used as default.
using
default_socket_acceptor
=
default_socket
;
/// An event handler for the internal event pipe.
class
pipe_reader
:
public
event_handler
{
public:
pipe_reader
(
default_multiplexer
&
dm
);
void
removed_from_loop
(
operation
op
)
override
;
void
handle_event
(
operation
op
)
override
;
void
init
(
native_socket
fd
);
resumable
*
try_read_next
();
};
class
default_multiplexer
:
public
multiplexer
{
public:
...
...
@@ -283,8 +271,6 @@ public:
void
assign_tcp_scribe
(
abstract_broker
*
ptr
,
connection_handle
hdl
)
override
;
connection_handle
add_tcp_scribe
(
abstract_broker
*
,
default_socket_acceptor
&&
);
connection_handle
add_tcp_scribe
(
abstract_broker
*
,
native_socket
fd
)
override
;
connection_handle
add_tcp_scribe
(
abstract_broker
*
,
const
std
::
string
&
h
,
...
...
@@ -295,8 +281,6 @@ public:
void
assign_tcp_doorman
(
abstract_broker
*
ptr
,
accept_handle
hdl
)
override
;
accept_handle
add_tcp_doorman
(
abstract_broker
*
,
default_socket_acceptor
&&
sock
);
accept_handle
add_tcp_doorman
(
abstract_broker
*
,
native_socket
fd
)
override
;
std
::
pair
<
accept_handle
,
uint16_t
>
...
...
@@ -361,39 +345,32 @@ private:
void
handle
(
const
event
&
event
);
bool
socket_had_rd_shutdown_event
(
native_socket
fd
);
void
handle_socket_event
(
native_socket
fd
,
int
mask
,
event_handler
*
ptr
);
void
close_pipe
();
void
wr_dispatch_request
(
resumable
*
ptr
);
resumable
*
rd_dispatch_request
();
//
resumable* rd_dispatch_request();
native_socket
epollfd_
;
// unused in poll() implementation
std
::
vector
<
multiplexer_data
>
pollset_
;
std
::
vector
<
event
>
events_
;
// always sorted by .fd
multiplexer_poll_shadow_data
shadow_
;
std
::
pair
<
native_socket
,
native_socket
>
pipe_
;
pipe_reader
pipe_reader_
;
};
template
<
class
T
>
connection_handle
conn_hdl_from_socket
(
const
T
&
sock
)
{
return
connection_handle
::
from_int
(
int64_from_native_socket
(
sock
.
native_handle
()));
inline
connection_handle
conn_hdl_from_socket
(
native_socket
fd
)
{
return
connection_handle
::
from_int
(
int64_from_native_socket
(
fd
));
}
template
<
class
T
>
accept_handle
accept_hdl_from_socket
(
const
T
&
sock
)
{
return
accept_handle
::
from_int
(
int64_from_native_socket
(
sock
.
native_handle
()));
inline
accept_handle
accept_hdl_from_socket
(
native_socket
fd
)
{
return
accept_handle
::
from_int
(
int64_from_native_socket
(
fd
));
}
/// A stream capable of both reading and writing. The stream's input
/// data is forwarded to its {@link stream_manager manager}.
template
<
class
Socket
>
class
stream
:
public
event_handler
{
public:
/// A smart pointer to a stream manager.
...
...
@@ -403,72 +380,33 @@ public:
/// interface to `std::vector`.
using
buffer_type
=
std
::
vector
<
char
>
;
stream
(
default_multiplexer
&
backend_ref
)
:
event_handler
(
backend_ref
),
sock_
(
backend_ref
),
read_threshold_
(
1
),
collected_
(
0
),
ack_writes_
(
false
),
writing_
(
false
),
written_
(
0
)
{
configure_read
(
receive_policy
::
at_most
(
1024
));
}
/// Returns the IO socket.
Socket
&
socket_handle
()
{
return
sock_
;
}
/// Initializes this stream, setting the socket handle to `fd`.
void
init
(
Socket
sockfd
)
{
sock_
=
std
::
move
(
sockfd
);
}
stream
(
default_multiplexer
&
backend_ref
,
native_socket
sockfd
);
/// Starts reading data from the socket, forwarding incoming data to `mgr`.
void
start
(
const
manager_ptr
&
mgr
)
{
CAF_ASSERT
(
mgr
!=
nullptr
);
reader_
=
mgr
;
backend
().
add
(
operation
::
read
,
sock_
.
fd
(),
this
);
read_loop
();
}
void
removed_from_loop
(
operation
op
)
override
{
switch
(
op
)
{
case
operation
:
:
read
:
reader_
.
reset
();
break
;
case
operation
:
:
write
:
writer_
.
reset
();
break
;
case
operation
:
:
propagate_error
:
break
;
}
}
void
start
(
const
manager_ptr
&
mgr
);
/// Configures how much data will be provided for the next `consume` callback.
/// @warning Must not be called outside the IO multiplexers event loop
/// once the stream has been started.
void
configure_read
(
receive_policy
::
config
config
)
{
rd_flag_
=
config
.
first
;
max_
=
config
.
second
;
}
void
configure_read
(
receive_policy
::
config
config
);
void
ack_writes
(
bool
x
)
{
ack_writes_
=
x
;
}
void
ack_writes
(
bool
x
);
/// Copies data to the write buffer.
/// @warning Not thread safe.
void
write
(
const
void
*
buf
,
size_t
num_bytes
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
num_bytes
));
auto
first
=
reinterpret_cast
<
const
char
*>
(
buf
);
auto
last
=
first
+
num_bytes
;
wr_offline_buf_
.
insert
(
wr_offline_buf_
.
end
(),
first
,
last
);
}
void
write
(
const
void
*
buf
,
size_t
num_bytes
);
/// Returns the write buffer of this stream.
/// @warning Must not be modified outside the IO multiplexers event loop
/// once the stream has been started.
buffer_type
&
wr_buf
()
{
inline
buffer_type
&
wr_buf
()
{
return
wr_offline_buf_
;
}
buffer_type
&
rd_buf
()
{
/// Returns the read buffer of this stream.
/// @warning Must not be modified outside the IO multiplexers event loop
/// once the stream has been started.
inline
buffer_type
&
rd_buf
()
{
return
rd_buf_
;
}
...
...
@@ -476,128 +414,30 @@ public:
/// member function of `mgr` in case of an error.
/// @warning Must not be called outside the IO multiplexers event loop
/// once the stream has been started.
void
flush
(
const
manager_ptr
&
mgr
)
{
CAF_ASSERT
(
mgr
!=
nullptr
);
CAF_LOG_TRACE
(
CAF_ARG
(
wr_offline_buf_
.
size
()));
if
(
!
wr_offline_buf_
.
empty
()
&&
!
writing_
)
{
backend
().
add
(
operation
::
write
,
sock_
.
fd
(),
this
);
writer_
=
mgr
;
writing_
=
true
;
write_loop
();
}
}
void
flush
(
const
manager_ptr
&
mgr
);
void
stop_reading
()
{
CAF_LOG_TRACE
(
""
);
sock_
.
close_read
();
backend
().
del
(
operation
::
read
,
sock_
.
fd
(),
this
);
}
/// Closes the read channel of the underlying socket and removes
/// this handler from its parent.
void
stop_reading
();
void
handle_event
(
operation
op
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
op
));
switch
(
op
)
{
case
operation
:
:
read
:
{
size_t
rb
;
// read bytes
if
(
!
read_some
(
rb
,
sock_
.
fd
(),
rd_buf_
.
data
()
+
collected_
,
rd_buf_
.
size
()
-
collected_
))
{
reader_
->
io_failure
(
&
backend
(),
operation
::
read
);
backend
().
del
(
operation
::
read
,
sock_
.
fd
(),
this
);
}
else
if
(
rb
>
0
)
{
collected_
+=
rb
;
if
(
collected_
>=
read_threshold_
)
{
reader_
->
consume
(
&
backend
(),
rd_buf_
.
data
(),
collected_
);
read_loop
();
}
}
break
;
}
case
operation
:
:
write
:
{
size_t
wb
;
// written bytes
if
(
!
write_some
(
wb
,
sock_
.
fd
(),
wr_buf_
.
data
()
+
written_
,
wr_buf_
.
size
()
-
written_
))
{
writer_
->
io_failure
(
&
backend
(),
operation
::
write
);
backend
().
del
(
operation
::
write
,
sock_
.
fd
(),
this
);
}
else
if
(
wb
>
0
)
{
written_
+=
wb
;
CAF_ASSERT
(
written_
<=
wr_buf_
.
size
());
auto
remaining
=
wr_buf_
.
size
()
-
written_
;
if
(
ack_writes_
)
writer_
->
data_transferred
(
&
backend
(),
wb
,
remaining
+
wr_offline_buf_
.
size
());
// prepare next send (or stop sending)
if
(
remaining
==
0
)
write_loop
();
}
break
;
}
case
operation
:
:
propagate_error
:
if
(
reader_
)
reader_
->
io_failure
(
&
backend
(),
operation
::
read
);
if
(
writer_
)
writer_
->
io_failure
(
&
backend
(),
operation
::
write
);
// backend will delete this handler anyway,
// no need to call backend().del() here
break
;
}
}
void
removed_from_loop
(
operation
op
)
override
;
native_socket
fd
()
const
override
{
return
sock_
.
fd
();
}
void
handle_event
(
operation
op
)
override
;
private:
void
read_loop
()
{
collected_
=
0
;
switch
(
rd_flag_
)
{
case
receive_policy_flag
:
:
exactly
:
if
(
rd_buf_
.
size
()
!=
max_
)
{
rd_buf_
.
resize
(
max_
);
}
read_threshold_
=
max_
;
break
;
case
receive_policy_flag
:
:
at_most
:
if
(
rd_buf_
.
size
()
!=
max_
)
{
rd_buf_
.
resize
(
max_
);
}
read_threshold_
=
1
;
break
;
case
receive_policy_flag
:
:
at_least
:
{
// read up to 10% more, but at least allow 100 bytes more
auto
max_size
=
max_
+
std
::
max
<
size_t
>
(
100
,
max_
/
10
);
if
(
rd_buf_
.
size
()
!=
max_size
)
{
rd_buf_
.
resize
(
max_size
);
}
read_threshold_
=
max_
;
break
;
}
}
}
void
read_loop
();
void
write_loop
()
{
CAF_LOG_TRACE
(
CAF_ARG
(
wr_buf_
.
size
())
<<
CAF_ARG
(
wr_offline_buf_
.
size
()));
written_
=
0
;
wr_buf_
.
clear
();
if
(
wr_offline_buf_
.
empty
())
{
writing_
=
false
;
backend
().
del
(
operation
::
write
,
sock_
.
fd
(),
this
);
}
else
{
wr_buf_
.
swap
(
wr_offline_buf_
);
}
}
void
write_loop
();
// reading & writing
Socket
sock_
;
// reading
// state for reading
manager_ptr
reader_
;
size_t
read_threshold_
;
size_t
collected_
;
size_t
max_
;
receive_policy_flag
rd_flag_
;
buffer_type
rd_buf_
;
// writing
// state for writing
manager_ptr
writer_
;
bool
ack_writes_
;
bool
writing_
;
...
...
@@ -607,101 +447,45 @@ private:
};
/// An acceptor is responsible for accepting incoming connections.
template
<
class
SocketAcceptor
>
class
acceptor
:
public
event_handler
{
public:
using
socket_type
=
typename
SocketAcceptor
::
socket_type
;
/// A manager providing the `accept` member function.
using
manager_type
=
acceptor_manager
;
/// A smart pointer to an acceptor manager.
using
manager_ptr
=
intrusive_ptr
<
manager_type
>
;
acceptor
(
default_multiplexer
&
backend_ref
)
:
event_handler
(
backend_ref
),
accept_sock_
(
backend_ref
),
sock_
(
backend_ref
)
{
// nop
}
/// Returns the IO socket.
SocketAcceptor
&
socket_handle
()
{
return
accept_sock_
;
}
acceptor
(
default_multiplexer
&
backend_ref
,
native_socket
sockfd
);
/// Returns the accepted socket. This member function should
/// be called only from the `new_connection` callback.
socket_type
&
accepted_socket
()
{
inline
native_socket
&
accepted_socket
()
{
return
sock_
;
}
/// Initializes this acceptor, setting the socket handle to `fd`.
void
init
(
SocketAcceptor
sock
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
sock
.
fd
()));
accept_sock_
=
std
::
move
(
sock
);
}
/// Starts this acceptor, forwarding all incoming connections to
/// `manager`. The intrusive pointer will be released after the
/// acceptor has been closed or an IO error occured.
void
start
(
const
manager_ptr
&
mgr
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
()));
CAF_ASSERT
(
mgr
!=
nullptr
);
mgr_
=
mgr
;
backend
().
add
(
operation
::
read
,
accept_sock_
.
fd
(),
this
);
}
void
start
(
const
manager_ptr
&
mgr
);
/// Closes the network connection, thus stopping this acceptor.
void
stop_reading
()
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
()));
backend
().
del
(
operation
::
read
,
accept_sock_
.
fd
(),
this
);
accept_sock_
.
close_read
();
}
/// Closes the network connection and removes this handler from its parent.
void
stop_reading
();
void
handle_event
(
operation
op
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
())
<<
CAF_ARG
(
op
));
if
(
mgr_
&&
op
==
operation
::
read
)
{
native_socket
sockfd
=
invalid_native_socket
;
if
(
try_accept
(
sockfd
,
accept_sock_
.
fd
()))
{
if
(
sockfd
!=
invalid_native_socket
)
{
sock_
=
socket_type
{
backend
(),
sockfd
};
mgr_
->
new_connection
();
}
}
}
}
void
handle_event
(
operation
op
)
override
;
void
removed_from_loop
(
operation
op
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
())
<<
CAF_ARG
(
op
));
if
(
op
==
operation
::
read
)
mgr_
.
reset
();
}
native_socket
fd
()
const
override
{
return
accept_sock_
.
fd
();
}
void
removed_from_loop
(
operation
op
)
override
;
private:
manager_ptr
mgr_
;
SocketAcceptor
accept_sock_
;
socket_type
sock_
;
native_socket
sock_
;
};
native_socket
new_tcp_connection_impl
(
const
std
::
string
&
,
uint16_t
,
maybe
<
protocol
>
=
none
);
default_socket
new_tcp_connection
(
default_multiplexer
&
backend
,
const
std
::
string
&
host
,
uint16_t
port
);
native_socket
new_tcp_connection
(
const
std
::
string
&
host
,
uint16_t
port
,
maybe
<
protocol
>
preferred
=
none
);
std
::
pair
<
native_socket
,
uint16_t
>
new_tcp_acceptor_impl
(
uint16_t
port
,
const
char
*
addr
,
bool
reuse_addr
);
std
::
pair
<
default_socket_acceptor
,
uint16_t
>
new_tcp_acceptor
(
default_multiplexer
&
backend
,
uint16_t
port
,
const
char
*
addr
=
nullptr
,
bool
reuse_addr
=
false
);
}
// namespace network
}
// namespace io
}
// namespace caf
...
...
libcaf_io/src/default_multiplexer.cpp
View file @
f1cac1c5
...
...
@@ -33,7 +33,7 @@
#ifdef CAF_WINDOWS
# include <winsock2.h>
# include <ws2tcpip.h>
/
* socklen_t, et al (MSVC20xx) */
# include <ws2tcpip.h> /
/ socklen_t, etc. (MSVC20xx)
# include <windows.h>
# include <io.h>
#else
...
...
@@ -111,7 +111,7 @@ std::string remote_addr_of_fd(native_socket fd);
uint16_t
remote_port_of_fd
(
native_socket
fd
);
/******************************************************************************
*
platform-dependent implementations
*
*
platform-dependent implementations
*
******************************************************************************/
#ifndef CAF_WINDOWS
...
...
@@ -270,7 +270,7 @@ uint16_t remote_port_of_fd(native_socket fd);
#endif
/******************************************************************************
* epoll()
x
s. poll() *
* epoll()
v
s. poll() *
******************************************************************************/
#ifdef CAF_EPOLL_MULTIPLEXER
...
...
@@ -281,7 +281,8 @@ uint16_t remote_port_of_fd(native_socket fd);
default_multiplexer
::
default_multiplexer
(
actor_system
*
sys
)
:
multiplexer
(
sys
),
epollfd_
(
invalid_native_socket
),
shadow_
(
1
)
{
shadow_
(
1
),
pipe_reader_
(
*
this
)
{
init
();
epollfd_
=
epoll_create1
(
EPOLL_CLOEXEC
);
if
(
epollfd_
==
-
1
)
{
...
...
@@ -291,10 +292,11 @@ uint16_t remote_port_of_fd(native_socket fd);
// handle at most 64 events at a time
pollset_
.
resize
(
64
);
pipe_
=
create_pipe
();
pipe_reader
.
init
(
pipe_
.
first
);
epoll_event
ee
;
ee
.
events
=
input_mask
;
ee
.
data
.
ptr
=
nullpt
r
;
if
(
epoll_ctl
(
epollfd_
,
EPOLL_CTL_ADD
,
pipe_
.
first
,
&
ee
)
<
0
)
{
ee
.
data
.
ptr
=
&
pipe_reade
r
;
if
(
epoll_ctl
(
epollfd_
,
EPOLL_CTL_ADD
,
pipe_
reader
.
fd
()
,
&
ee
)
<
0
)
{
CAF_LOG_ERROR
(
"epoll_ctl: "
<<
strerror
(
errno
));
exit
(
errno
);
}
...
...
@@ -417,16 +419,18 @@ uint16_t remote_port_of_fd(native_socket fd);
default_multiplexer
::
default_multiplexer
(
actor_system
*
sys
)
:
multiplexer
(
sys
),
epollfd_
(
-
1
)
{
epollfd_
(
-
1
),
pipe_reader_
(
*
this
)
{
init
();
// initial setup
pipe_
=
create_pipe
();
pipe_reader_
.
init
(
pipe_
.
first
);
pollfd
pipefd
;
pipefd
.
fd
=
pipe_
.
first
;
pipefd
.
fd
=
pipe_
reader_
.
fd
()
;
pipefd
.
events
=
input_mask
;
pipefd
.
revents
=
0
;
pollset_
.
push_back
(
pipefd
);
shadow_
.
push_back
(
nullptr
);
shadow_
.
push_back
(
&
pipe_reader_
);
}
void
default_multiplexer
::
run
()
{
...
...
@@ -626,21 +630,6 @@ void default_multiplexer::wr_dispatch_request(resumable* ptr) {
}
}
resumable
*
default_multiplexer
::
rd_dispatch_request
()
{
intptr_t
ptrval
;
// on windows, we actually have sockets, otherwise we have file handles
# ifdef CAF_WINDOWS
auto
res
=
recv
(
pipe_
.
first
,
reinterpret_cast
<
socket_recv_ptr
>
(
&
ptrval
),
sizeof
(
ptrval
),
0
);
# else
auto
res
=
read
(
pipe_
.
first
,
&
ptrval
,
sizeof
(
ptrval
));
# endif
if
(
res
!=
sizeof
(
ptrval
))
{
return
nullptr
;
}
return
reinterpret_cast
<
resumable
*>
(
ptrval
);;
}
multiplexer
::
supervisor_ptr
default_multiplexer
::
make_supervisor
()
{
class
impl
:
public
multiplexer
::
supervisor
{
public:
...
...
@@ -662,63 +651,29 @@ void default_multiplexer::close_pipe() {
del
(
operation
::
read
,
pipe_
.
first
,
nullptr
);
}
bool
default_multiplexer
::
socket_had_rd_shutdown_event
(
native_socket
fd
)
{
auto
last
=
events_
.
end
();
auto
i
=
std
::
lower_bound
(
events_
.
begin
(),
last
,
fd
,
event_less
{});
if
(
i
!=
last
&&
i
->
fd
==
fd
)
{
// socket is about to be shut down for read if
// its new bitmask does not have the input_mask flag
return
(
i
->
mask
&
input_mask
)
==
0
;
}
return
false
;
}
void
default_multiplexer
::
handle_socket_event
(
native_socket
fd
,
int
mask
,
event_handler
*
ptr
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
fd
)
<<
CAF_ARG
(
mask
));
CAF_ASSERT
(
ptr
!=
nullptr
);
bool
checkerror
=
true
;
// ignore read events if a previous event caused
// this socket to be shut down for reading
if
((
mask
&
input_mask
)
&&
!
socket_had_rd_shutdown_event
(
fd
))
{
if
(
mask
&
input_mask
)
{
checkerror
=
false
;
if
(
ptr
)
{
// ignore read events if a previous event caused
// this socket to be shut down for reading
if
(
!
ptr
->
read_channel_closed
())
ptr
->
handle_event
(
operation
::
read
);
}
else
{
CAF_ASSERT
(
fd
==
pipe_
.
first
);
CAF_LOG_DEBUG
(
"read message from pipe"
);
auto
cb
=
rd_dispatch_request
();
switch
(
cb
->
resume
(
this
,
max_throughput
()))
{
case
resumable
:
:
resume_later
:
exec_later
(
cb
);
break
;
case
resumable
:
:
done
:
intrusive_ptr_release
(
cb
);
break
;
default:
;
// ignored
}
}
}
if
(
mask
&
output_mask
)
{
// we do *never* register our pipe handle for writing
CAF_ASSERT
(
ptr
!=
nullptr
);
checkerror
=
false
;
ptr
->
handle_event
(
operation
::
write
);
}
if
(
checkerror
&&
(
mask
&
error_mask
))
{
if
(
ptr
)
{
CAF_LOG_DEBUG
(
"error occured on socket:"
<<
CAF_ARG
(
fd
)
<<
CAF_ARG
(
last_socket_error
())
<<
CAF_ARG
(
last_socket_error_as_string
()));
ptr
->
handle_event
(
operation
::
propagate_error
);
del
(
operation
::
read
,
fd
,
ptr
);
del
(
operation
::
write
,
fd
,
ptr
);
}
else
{
CAF_LOG_DEBUG
(
"pipe has been closed, assume shutdown"
);
// a pipe failure means we are in the process
// of shutting down the middleman
del
(
operation
::
read
,
fd
,
nullptr
);
}
CAF_LOG_DEBUG
(
"error occured on socket:"
<<
CAF_ARG
(
fd
)
<<
CAF_ARG
(
last_socket_error
())
<<
CAF_ARG
(
last_socket_error_as_string
()));
ptr
->
handle_event
(
operation
::
propagate_error
);
del
(
operation
::
read
,
fd
,
ptr
);
del
(
operation
::
write
,
fd
,
ptr
);
}
}
...
...
@@ -732,24 +687,26 @@ void default_multiplexer::init() {
}
default_multiplexer
::~
default_multiplexer
()
{
if
(
epollfd_
!=
invalid_native_socket
)
{
if
(
epollfd_
!=
invalid_native_socket
)
closesocket
(
epollfd_
);
}
// close write handle first
closesocket
(
pipe_
.
second
);
// flush pipe before closing it
nonblocking
(
pipe_
.
first
,
true
);
auto
ptr
=
rd_dispatch_reques
t
();
auto
ptr
=
pipe_reader_
.
try_read_nex
t
();
while
(
ptr
)
{
intrusive_ptr_release
(
ptr
);
ptr
=
rd_dispatch_reques
t
();
ptr
=
pipe_reader_
.
try_read_nex
t
();
}
closesocket
(
pipe_
.
first
);
// do cleanup for pipe reader manually, since WSACleanup needs to happen last
closesocket
(
pipe_reader_
.
fd
());
pipe_reader_
.
init
(
invalid_native_socket
);
# ifdef CAF_WINDOWS
WSACleanup
();
# endif
}
void
default_multiplexer
::
exec_later
(
resumable
*
ptr
)
{
CAF_ASSERT
(
ptr
);
CAF_ASSERT
(
ptr
->
as_ref_counted_ptr
()
->
get_reference_count
()
>
0
);
...
...
@@ -764,20 +721,21 @@ void default_multiplexer::exec_later(resumable* ptr) {
}
connection_handle
default_multiplexer
::
add_tcp_scribe
(
abstract_broker
*
self
,
default_socket
&&
sock
)
{
native_socket
fd
)
{
CAF_LOG_TRACE
(
""
);
class
impl
:
public
scribe
{
public:
impl
(
abstract_broker
*
ptr
,
default_
socket
&&
s
)
:
scribe
(
ptr
,
network
::
conn_hdl_from_socket
(
s
)),
impl
(
abstract_broker
*
ptr
,
default_
multiplexer
&
ref
,
native_socket
sockfd
)
:
scribe
(
ptr
,
network
::
conn_hdl_from_socket
(
s
ockfd
)),
launched_
(
false
),
stream_
(
s
.
backend
()
)
{
stream_
.
init
(
std
::
move
(
s
));
stream_
(
ref
,
sockfd
)
{
// nop
}
void
configure_read
(
receive_policy
::
config
config
)
override
{
CAF_LOG_TRACE
(
""
);
stream_
.
configure_read
(
config
);
if
(
!
launched_
)
launch
();
if
(
!
launched_
)
launch
();
}
void
ack_writes
(
bool
enable
)
override
{
CAF_LOG_TRACE
(
CAF_ARG
(
enable
));
...
...
@@ -812,24 +770,23 @@ connection_handle default_multiplexer::add_tcp_scribe(abstract_broker* self,
}
private:
bool
launched_
;
stream
<
default_socket
>
stream_
;
stream
stream_
;
};
auto
ptr
=
make_counted
<
impl
>
(
self
,
std
::
move
(
sock
)
);
auto
ptr
=
make_counted
<
impl
>
(
self
,
*
this
,
fd
);
self
->
add_scribe
(
ptr
);
return
ptr
->
hdl
();
}
accept_handle
default_multiplexer
::
add_tcp_doorman
(
abstract_broker
*
self
,
default_socket_acceptor
&&
sock
)
{
accept_handle
default_multiplexer
::
add_tcp_doorman
(
abstract_broker
*
self
,
native_socket
fd
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
sock
.
fd
()));
CAF_ASSERT
(
sock
.
fd
()
!=
network
::
invalid_native_socket
);
class
impl
:
public
doorman
{
public:
impl
(
abstract_broker
*
ptr
,
default_
socket_acceptor
&&
s
)
:
doorman
(
ptr
,
network
::
accept_hdl_from_socket
(
s
)),
acceptor_
(
s
.
backend
()
)
{
acceptor_
.
init
(
std
::
move
(
s
));
impl
(
abstract_broker
*
ptr
,
default_
multiplexer
&
ref
,
native_socket
sockfd
)
:
doorman
(
ptr
,
network
::
accept_hdl_from_socket
(
s
ockfd
)),
acceptor_
(
ref
,
sockfd
)
{
// nop
}
void
new_connection
()
override
{
CAF_LOG_TRACE
(
""
);
...
...
@@ -854,16 +811,16 @@ default_multiplexer::add_tcp_doorman(abstract_broker* self,
return
local_port_of_fd
(
acceptor_
.
fd
());
}
private:
network
::
acceptor
<
default_socket_acceptor
>
acceptor_
;
network
::
acceptor
acceptor_
;
};
auto
ptr
=
make_counted
<
impl
>
(
self
,
std
::
move
(
sock
)
);
auto
ptr
=
make_counted
<
impl
>
(
self
,
*
this
,
fd
);
self
->
add_doorman
(
ptr
);
return
ptr
->
hdl
();
}
connection_handle
default_multiplexer
::
new_tcp_scribe
(
const
std
::
string
&
host
,
uint16_t
port
)
{
auto
fd
=
new_tcp_connection
_impl
(
host
,
port
);
auto
fd
=
new_tcp_connection
(
host
,
port
);
return
connection_handle
::
from_int
(
int64_from_native_socket
(
fd
));
}
...
...
@@ -873,17 +830,12 @@ void default_multiplexer::assign_tcp_scribe(abstract_broker* self,
add_tcp_scribe
(
self
,
static_cast
<
native_socket
>
(
hdl
.
id
()));
}
connection_handle
default_multiplexer
::
add_tcp_scribe
(
abstract_broker
*
self
,
native_socket
fd
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
self
->
id
())
<<
CAF_ARG
(
fd
));
return
add_tcp_scribe
(
self
,
default_socket
{
*
this
,
fd
});
}
connection_handle
default_multiplexer
::
add_tcp_scribe
(
abstract_broker
*
self
,
const
std
::
string
&
host
,
uint16_t
port
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
self
->
id
())
<<
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
));
return
add_tcp_scribe
(
self
,
new_tcp_connection
(
*
this
,
host
,
port
));
return
add_tcp_scribe
(
self
,
new_tcp_connection
(
host
,
port
));
}
std
::
pair
<
accept_handle
,
uint16_t
>
...
...
@@ -899,17 +851,12 @@ void default_multiplexer::assign_tcp_doorman(abstract_broker* ptr,
add_tcp_doorman
(
ptr
,
static_cast
<
native_socket
>
(
hdl
.
id
()));
}
accept_handle
default_multiplexer
::
add_tcp_doorman
(
abstract_broker
*
self
,
native_socket
fd
)
{
return
add_tcp_doorman
(
self
,
default_socket_acceptor
{
*
this
,
fd
});
}
std
::
pair
<
accept_handle
,
uint16_t
>
default_multiplexer
::
add_tcp_doorman
(
abstract_broker
*
self
,
uint16_t
port
,
const
char
*
host
,
bool
reuse_addr
)
{
auto
acceptor
=
new_tcp_acceptor
(
*
this
,
port
,
host
,
reuse_addr
);
auto
acceptor
=
new_tcp_acceptor
_impl
(
port
,
host
,
reuse_addr
);
auto
bound_port
=
acceptor
.
second
;
return
{
add_tcp_doorman
(
self
,
std
::
move
(
acceptor
.
first
)
),
bound_port
};
return
{
add_tcp_doorman
(
self
,
acceptor
.
first
),
bound_port
};
}
/******************************************************************************
...
...
@@ -975,52 +922,268 @@ bool try_accept(native_socket& result, native_socket fd) {
return
true
;
}
event_handler
::
event_handler
(
default_multiplexer
&
dm
)
:
backend_
(
dm
),
eventbf_
(
0
)
{
// nop
event_handler
::
event_handler
(
default_multiplexer
&
dm
,
native_socket
sockfd
)
:
eventbf_
(
0
),
fd_
(
sockfd
),
read_channel_closed_
(
false
),
backend_
(
dm
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
sockfd
));
set_fd_flags
();
}
event_handler
::~
event_handler
()
{
if
(
fd_
!=
invalid_native_socket
)
closesocket
(
fd_
);
}
void
event_handler
::
close_read_channel
()
{
if
(
fd_
==
invalid_native_socket
||
read_channel_closed_
)
return
;
::
shutdown
(
fd_
,
0
);
// 0 identifies the read channel on Win & UNIX
read_channel_closed_
=
true
;
}
void
event_handler
::
set_fd_flags
()
{
if
(
fd_
==
invalid_native_socket
)
return
;
// enable nonblocking IO, disable Nagle's algorithm, and suppress SIGPIPE
nonblocking
(
fd_
,
true
);
tcp_nodelay
(
fd_
,
true
);
allow_sigpipe
(
fd_
,
false
);
}
pipe_reader
::
pipe_reader
(
default_multiplexer
&
dm
)
:
event_handler
(
dm
,
invalid_native_socket
)
{
// nop
}
default_socket
::
default_socket
(
default_multiplexer
&
ref
,
native_socket
sockfd
)
:
parent_
(
ref
),
fd_
(
sockfd
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
sockfd
));
if
(
sockfd
!=
invalid_native_socket
)
{
// enable nonblocking IO, disable Nagle's algorithm, and suppress SIGPIPE
nonblocking
(
fd_
,
true
);
tcp_nodelay
(
fd_
,
true
);
allow_sigpipe
(
fd_
,
false
);
void
pipe_reader
::
removed_from_loop
(
operation
)
{
// nop
}
resumable
*
pipe_reader
::
try_read_next
()
{
intptr_t
ptrval
;
// on windows, we actually have sockets, otherwise we have file handles
# ifdef CAF_WINDOWS
auto
res
=
recv
(
fd
(),
reinterpret_cast
<
socket_recv_ptr
>
(
&
ptrval
),
sizeof
(
ptrval
),
0
);
# else
auto
res
=
read
(
fd
(),
&
ptrval
,
sizeof
(
ptrval
));
# endif
if
(
res
!=
sizeof
(
ptrval
))
return
nullptr
;
return
reinterpret_cast
<
resumable
*>
(
ptrval
);
}
void
pipe_reader
::
handle_event
(
operation
op
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
op
));
switch
(
op
)
{
case
operation
:
:
read
:
{
auto
cb
=
try_read_next
();
switch
(
cb
->
resume
(
&
backend
(),
backend
().
max_throughput
()))
{
case
resumable
:
:
resume_later
:
backend
().
exec_later
(
cb
);
break
;
case
resumable
:
:
done
:
intrusive_ptr_release
(
cb
);
break
;
default:
;
// ignored
}
break
;
}
default:
// nop (simply ignore errors)
break
;
}
}
default_socket
::
default_socket
(
default_socket
&&
other
)
:
parent_
(
other
.
parent_
),
fd_
(
other
.
fd_
)
{
other
.
fd_
=
invalid_native_socket
;
void
pipe_reader
::
init
(
native_socket
fd
)
{
fd_
=
fd
;
}
default_socket
&
default_socket
::
operator
=
(
default_socket
&&
other
)
{
std
::
swap
(
fd_
,
other
.
fd_
);
return
*
this
;
stream
::
stream
(
default_multiplexer
&
backend_ref
,
native_socket
sockfd
)
:
event_handler
(
backend_ref
,
sockfd
),
read_threshold_
(
1
),
collected_
(
0
),
ack_writes_
(
false
),
writing_
(
false
),
written_
(
0
)
{
configure_read
(
receive_policy
::
at_most
(
1024
));
}
default_socket
::~
default_socket
()
{
if
(
fd_
!=
invalid_native_socket
)
{
CAF_LOG_DEBUG
(
"close socket:"
<<
CAF_ARG
(
fd_
));
closesocket
(
fd_
);
void
stream
::
start
(
const
manager_ptr
&
mgr
)
{
CAF_ASSERT
(
mgr
!=
nullptr
);
reader_
=
mgr
;
backend
().
add
(
operation
::
read
,
fd
(),
this
);
read_loop
();
}
void
stream
::
configure_read
(
receive_policy
::
config
config
)
{
rd_flag_
=
config
.
first
;
max_
=
config
.
second
;
}
void
stream
::
ack_writes
(
bool
x
)
{
ack_writes_
=
x
;
}
void
stream
::
write
(
const
void
*
buf
,
size_t
num_bytes
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
num_bytes
));
auto
first
=
reinterpret_cast
<
const
char
*>
(
buf
);
auto
last
=
first
+
num_bytes
;
wr_offline_buf_
.
insert
(
wr_offline_buf_
.
end
(),
first
,
last
);
}
void
stream
::
flush
(
const
manager_ptr
&
mgr
)
{
CAF_ASSERT
(
mgr
!=
nullptr
);
CAF_LOG_TRACE
(
CAF_ARG
(
wr_offline_buf_
.
size
()));
if
(
!
wr_offline_buf_
.
empty
()
&&
!
writing_
)
{
backend
().
add
(
operation
::
write
,
fd
(),
this
);
writer_
=
mgr
;
writing_
=
true
;
write_loop
();
}
}
void
stream
::
stop_reading
()
{
CAF_LOG_TRACE
(
""
);
close_read_channel
();
backend
().
del
(
operation
::
read
,
fd
(),
this
);
}
void
stream
::
removed_from_loop
(
operation
op
)
{
switch
(
op
)
{
case
operation
:
:
read
:
reader_
.
reset
();
break
;
case
operation
:
:
write
:
writer_
.
reset
();
break
;
case
operation
:
:
propagate_error
:
break
;
}
}
void
stream
::
handle_event
(
operation
op
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
op
));
switch
(
op
)
{
case
operation
:
:
read
:
{
size_t
rb
;
// read bytes
if
(
!
read_some
(
rb
,
fd
(),
rd_buf_
.
data
()
+
collected_
,
rd_buf_
.
size
()
-
collected_
))
{
reader_
->
io_failure
(
&
backend
(),
operation
::
read
);
backend
().
del
(
operation
::
read
,
fd
(),
this
);
}
else
if
(
rb
>
0
)
{
collected_
+=
rb
;
if
(
collected_
>=
read_threshold_
)
{
reader_
->
consume
(
&
backend
(),
rd_buf_
.
data
(),
collected_
);
read_loop
();
}
}
break
;
}
case
operation
:
:
write
:
{
size_t
wb
;
// written bytes
if
(
!
write_some
(
wb
,
fd
(),
wr_buf_
.
data
()
+
written_
,
wr_buf_
.
size
()
-
written_
))
{
writer_
->
io_failure
(
&
backend
(),
operation
::
write
);
backend
().
del
(
operation
::
write
,
fd
(),
this
);
}
else
if
(
wb
>
0
)
{
written_
+=
wb
;
CAF_ASSERT
(
written_
<=
wr_buf_
.
size
());
auto
remaining
=
wr_buf_
.
size
()
-
written_
;
if
(
ack_writes_
)
writer_
->
data_transferred
(
&
backend
(),
wb
,
remaining
+
wr_offline_buf_
.
size
());
// prepare next send (or stop sending)
if
(
remaining
==
0
)
write_loop
();
}
break
;
}
case
operation
:
:
propagate_error
:
if
(
reader_
)
reader_
->
io_failure
(
&
backend
(),
operation
::
read
);
if
(
writer_
)
writer_
->
io_failure
(
&
backend
(),
operation
::
write
);
// backend will delete this handler anyway,
// no need to call backend().del() here
break
;
}
}
void
default_socket
::
close_read
()
{
if
(
fd_
!=
invalid_native_socket
)
{
::
shutdown
(
fd_
,
0
);
// 0 identifies the read channel on Win & UNIX
void
stream
::
read_loop
()
{
collected_
=
0
;
switch
(
rd_flag_
)
{
case
receive_policy_flag
:
:
exactly
:
if
(
rd_buf_
.
size
()
!=
max_
)
rd_buf_
.
resize
(
max_
);
read_threshold_
=
max_
;
break
;
case
receive_policy_flag
:
:
at_most
:
if
(
rd_buf_
.
size
()
!=
max_
)
rd_buf_
.
resize
(
max_
);
read_threshold_
=
1
;
break
;
case
receive_policy_flag
:
:
at_least
:
{
// read up to 10% more, but at least allow 100 bytes more
auto
max_size
=
max_
+
std
::
max
<
size_t
>
(
100
,
max_
/
10
);
if
(
rd_buf_
.
size
()
!=
max_size
)
rd_buf_
.
resize
(
max_size
);
read_threshold_
=
max_
;
break
;
}
}
}
void
stream
::
write_loop
()
{
CAF_LOG_TRACE
(
CAF_ARG
(
wr_buf_
.
size
())
<<
CAF_ARG
(
wr_offline_buf_
.
size
()));
written_
=
0
;
wr_buf_
.
clear
();
if
(
wr_offline_buf_
.
empty
())
{
writing_
=
false
;
backend
().
del
(
operation
::
write
,
fd
(),
this
);
}
else
{
wr_buf_
.
swap
(
wr_offline_buf_
);
}
}
acceptor
::
acceptor
(
default_multiplexer
&
backend_ref
,
native_socket
sockfd
)
:
event_handler
(
backend_ref
,
sockfd
),
sock_
(
invalid_native_socket
)
{
// nop
}
void
acceptor
::
start
(
const
manager_ptr
&
mgr
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
()));
CAF_ASSERT
(
mgr
!=
nullptr
);
mgr_
=
mgr
;
backend
().
add
(
operation
::
read
,
fd
(),
this
);
}
void
acceptor
::
stop_reading
()
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
()));
close_read_channel
();
backend
().
del
(
operation
::
read
,
fd
(),
this
);
}
void
acceptor
::
handle_event
(
operation
op
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
())
<<
CAF_ARG
(
op
));
if
(
mgr_
&&
op
==
operation
::
read
)
{
native_socket
sockfd
=
invalid_native_socket
;
if
(
try_accept
(
sockfd
,
fd
()))
{
if
(
sockfd
!=
invalid_native_socket
)
{
sock_
=
sockfd
;
mgr_
->
new_connection
();
}
}
}
}
void
acceptor
::
removed_from_loop
(
operation
op
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
accept_sock_
.
fd
())
<<
CAF_ARG
(
op
));
if
(
op
==
operation
::
read
)
mgr_
.
reset
();
}
class
socket_guard
{
public:
explicit
socket_guard
(
native_socket
fd
)
:
fd_
(
fd
)
{
...
...
@@ -1108,8 +1271,8 @@ bool ip_connect(native_socket fd, const std::string& host, uint16_t port) {
return
connect
(
fd
,
reinterpret_cast
<
const
sockaddr
*>
(
&
sa
),
sizeof
(
sa
))
==
0
;
}
native_socket
new_tcp_connection
_impl
(
const
std
::
string
&
host
,
uint16_t
port
,
maybe
<
protocol
>
preferred
)
{
native_socket
new_tcp_connection
(
const
std
::
string
&
host
,
uint16_t
port
,
maybe
<
protocol
>
preferred
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
)
<<
CAF_ARG
(
preferred
));
CAF_LOG_INFO
(
"try to connect to:"
<<
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
));
auto
res
=
interfaces
::
native_address
(
host
,
preferred
);
...
...
@@ -1129,7 +1292,7 @@ native_socket new_tcp_connection_impl(const std::string& host, uint16_t port,
}
sguard
.
close
();
// IPv4 fallback
return
new_tcp_connection
_impl
(
host
,
port
,
ipv4
);
return
new_tcp_connection
(
host
,
port
,
ipv4
);
}
if
(
!
ip_connect
<
AF_INET
>
(
fd
,
res
->
first
,
port
))
{
CAF_LOG_ERROR
(
"could not connect to:"
<<
CAF_ARG
(
host
)
<<
CAF_ARG
(
port
));
...
...
@@ -1139,11 +1302,6 @@ native_socket new_tcp_connection_impl(const std::string& host, uint16_t port,
return
sguard
.
release
();
}
default_socket
new_tcp_connection
(
default_multiplexer
&
backend
,
const
std
::
string
&
host
,
uint16_t
port
)
{
return
default_socket
{
backend
,
new_tcp_connection_impl
(
host
,
port
)};
}
template
<
class
SockAddrType
>
void
read_port
(
native_socket
fd
,
SockAddrType
&
sa
)
{
socklen_t
len
=
sizeof
(
SockAddrType
);
...
...
@@ -1226,18 +1384,6 @@ new_tcp_acceptor_impl(uint16_t port, const char* addr, bool reuse_addr) {
return
{
sguard
.
release
(),
p
};
}
std
::
pair
<
default_socket_acceptor
,
uint16_t
>
new_tcp_acceptor
(
default_multiplexer
&
backend
,
uint16_t
port
,
const
char
*
addr
,
bool
reuse
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
port
)
<<
", addr = "
<<
(
addr
?
addr
:
"nullptr"
)
<<
", "
<<
CAF_ARG
(
reuse
));
auto
acceptor
=
new_tcp_acceptor_impl
(
port
,
addr
,
reuse
);
auto
bound_port
=
acceptor
.
second
;
CAF_ASSERT
(
port
==
0
||
bound_port
==
port
);
return
{
default_socket_acceptor
{
backend
,
std
::
move
(
acceptor
.
first
)},
bound_port
};
}
std
::
string
local_addr_of_fd
(
native_socket
fd
)
{
sockaddr_storage
st
;
socklen_t
st_len
=
sizeof
(
st
);
...
...
@@ -1250,7 +1396,8 @@ std::string local_addr_of_fd(native_socket fd) {
return
inet_ntop
(
AF_INET
,
&
reinterpret_cast
<
sockaddr_in
*>
(
sa
)
->
sin_addr
,
addr
,
sizeof
(
addr
));
case
AF_INET6
:
return
inet_ntop
(
AF_INET6
,
&
reinterpret_cast
<
sockaddr_in6
*>
(
sa
)
->
sin6_addr
,
return
inet_ntop
(
AF_INET6
,
&
reinterpret_cast
<
sockaddr_in6
*>
(
sa
)
->
sin6_addr
,
addr
,
sizeof
(
addr
));
default:
break
;
...
...
@@ -1278,7 +1425,8 @@ std::string remote_addr_of_fd(native_socket fd) {
return
inet_ntop
(
AF_INET
,
&
reinterpret_cast
<
sockaddr_in
*>
(
sa
)
->
sin_addr
,
addr
,
sizeof
(
addr
));
case
AF_INET6
:
return
inet_ntop
(
AF_INET6
,
&
reinterpret_cast
<
sockaddr_in6
*>
(
sa
)
->
sin6_addr
,
return
inet_ntop
(
AF_INET6
,
&
reinterpret_cast
<
sockaddr_in6
*>
(
sa
)
->
sin6_addr
,
addr
,
sizeof
(
addr
));
default:
break
;
...
...
Write
Preview
Markdown
is supported
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