aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/neh/asio/tcp_acceptor_impl.h
blob: c990236efc1dd60e7ca9579744cc067d2ec5f2e2 (plain) (blame)
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_;
    };
}