-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathsocket.cpp
More file actions
140 lines (124 loc) · 3.5 KB
/
Copy pathsocket.cpp
File metadata and controls
140 lines (124 loc) · 3.5 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//
// Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/cppalliance/corosio
//
#include <boost/corosio/socket.hpp>
#include <boost/corosio/detail/except.hpp>
#include "src/detail/config_backend.hpp"
#if defined(BOOST_COROSIO_BACKEND_IOCP)
#include "src/detail/iocp/sockets.hpp"
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
#include "src/detail/epoll/sockets.hpp"
#endif
#include <cassert>
namespace boost {
namespace corosio {
namespace {
#if defined(BOOST_COROSIO_BACKEND_IOCP)
using socket_service = detail::win_sockets;
using socket_impl_type = detail::win_socket_impl;
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
using socket_service = detail::epoll_sockets;
using socket_impl_type = detail::epoll_socket_impl;
#endif
} // namespace
socket::
~socket()
{
close();
}
socket::
socket(
capy::execution_context& ctx)
: io_stream(ctx)
{
}
/**
* @brief Ensure the socket has an underlying implementation and open the native socket handle.
*
* Creates and stores the backend-specific socket implementation from the execution context
* and opens the associated native socket handle. If the socket is already open, the call
* returns immediately.
*
* @throws std::system_error If the underlying service fails to open the native socket; the
* implementation is released before the exception is thrown.
*/
void
socket::
open()
{
if (impl_)
return;
auto& svc = ctx_->use_service<socket_service>();
auto& wrapper = svc.create_impl();
impl_ = &wrapper;
#if defined(BOOST_COROSIO_BACKEND_IOCP)
system::error_code ec = svc.open_socket(*wrapper.get_internal());
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
system::error_code ec = svc.open_socket(wrapper);
#endif
if (ec)
{
wrapper.release();
impl_ = nullptr;
detail::throw_system_error(ec, "socket::open");
}
}
/**
* @brief Releases the underlying socket implementation and resets the socket state.
*
* If the socket is not open, the call has no effect. Otherwise this releases the
* held implementation (closing the underlying resource) and clears the internal
* implementation pointer.
*/
void
socket::
close()
{
if (!impl_)
return;
auto* wrapper = static_cast<socket_impl_type*>(impl_);
wrapper->release();
impl_ = nullptr;
}
/**
* @brief Cancel all outstanding asynchronous operations on the socket.
*
* Requires that the socket implementation has been created (socket is open).
* After calling this, any pending asynchronous I/O initiated on the underlying
* socket will be requested to cancel.
*
* @pre impl_ must be non-null (socket must be open).
*/
void
socket::
cancel()
{
assert(impl_ != nullptr);
#if defined(BOOST_COROSIO_BACKEND_IOCP)
static_cast<socket_impl_type*>(impl_)->get_internal()->cancel();
#elif defined(BOOST_COROSIO_BACKEND_EPOLL)
static_cast<socket_impl_type*>(impl_)->cancel();
#endif
}
/**
* @brief Shuts down one or both directions of the underlying socket.
*
* If the socket has an active implementation, delegates the shutdown request
* to that implementation; otherwise the call is a no-op.
*
* @param what Specifies which direction(s) to shut down (for example: read, write, or both).
*/
void
socket::
shutdown(shutdown_type what)
{
if (impl_)
get().shutdown(what);
}
} // namespace corosio
} // namespace boost