Skip to content

Commit

Permalink
#77 Made exceptions optional in the build. Address validity testing m…
Browse files Browse the repository at this point in the history
…ore uniform with 'is_set()' and operator bool()'
  • Loading branch information
fpagliughi committed Apr 29, 2023
1 parent 3a6083e commit 7b82602
Show file tree
Hide file tree
Showing 14 changed files with 130 additions and 84 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ option(SOCKPP_BUILD_DOCUMENTATION "Create Doxygen reference documentation" OFF)
#option(SOCKPP_WITH_OPENSSL "Include support for TLS Secure Sockets with OpenSSL" OFF)
#option(SOCKPP_WITH_MBEDTLS "Include support for TLS Secure Sockets with Mbed TLS" OFF)
option(SOCKPP_WITH_CAN "Include support for Linux SocketCAN components" OFF)

option(SOCKPP_WITH_EXCEPTIONS "Use C++ exceptions" ON)

# ----- Find any dependencies -----

Expand Down
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# sockpp

[![Build Status](https://travis-ci.org/fpagliughi/sockpp.svg?branch=master)](https://travis-ci.org/fpagliughi/sockpp)

Simple, modern, C++ socket library.

This is a fairly low-level C++ wrapper around the Berkeley sockets library using `socket`, `acceptor,` and `connector` classes that are familiar concepts from other languages.
Expand All @@ -24,7 +22,7 @@ The API is changing (slightly)!

The idea of having "stateless" I/O operations introduced in [PR #17](https://github.com/fpagliughi/sockpp/pull/17), which was never fully merged is coming into the API with a `result<T>` class. This will be generic over the return type, though typically use an int for I/O operations, but the error state will be represented by a `std::error_code`. This should help to significantly reduce platform issues for tracking and reporting errors. This may even take over the whole of the API to make _all_ operations stateless by default.

Work has has begun on incorporating Secure Sockets into the library using either OpenSSL or MbedTLS libraries. [PR #17](https://github.com/fpagliughi/sockpp/pull/17), which has been sitting dormant for a few years in being merged and updated, along with new work to do something compatible with OpenSSL. You will be ablt to chose one library or the other when building `sockpp`.
Work has has begun on incorporating Secure Sockets into the library using either OpenSSL or MbedTLS libraries. [PR #17](https://github.com/fpagliughi/sockpp/pull/17), which has been sitting dormant for a few years in being merged and updated, along with new work to do something compatible with OpenSSL. You will be ablt to chose one library or the other when building `sockpp`. This probably won't be in the next release, but the following one.

The library is reaching a stable API, and is on track for a 1.0 release in the near future. Until then, there may be a few more breaking changes, but hopefully those will be fewer than we have seen so far.

Expand All @@ -38,9 +36,15 @@ If you're using this library, tweet at me or send me a message, and let me know

## Unrelased Features in this Branch

- [#72](https://github.com/fpagliughi/sockpp/issues/72) Removed exceptions
- [#72](https://github.com/fpagliughi/sockpp/issues/72) Removed some exceptions and made the others optional by build option.
- Added `raw_socket` class.
- [#77](https://github.com/fpagliughi/sockpp/issues/77) Added `result<T>` tempate class for success/error return values using `std::error_code` for errors.
- [#77](https://github.com/fpagliughi/sockpp/issues/77)
- Exceptions can now be removed through a CMake build option, `SOCKPP_WITH_EXCEPTIONS`.
- Added `result<T>` tempate class for success/error return values using `std::error_code` for errors.
- `sockpp::last_error()` now returns a `std::error_code`. This should be slightly more portable, but Windows will likely still be somewhat problematic.
- A new `sockpp::last_errno()` will return the platform-specific integer error code (i.e. what `last_error()` used to return).
- More consistent validity checks for address types with `is_set()` and `operator bool()`.
- The `connector::connect()` with timeout now uses `poll()` for the timeout on non-Windows systems. Hopefully `WSAPoll()` on Windows will be available before the upcoming release as well.

## New in v0.8.1

Expand Down Expand Up @@ -112,7 +116,7 @@ $ cmake --build build/ --target install

### Build Options

The library has several build options via CMake to choose between creating a static or shared (dynamic) library - or both. It also allows you to build the example options, and if Doxygen is
The library has several build options via CMake to choose between creating a static or shared (dynamic) library - or both. It also allows you to build the example options, and if Doxygen is installed, it can be used to create documentation.

Variable | Default Value | Description
------------ | ------------- | -------------
Expand All @@ -121,9 +125,8 @@ SOCKPP_BUILD_STATIC | OFF | Whether to build the static library
SOCKPP_BUILD_DOCUMENTATION | OFF | Create and install the HTML based API documentation (requires _Doxygen)_
SOCKPP_BUILD_EXAMPLES | OFF | Build example programs
SOCKPP_BUILD_TESTS | OFF | Build the unit tests (requires _Catch2_)
SOCKPP_BUILD_CAN | OFF | Build SocketCAN support. (Linux only)
SOCKPP_WITH_MBEDTLS | OFF | Secure Sockets with MbedTLS
SOCKPP_WITH_OPENSSL | OFF | Secure Sockets with OpenSSL
SOCKPP_WITH_CAN | OFF | Include SocketCAN support. (Linux only)
SOCKPP_WITH_EXCEPTIONS | ON | Whether to use C++ exceptions

Set these using the '-D' switch in the CMake configuration command. For example, to build documentation and example apps:

Expand Down
7 changes: 7 additions & 0 deletions cmake/version.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@

#include <string>

// Flag if sockpp was built with exceptions

#cmakedefine SOCKPP_WITH_EXCEPTIONS
#if defined(SOCKPP_WITH_EXCEPTIONS)
#define SOCKPP_EXCEPTIONS
#endif

// Define which secure socket library compiled in (if any)

#cmakedefine SOCKPP_WITH_OPENSSL
Expand Down
8 changes: 1 addition & 7 deletions include/sockpp/can_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,7 @@ class can_address : public sock_address
* that it's not all zero.
* @return @em true if the address has been set, @em false otherwise.
*/
bool is_set() const noexcept { return family() != AF_UNSPEC; }
/**
* Determines if the address is valid for a CAN bus interface.
* @return @em true if the address is valid or a CAN bus interface,
* @false otherwise.
*/
operator bool() const noexcept { return family() == AF_CAN; }
bool is_set() const noexcept override { return addr_.can_family == ADDRESS_FAMILY; }
/**
* Gets the name of the CAN interface to which this address refers.
* @return The name of the CAN interface to which this address refers.
Expand Down
12 changes: 12 additions & 0 deletions include/sockpp/datagram_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,18 @@ class datagram_socket_tmpl : public datagram_socket
datagram_socket_tmpl{std::get<0>(pr).release()},
datagram_socket_tmpl{std::get<1>(pr).release()});
}
/**
* Gets the local address to which the socket is bound.
* @return The local address to which the socket is bound.
* @throw sys_error on error
*/
addr_t address() const { return addr_t(socket::address()); }
/**
* Gets the address of the remote peer, if this socket is connected.
* @return The address of the remote peer, if this socket is connected.
* @throw sys_error on error
*/
addr_t peer_address() const { return addr_t(socket::peer_address()); }
/**
* Binds the socket to the local address.
* Datagram sockets can bind to a local address/adapter to filter which
Expand Down
15 changes: 7 additions & 8 deletions include/sockpp/inet6_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2019 Frank Pagliughi All rights reserved.
// Copyright (c) 2019-2023 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
Expand Down Expand Up @@ -56,7 +57,6 @@ namespace sockpp {

/////////////////////////////////////////////////////////////////////////////


/**
* Class that represents an internet (IPv6) address. This inherits from the
* IP-specific form of a socket address, @em sockaddr_in.
Expand Down Expand Up @@ -139,11 +139,12 @@ class inet6_address : public sock_address
}
/**
* Checks if the address is set to some value.
* This doesn't attempt to determine if the address is valid, simply
* that it's not all zero.
* @return bool
* This doesn't attempt to determine if the address is valid, simply
* that it was at least set to an address of this family.
* @return @em true if the address is set to some value in this family,
* even if not valid, @em false if the address is empty.
*/
bool is_set() const;
bool is_set() const noexcept override { return addr_.sin6_family == ADDRESS_FAMILY; }
/**
* Attempts to resolve the host name into a 32-bit internet address.
* @param saddr The string host name.
Expand Down Expand Up @@ -175,8 +176,6 @@ class inet6_address : public sock_address
* Note that the address is normally stored in network byte
* order.
* @param i The byte to read (0-7)
{
return addr_ != sockaddr_in6{};
* @return The specified byte in the 128-bit IPv6 Address
*/
uint8_t operator[](int i) const {
Expand Down
18 changes: 6 additions & 12 deletions include/sockpp/inet_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2014-2019 Frank Pagliughi
// Copyright (c) 2014-2023 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -129,21 +129,15 @@ class inet_address : public sock_address
* @param addr The other address
*/
inet_address(const inet_address& addr) : addr_{addr.addr_} {}

/**
* Checks if the address is set to some value.
* This doesn't attempt to determine if the address is valid, simply
* that it's not all zero.
* @return bool
*/
bool is_set() const;
/**
* Determines if the address is set to some value.
* This doesn't attempt to determine if the address is valid, simply
* that the family has been set properly.
* @return @em true if this has been set as some AF_INET address,
* whether or not is is valid.
* that it was at least set to an address of this family.
* @return @em true if the address is set to some value in this family,
* even if not valid, @em false if the address is empty.
*/
operator bool() const { return addr_.sin_family == ADDRESS_FAMILY; }
bool is_set() const noexcept override { return addr_.sin_family == ADDRESS_FAMILY; }
/**
* Attempts to resolve the host name into a 32-bit internet address.
* @param saddr The string host name.
Expand Down
47 changes: 37 additions & 10 deletions include/sockpp/sock_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@ class sock_address
auto p = sockaddr_ptr();
return p ? p->sa_family : AF_UNSPEC;
}
/**
* Checks if the address is set to some value.
* This doesn't attempt to determine if the address is valid, simply
* that it has set an address family.
* @return @em true if at least the address family has been set, @em
* false otherwise.
*/
virtual bool is_set() const noexcept { return family() != AF_UNSPEC; }
/**
* Determines if the address is set to some value.
* This doesn't attempt to determine if the address is valid, simply
* that the family has been set properly.
* @return @em true if this has been set as some address, whether or not
* is is valid.
*/
virtual operator bool() const noexcept { return is_set(); }

};

/////////////////////////////////////////////////////////////////////////////
Expand All @@ -109,20 +126,20 @@ class sock_address
*/
class sock_address_any : public sock_address
{
/** Storage for any kind of socket address */
sockaddr_storage addr_;
/** Length of the address (in bytes) */
socklen_t sz_;

/** The maximum size of an address, in bytes */
static constexpr size_t MAX_SZ = sizeof(sockaddr_storage);

/** Storage for any kind of socket address */
sockaddr_storage addr_{};
/** Length of the address (in bytes) */
socklen_t sz_{MAX_SZ};

public:
/**
* Constructs an empty address.
* The address is initialized to all zeroes.
*/
sock_address_any() : addr_{}, sz_{MAX_SZ} {}
sock_address_any() =default;
/**
* Constructs an address.
* @param addr Pointer to a buffer holding the address.
Expand All @@ -131,8 +148,13 @@ class sock_address_any : public sock_address
* an address.
*/
sock_address_any(const sockaddr* addr, socklen_t n) {
if (size_t(n) > MAX_SZ)
throw std::length_error("Address length out of range");
if (size_t(n) > MAX_SZ) {
#if defined(SOCKPP_WITH_EXCEPTIONS)
throw std::length_error("Address length out of range");
#else
return;
#endif
}
std::memcpy(&addr_, addr, sz_ = n);
}
/**
Expand All @@ -143,8 +165,13 @@ class sock_address_any : public sock_address
* an address.
*/
sock_address_any(const sockaddr_storage& addr, socklen_t n) {
if (size_t(n) > MAX_SZ)
throw std::length_error("Address length out of range");
if (size_t(n) > MAX_SZ) {
#if defined(SOCKPP_WITH_EXCEPTIONS)
throw std::length_error("Address length out of range");
#else
return;
#endif
}
std::memcpy(&addr_, &addr, sz_ = n);
}
/**
Expand Down
10 changes: 2 additions & 8 deletions include/sockpp/unix_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,8 @@ class unix_address : public sock_address
* that it's not all zero.
* @return @em true if the address has been set, @em false otherwise.
*/
bool is_set() const { return addr_.sun_path[0] != '\0'; }
/**
* Determines if the address is valid for a UNIX socket.
* @return @em true if the address is valid for a UNIX socket,
* @false otherwise.
*/
operator bool() const noexcept {
return family() == ADDRESS_FAMILY && is_set();
bool is_set() const noexcept override {
return addr_.sun_family == ADDRESS_FAMILY && addr_.sun_path[0] != '\0';
}
/**
* Gets the path to which this address refers.
Expand Down
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ endif()

target_compile_features(sockpp-objs PUBLIC cxx_std_14)

if(SOCKPP_WITH_EXCEPTIONS)
target_compile_options(sockpp-objs PUBLIC -DSOCKPP_WITH_EXCEPTIONS)
endif()

# Position indepence is only necessary for older compilers, but doesn't hurt
set_target_properties(sockpp-objs
PROPERTIES
Expand Down
29 changes: 15 additions & 14 deletions src/inet6_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// --------------------------------------------------------------------------
// This file is part of the "sockpp" C++ socket library.
//
// Copyright (c) 2019 Frank Pagliughi
// Copyright (c) 2019-2023 Frank Pagliughi
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -43,14 +43,6 @@ namespace sockpp {

// --------------------------------------------------------------------------

bool inet6_address::is_set() const
{
static const auto EMPTY_ADDR = sockaddr_in6{};
return std::memcmp(&addr_, &EMPTY_ADDR, SZ) != 0;
}

// --------------------------------------------------------------------------

in6_addr inet6_address::resolve_name(const string& saddr)
{
#if !defined(_WIN32)
Expand All @@ -66,13 +58,22 @@ in6_addr inet6_address::resolve_name(const string& saddr)
int gai_err = ::getaddrinfo(saddr.c_str(), NULL, &hints, &res);

#if !defined(_WIN32)
if (gai_err == EAI_SYSTEM)
throw sys_error();
if (gai_err == EAI_SYSTEM) {
#if defined(SOCKPP_WITH_EXCEPTIONS)
throw sys_error();
#else
return in6_addr{};
#endif
}
#endif

if (gai_err != 0)
throw getaddrinfo_error(gai_err, saddr);

if (gai_err != 0) {
#if defined(SOCKPP_WITH_EXCEPTIONS)
throw getaddrinfo_error(gai_err, saddr);
#else
return in6_addr{};
#endif
}

auto ipv6 = reinterpret_cast<sockaddr_in6*>(res->ai_addr);
auto addr = ipv6->sin6_addr;
Expand Down
Loading

0 comments on commit 7b82602

Please sign in to comment.