1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#pragma once
#include "asio.h"
#include "tcp_socket_impl.h"
namespace NAsio {
class TOperationAccept: public TFdOperation {
public:
TOperationAccept(SOCKET fd, TTcpSocket::TImpl& newSocket, TTcpAcceptor::TAcceptHandler h, TInstant deadline)
: TFdOperation(fd, PollRead, deadline)
, H_(h)
, NS_(newSocket)
{
}
bool Execute(int errorCode) override;
TTcpAcceptor::TAcceptHandler H_;
TTcpSocket::TImpl& NS_;
};
class TTcpAcceptor::TImpl: public TThrRefBase {
public:
TImpl(TIOService::TImpl& srv) noexcept
: Srv_(srv)
{
}
inline void Bind(TEndpoint& ep, TErrorCode& ec) noexcept {
TSocketHolder s(socket(ep.SockAddr()->sa_family, SOCK_STREAM, 0));
if (s == INVALID_SOCKET) {
ec.Assign(LastSystemError());
}
FixIPv6ListenSocket(s);
CheckedSetSockOpt(s, SOL_SOCKET, SO_REUSEADDR, 1, "reuse addr");
SetNonBlock(s);
if (::bind(s, ep.SockAddr(), ep.SockAddrLen())) {
ec.Assign(LastSystemError());
return;
}
S_.Swap(s);
}
inline void Listen(int backlog, TErrorCode& ec) noexcept {
if (::listen(S_, backlog)) {
ec.Assign(LastSystemError());
return;
}
}
inline void AsyncAccept(TTcpSocket& s, TTcpAcceptor::TAcceptHandler h, TInstant deadline) {
Srv_.ScheduleOp(new TOperationAccept((SOCKET)S_, s.GetImpl(), h, deadline)); //set callback
}
inline void AsyncCancel() {
Srv_.ScheduleOp(new TOperationCancel<TTcpAcceptor::TImpl>(this));
}
inline TIOService::TImpl& GetIOServiceImpl() const noexcept {
return Srv_;
}
inline SOCKET Fd() const noexcept {
return S_;
}
private:
TIOService::TImpl& Srv_;
TSocketHolder S_;
};
}
|