Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
817e9120
Commit
817e9120
authored
Aug 10, 2017
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
net/SocketDescriptor: specialization of FileDescriptor for network sockets
parent
7f83d38b
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
717 additions
and
0 deletions
+717
-0
Makefile.am
Makefile.am
+2
-0
SocketDescriptor.cxx
src/net/SocketDescriptor.cxx
+405
-0
SocketDescriptor.hxx
src/net/SocketDescriptor.hxx
+205
-0
StaticSocketAddress.hxx
src/net/StaticSocketAddress.hxx
+2
-0
UniqueSocketDescriptor.hxx
src/net/UniqueSocketDescriptor.hxx
+103
-0
No files found.
Makefile.am
View file @
817e9120
...
...
@@ -484,6 +484,8 @@ libnet_a_SOURCES = \
src/net/AllocatedSocketAddress.cxx src/net/AllocatedSocketAddress.hxx
\
src/net/SocketAddress.cxx src/net/SocketAddress.hxx
\
src/net/SocketUtil.cxx src/net/SocketUtil.hxx
\
src/net/SocketDescriptor.cxx src/net/SocketDescriptor.hxx
\
src/net/UniqueSocketDescriptor.hxx
\
src/net/SocketError.cxx src/net/SocketError.hxx
# System library
...
...
src/net/SocketDescriptor.cxx
0 → 100644
View file @
817e9120
/*
* Copyright (C) 2012-2017 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "SocketDescriptor.hxx"
#include "SocketAddress.hxx"
#include "StaticSocketAddress.hxx"
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#endif
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#ifdef _WIN32
void
SocketDescriptor
::
Close
()
{
if
(
IsDefined
())
::
closesocket
(
Steal
());
}
#endif
SocketDescriptor
SocketDescriptor
::
Accept
()
{
#if defined(__linux__) && !defined(__BIONIC__) && !defined(KOBO)
int
connection_fd
=
::
accept4
(
Get
(),
nullptr
,
nullptr
,
SOCK_CLOEXEC
);
#else
int
connection_fd
=
::
accept
(
Get
(),
nullptr
,
nullptr
);
#endif
return
connection_fd
>=
0
?
SocketDescriptor
(
connection_fd
)
:
Undefined
();
}
SocketDescriptor
SocketDescriptor
::
AcceptNonBlock
(
StaticSocketAddress
&
address
)
const
{
address
.
SetMaxSize
();
#if defined(__linux__) && !defined(__BIONIC__) && !defined(KOBO)
int
connection_fd
=
::
accept4
(
Get
(),
address
,
&
address
.
size
,
SOCK_CLOEXEC
|
SOCK_NONBLOCK
);
#else
int
connection_fd
=
::
accept
(
Get
(),
address
,
&
address
.
size
);
#endif
return
SocketDescriptor
(
connection_fd
);
}
bool
SocketDescriptor
::
Connect
(
SocketAddress
address
)
{
assert
(
address
.
IsDefined
());
return
::
connect
(
Get
(),
address
.
GetAddress
(),
address
.
GetSize
())
>=
0
;
}
bool
SocketDescriptor
::
Create
(
int
domain
,
int
type
,
int
protocol
)
{
#ifdef WIN32
static
bool
initialised
=
false
;
if
(
!
initialised
)
{
WSADATA
data
;
WSAStartup
(
MAKEWORD
(
2
,
2
),
&
data
);
initialised
=
true
;
}
#endif
#ifdef SOCK_CLOEXEC
/* implemented since Linux 2.6.27 */
type
|=
SOCK_CLOEXEC
;
#endif
int
new_fd
=
socket
(
domain
,
type
,
protocol
);
if
(
new_fd
<
0
)
return
false
;
Set
(
new_fd
);
return
true
;
}
bool
SocketDescriptor
::
CreateNonBlock
(
int
domain
,
int
type
,
int
protocol
)
{
#ifdef SOCK_NONBLOCK
type
|=
SOCK_NONBLOCK
;
#endif
if
(
!
Create
(
domain
,
type
,
protocol
))
return
false
;
#ifndef __linux__
SetNonBlocking
();
#endif
return
true
;
}
bool
SocketDescriptor
::
CreateSocketPair
(
int
domain
,
int
type
,
int
protocol
,
SocketDescriptor
&
a
,
SocketDescriptor
&
b
)
{
#ifdef SOCK_CLOEXEC
/* implemented since Linux 2.6.27 */
type
|=
SOCK_CLOEXEC
;
#endif
int
fds
[
2
];
if
(
socketpair
(
domain
,
type
,
protocol
,
fds
)
<
0
)
return
false
;
a
=
SocketDescriptor
(
fds
[
0
]);
b
=
SocketDescriptor
(
fds
[
1
]);
return
true
;
}
bool
SocketDescriptor
::
CreateSocketPairNonBlock
(
int
domain
,
int
type
,
int
protocol
,
SocketDescriptor
&
a
,
SocketDescriptor
&
b
)
{
#ifdef SOCK_CLOEXEC
/* implemented since Linux 2.6.27 */
type
|=
SOCK_CLOEXEC
;
#endif
if
(
!
CreateSocketPair
(
domain
,
type
,
protocol
,
a
,
b
))
return
false
;
#ifndef __linux__
a
.
SetNonBlocking
();
b
.
SetNonBlocking
();
#endif
return
true
;
}
int
SocketDescriptor
::
GetError
()
{
assert
(
IsDefined
());
int
s_err
=
0
;
socklen_t
s_err_size
=
sizeof
(
s_err
);
return
getsockopt
(
fd
,
SOL_SOCKET
,
SO_ERROR
,
(
char
*
)
&
s_err
,
&
s_err_size
)
==
0
?
s_err
:
errno
;
}
bool
SocketDescriptor
::
SetOption
(
int
level
,
int
name
,
const
void
*
value
,
size_t
size
)
{
assert
(
IsDefined
());
return
setsockopt
(
fd
,
level
,
name
,
value
,
size
)
==
0
;
}
#ifdef __linux__
bool
SocketDescriptor
::
SetReuseAddress
(
bool
value
)
{
return
SetBoolOption
(
SOL_SOCKET
,
SO_REUSEADDR
,
value
);
}
#ifdef SO_REUSEPORT
bool
SocketDescriptor
::
SetReusePort
(
bool
value
)
{
return
SetBoolOption
(
SOL_SOCKET
,
SO_REUSEPORT
,
value
);
}
#endif
bool
SocketDescriptor
::
SetFreeBind
(
bool
value
)
{
return
SetBoolOption
(
IPPROTO_IP
,
IP_FREEBIND
,
value
);
}
bool
SocketDescriptor
::
SetNoDelay
(
bool
value
)
{
return
SetBoolOption
(
IPPROTO_TCP
,
TCP_NODELAY
,
value
);
}
bool
SocketDescriptor
::
SetCork
(
bool
value
)
{
return
SetBoolOption
(
IPPROTO_TCP
,
TCP_CORK
,
value
);
}
bool
SocketDescriptor
::
SetTcpDeferAccept
(
const
int
&
seconds
)
{
return
SetOption
(
IPPROTO_TCP
,
TCP_DEFER_ACCEPT
,
&
seconds
,
sizeof
(
seconds
));
}
bool
SocketDescriptor
::
SetV6Only
(
bool
value
)
{
return
SetBoolOption
(
IPPROTO_IPV6
,
IPV6_V6ONLY
,
value
);
}
bool
SocketDescriptor
::
SetBindToDevice
(
const
char
*
name
)
{
return
SetOption
(
SOL_SOCKET
,
SO_BINDTODEVICE
,
name
,
strlen
(
name
));
}
#ifdef TCP_FASTOPEN
bool
SocketDescriptor
::
SetTcpFastOpen
(
int
qlen
)
{
return
SetOption
(
SOL_TCP
,
TCP_FASTOPEN
,
&
qlen
,
sizeof
(
qlen
));
}
#endif
#endif
bool
SocketDescriptor
::
Bind
(
SocketAddress
address
)
{
return
bind
(
Get
(),
address
.
GetAddress
(),
address
.
GetSize
())
==
0
;
}
#ifdef __linux__
bool
SocketDescriptor
::
AutoBind
()
{
static
constexpr
sa_family_t
family
=
AF_LOCAL
;
return
Bind
(
SocketAddress
((
const
struct
sockaddr
*
)
&
family
,
sizeof
(
family
)));
}
#endif
bool
SocketDescriptor
::
Listen
(
int
backlog
)
{
return
listen
(
Get
(),
backlog
)
==
0
;
}
StaticSocketAddress
SocketDescriptor
::
GetLocalAddress
()
const
{
assert
(
IsDefined
());
StaticSocketAddress
result
;
result
.
size
=
result
.
GetCapacity
();
if
(
getsockname
(
fd
,
result
,
&
result
.
size
)
<
0
)
result
.
Clear
();
return
result
;
}
StaticSocketAddress
SocketDescriptor
::
GetPeerAddress
()
const
{
assert
(
IsDefined
());
StaticSocketAddress
result
;
result
.
size
=
result
.
GetCapacity
();
if
(
getpeername
(
fd
,
result
,
&
result
.
size
)
<
0
)
result
.
Clear
();
return
result
;
}
ssize_t
SocketDescriptor
::
Read
(
void
*
buffer
,
size_t
length
)
{
int
flags
=
0
;
#ifndef _WIN32
flags
|=
MSG_DONTWAIT
;
#endif
return
::
recv
(
Get
(),
(
char
*
)
buffer
,
length
,
flags
);
}
ssize_t
SocketDescriptor
::
Write
(
const
void
*
buffer
,
size_t
length
)
{
int
flags
=
0
;
#ifdef __linux__
flags
|=
MSG_NOSIGNAL
;
#endif
return
::
send
(
Get
(),
(
const
char
*
)
buffer
,
length
,
flags
);
}
#ifdef _WIN32
int
SocketDescriptor
::
WaitReadable
(
int
timeout_ms
)
const
{
assert
(
IsDefined
());
fd_set
rfds
;
FD_ZERO
(
&
rfds
);
FD_SET
(
Get
(),
&
rfds
);
struct
timeval
timeout
,
*
timeout_p
=
nullptr
;
if
(
timeout_ms
>=
0
)
{
timeout
.
tv_sec
=
unsigned
(
timeout_ms
)
/
1000
;
timeout
.
tv_usec
=
(
unsigned
(
timeout_ms
)
%
1000
)
*
1000
;
timeout_p
=
&
timeout
;
}
return
select
(
Get
()
+
1
,
&
rfds
,
nullptr
,
nullptr
,
timeout_p
);
}
int
SocketDescriptor
::
WaitWritable
(
int
timeout_ms
)
const
{
assert
(
IsDefined
());
fd_set
wfds
;
FD_ZERO
(
&
wfds
);
FD_SET
(
Get
(),
&
wfds
);
struct
timeval
timeout
,
*
timeout_p
=
nullptr
;
if
(
timeout_ms
>=
0
)
{
timeout
.
tv_sec
=
unsigned
(
timeout_ms
)
/
1000
;
timeout
.
tv_usec
=
(
unsigned
(
timeout_ms
)
%
1000
)
*
1000
;
timeout_p
=
&
timeout
;
}
return
select
(
Get
()
+
1
,
nullptr
,
&
wfds
,
nullptr
,
timeout_p
);
}
#endif
ssize_t
SocketDescriptor
::
Read
(
void
*
buffer
,
size_t
length
,
StaticSocketAddress
&
address
)
{
int
flags
=
0
;
#ifndef _WIN32
flags
|=
MSG_DONTWAIT
;
#endif
socklen_t
addrlen
=
address
.
GetCapacity
();
ssize_t
nbytes
=
::
recvfrom
(
Get
(),
(
char
*
)
buffer
,
length
,
flags
,
address
,
&
addrlen
);
if
(
nbytes
>
0
)
address
.
SetSize
(
addrlen
);
return
nbytes
;
}
ssize_t
SocketDescriptor
::
Write
(
const
void
*
buffer
,
size_t
length
,
SocketAddress
address
)
{
int
flags
=
0
;
#ifndef _WIN32
flags
|=
MSG_DONTWAIT
;
#endif
#ifdef __linux__
flags
|=
MSG_NOSIGNAL
;
#endif
return
::
sendto
(
Get
(),
(
const
char
*
)
buffer
,
length
,
flags
,
address
.
GetAddress
(),
address
.
GetSize
());
}
src/net/SocketDescriptor.hxx
0 → 100644
View file @
817e9120
/*
* Copyright (C) 2012-2017 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SOCKET_DESCRIPTOR_HXX
#define SOCKET_DESCRIPTOR_HXX
#include "system/FileDescriptor.hxx"
#include <type_traits>
class
SocketAddress
;
class
StaticSocketAddress
;
/**
* An OO wrapper for a UNIX socket descriptor.
*/
class
SocketDescriptor
:
protected
FileDescriptor
{
protected
:
explicit
constexpr
SocketDescriptor
(
int
_fd
)
:
FileDescriptor
(
_fd
)
{}
explicit
constexpr
SocketDescriptor
(
FileDescriptor
_fd
)
:
FileDescriptor
(
_fd
)
{}
public
:
SocketDescriptor
()
=
default
;
constexpr
bool
operator
==
(
SocketDescriptor
other
)
const
{
return
fd
==
other
.
fd
;
}
#ifndef _WIN32
/**
* Convert a #FileDescriptor to a #SocketDescriptor. This is only
* possible on operating systems where socket descriptors are the
* same as file descriptors (i.e. not on Windows). Use this only
* when you know what you're doing.
*/
static
constexpr
SocketDescriptor
FromFileDescriptor
(
FileDescriptor
fd
)
{
return
SocketDescriptor
(
fd
);
}
/**
* Convert this object to a #FileDescriptor instance. This is only
* possible on operating systems where socket descriptors are the
* same as file descriptors (i.e. not on Windows). Use this only
* when you know what you're doing.
*/
constexpr
const
FileDescriptor
&
ToFileDescriptor
()
const
{
return
*
this
;
}
#endif
using
FileDescriptor
::
IsDefined
;
using
FileDescriptor
::
IsValid
;
using
FileDescriptor
::
Get
;
using
FileDescriptor
::
Set
;
using
FileDescriptor
::
Steal
;
using
FileDescriptor
::
SetUndefined
;
static
constexpr
SocketDescriptor
Undefined
()
{
return
SocketDescriptor
(
FileDescriptor
::
Undefined
());
}
#ifndef _WIN32
using
FileDescriptor
::
SetNonBlocking
;
using
FileDescriptor
::
SetBlocking
;
using
FileDescriptor
::
EnableCloseOnExec
;
using
FileDescriptor
::
DisableCloseOnExec
;
using
FileDescriptor
::
Duplicate
;
using
FileDescriptor
::
Close
;
#else
/**
* This method replaces FileDescriptor::Close(), using closesocket()
* on Windows. FileDescriptor::Close() is not virtual, so be
* careful when dealing with a FileDescriptor reference that is
* really a SocketDescriptor.
*/
void
Close
();
#endif
/**
* Create a socket.
*
* @param domain is the address domain
* @param type is the sochet type
* @param protocol is the protocol
* @return True on success, False on failure
* See man 2 socket for detailed information
*/
bool
Create
(
int
domain
,
int
type
,
int
protocol
);
/**
* Like Create(), but enable non-blocking mode.
*/
bool
CreateNonBlock
(
int
domain
,
int
type
,
int
protocol
);
static
bool
CreateSocketPair
(
int
domain
,
int
type
,
int
protocol
,
SocketDescriptor
&
a
,
SocketDescriptor
&
b
);
static
bool
CreateSocketPairNonBlock
(
int
domain
,
int
type
,
int
protocol
,
SocketDescriptor
&
a
,
SocketDescriptor
&
b
);
int
GetError
();
bool
SetOption
(
int
level
,
int
name
,
const
void
*
value
,
size_t
size
);
bool
SetBoolOption
(
int
level
,
int
name
,
bool
_value
)
{
const
int
value
=
_value
;
return
SetOption
(
level
,
name
,
&
value
,
sizeof
(
value
));
}
#ifdef __linux__
bool
SetReuseAddress
(
bool
value
=
true
);
bool
SetReusePort
(
bool
value
=
true
);
bool
SetFreeBind
(
bool
value
=
true
);
bool
SetNoDelay
(
bool
value
=
true
);
bool
SetCork
(
bool
value
=
true
);
bool
SetTcpDeferAccept
(
const
int
&
seconds
);
bool
SetV6Only
(
bool
value
);
/**
* Setter for SO_BINDTODEVICE.
*/
bool
SetBindToDevice
(
const
char
*
name
);
bool
SetTcpFastOpen
(
int
qlen
=
16
);
#endif
bool
Bind
(
SocketAddress
address
);
#ifdef __linux__
/**
* Binds the socket to a unique abstract address.
*/
bool
AutoBind
();
#endif
bool
Listen
(
int
backlog
);
SocketDescriptor
Accept
();
SocketDescriptor
AcceptNonBlock
(
StaticSocketAddress
&
address
)
const
;
bool
Connect
(
SocketAddress
address
);
gcc_pure
StaticSocketAddress
GetLocalAddress
()
const
;
gcc_pure
StaticSocketAddress
GetPeerAddress
()
const
;
ssize_t
Read
(
void
*
buffer
,
size_t
length
);
ssize_t
Write
(
const
void
*
buffer
,
size_t
length
);
#ifdef _WIN32
int
WaitReadable
(
int
timeout_ms
)
const
;
int
WaitWritable
(
int
timeout_ms
)
const
;
#else
using
FileDescriptor
::
WaitReadable
;
using
FileDescriptor
::
WaitWritable
;
using
FileDescriptor
::
IsReadyForWriting
;
#endif
/**
* Receive a datagram and return the source address.
*/
ssize_t
Read
(
void
*
buffer
,
size_t
length
,
StaticSocketAddress
&
address
);
/**
* Send a datagram to the specified address.
*/
ssize_t
Write
(
const
void
*
buffer
,
size_t
length
,
SocketAddress
address
);
};
static_assert
(
std
::
is_trivial
<
SocketDescriptor
>::
value
,
"type is not trivial"
);
#endif
src/net/StaticSocketAddress.hxx
View file @
817e9120
...
...
@@ -39,6 +39,8 @@
* An OO wrapper for struct sockaddr_storage.
*/
class
StaticSocketAddress
{
friend
class
SocketDescriptor
;
public
:
typedef
SocketAddress
::
size_type
size_type
;
...
...
src/net/UniqueSocketDescriptor.hxx
0 → 100644
View file @
817e9120
/*
* Copyright (C) 2012-2017 Max Kellermann <max.kellermann@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UNIQUE_SOCKET_DESCRIPTOR_SOCKET_HXX
#define UNIQUE_SOCKET_DESCRIPTOR_SOCKET_HXX
#include "SocketDescriptor.hxx"
#include <algorithm>
#include <utility>
class
StaticSocketAddress
;
/**
* Wrapper for a socket file descriptor.
*/
class
UniqueSocketDescriptor
:
public
SocketDescriptor
{
public
:
UniqueSocketDescriptor
()
:
SocketDescriptor
(
SocketDescriptor
::
Undefined
())
{}
explicit
UniqueSocketDescriptor
(
SocketDescriptor
_fd
)
:
SocketDescriptor
(
_fd
)
{}
explicit
UniqueSocketDescriptor
(
FileDescriptor
_fd
)
:
SocketDescriptor
(
_fd
)
{}
explicit
UniqueSocketDescriptor
(
int
_fd
)
:
SocketDescriptor
(
_fd
)
{}
UniqueSocketDescriptor
(
UniqueSocketDescriptor
&&
other
)
:
SocketDescriptor
(
std
::
exchange
(
other
.
fd
,
-
1
))
{}
~
UniqueSocketDescriptor
()
{
if
(
IsDefined
())
Close
();
}
/**
* Release ownership and return the descriptor as an unmanaged
* #SocketDescriptor instance.
*/
SocketDescriptor
Release
()
{
return
std
::
exchange
(
*
(
SocketDescriptor
*
)
this
,
Undefined
());
}
UniqueSocketDescriptor
&
operator
=
(
UniqueSocketDescriptor
&&
src
)
{
std
::
swap
(
fd
,
src
.
fd
);
return
*
this
;
}
bool
operator
==
(
const
UniqueSocketDescriptor
&
other
)
const
{
return
fd
==
other
.
fd
;
}
/**
* @return an "undefined" instance on error
*/
UniqueSocketDescriptor
AcceptNonBlock
(
StaticSocketAddress
&
address
)
const
{
return
UniqueSocketDescriptor
(
SocketDescriptor
::
AcceptNonBlock
(
address
));
}
static
bool
CreateSocketPair
(
int
domain
,
int
type
,
int
protocol
,
UniqueSocketDescriptor
&
a
,
UniqueSocketDescriptor
&
b
)
{
return
SocketDescriptor
::
CreateSocketPair
(
domain
,
type
,
protocol
,
a
,
b
);
}
static
bool
CreateSocketPairNonBlock
(
int
domain
,
int
type
,
int
protocol
,
UniqueSocketDescriptor
&
a
,
UniqueSocketDescriptor
&
b
)
{
return
SocketDescriptor
::
CreateSocketPairNonBlock
(
domain
,
type
,
protocol
,
a
,
b
);
}
};
#endif
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