summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/file/posixsocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/file/posixsocket.cpp')
-rw-r--r--src/osd/modules/file/posixsocket.cpp187
1 files changed, 105 insertions, 82 deletions
diff --git a/src/osd/modules/file/posixsocket.cpp b/src/osd/modules/file/posixsocket.cpp
index 2ce5ad05d5c..4770e91c6a9 100644
--- a/src/osd/modules/file/posixsocket.cpp
+++ b/src/osd/modules/file/posixsocket.cpp
@@ -2,7 +2,8 @@
// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb
//============================================================
//
-// sdlsocket.c - SDL socket (inet) access functions
+// sdlsocket.c - SDL socket (inet, unix domain) access
+// functions
//
// SDLMAME by Olivier Galibert and R. Belmont
//
@@ -16,17 +17,21 @@
#include <cstring>
#include <arpa/inet.h>
+#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/un.h>
#include <unistd.h>
namespace {
+
char const *const posixfile_socket_identifier = "socket.";
+char const *const posixfile_domain_identifier = "domain.";
class posix_osd_socket : public osd_file
@@ -37,7 +42,7 @@ public:
posix_osd_socket& operator=(posix_osd_socket const &) = delete;
posix_osd_socket& operator=(posix_osd_socket &&) = delete;
- posix_osd_socket(int sock, bool listening)
+ posix_osd_socket(int sock, bool listening) noexcept
: m_sock(sock)
, m_listening(listening)
{
@@ -49,7 +54,7 @@ public:
::close(m_sock);
}
- virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override
{
fd_set readfds;
FD_ZERO(&readfds);
@@ -58,12 +63,9 @@ public:
struct timeval timeout;
timeout.tv_sec = timeout.tv_usec = 0;
- if (select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0)
+ if (::select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0)
{
- char line[80];
- std::sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__);
- std::perror(line);
- return errno_to_file_error(errno);
+ return std::error_condition(errno, std::generic_category());
}
else if (FD_ISSET(m_sock, &readfds))
{
@@ -73,12 +75,12 @@ public:
ssize_t const result = ::read(m_sock, buffer, count);
if (result < 0)
{
- return errno_to_file_error(errno);
+ return std::error_condition(errno, std::generic_category());
}
else
{
actual = std::uint32_t(size_t(result));
- return error::NONE;
+ return std::error_condition();
}
}
else
@@ -87,7 +89,7 @@ public:
int const accepted = ::accept(m_sock, nullptr, nullptr);
if (accepted < 0)
{
- return errno_to_file_error(errno);
+ return std::error_condition(errno, std::generic_category());
}
else
{
@@ -96,36 +98,38 @@ public:
m_listening = false;
actual = 0;
- return error::NONE;
+ return std::error_condition();
}
}
}
else
{
- return error::FAILURE;
+ // no data available
+ actual = 0;
+ return std::error_condition();
}
}
- virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override
{
ssize_t const result = ::write(m_sock, buffer, count);
if (result < 0)
- return errno_to_file_error(errno);
+ return std::error_condition(errno, std::generic_category());
actual = std::uint32_t(size_t(result));
- return error::NONE;
+ return std::error_condition();
}
- virtual error truncate(std::uint64_t offset) override
+ virtual std::error_condition truncate(std::uint64_t offset) noexcept override
{
// doesn't make sense on socket
- return error::INVALID_ACCESS;
+ return std::errc::bad_file_descriptor;
}
- virtual error flush() override
+ virtual std::error_condition flush() noexcept override
{
// there's no simple way to flush buffers on a socket anyway
- return error::NONE;
+ return std::error_condition();
}
private:
@@ -133,6 +137,54 @@ private:
bool m_listening;
};
+
+template <typename T>
+std::error_condition create_socket(T const &sa, int sock, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept
+{
+ osd_file::ptr result;
+ if (openflags & OPEN_FLAG_CREATE)
+ {
+ // listening socket support
+ // bind socket...
+ if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sa), sizeof(sa)) < 0)
+ {
+ std::error_condition binderr(errno, std::generic_category());
+ ::close(sock);
+ return binderr;
+ }
+
+ // start to listen...
+ if (::listen(sock, 1) < 0)
+ {
+ std::error_condition lstnerr(errno, std::generic_category());
+ ::close(sock);
+ return lstnerr;
+ }
+
+ // mark socket as "listening"
+ result.reset(new (std::nothrow) posix_osd_socket(sock, true));
+ }
+ else
+ {
+ if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sa), sizeof(sa)) < 0)
+ {
+ std::error_condition connerr(errno, std::generic_category());
+ ::close(sock);
+ return connerr;
+ }
+ result.reset(new (std::nothrow) posix_osd_socket(sock, false));
+ }
+
+ if (!result)
+ {
+ ::close(sock);
+ return std::errc::not_enough_memory;
+ }
+ file = std::move(result);
+ filesize = 0;
+ return std::error_condition();
+}
+
} // anonymous namespace
@@ -141,7 +193,7 @@ private:
specification has the format "socket." host ":" port. Host may be simple
or fully qualified. Port must be between 1 and 65535.
*/
-bool posix_check_socket_path(std::string const &path)
+bool posix_check_socket_path(std::string const &path) noexcept
{
if (strncmp(path.c_str(), posixfile_socket_identifier, strlen(posixfile_socket_identifier)) == 0 &&
strchr(path.c_str(), ':') != nullptr) return true;
@@ -149,7 +201,15 @@ bool posix_check_socket_path(std::string const &path)
}
-osd_file::error posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+bool posix_check_domain_path(std::string const &path) noexcept
+{
+ if (strncmp(path.c_str(), posixfile_domain_identifier, strlen(posixfile_domain_identifier)) == 0)
+ return true;
+ return false;
+}
+
+
+std::error_condition posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept
{
char hostname[256];
int port;
@@ -157,7 +217,7 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla
struct hostent const *const localhost = ::gethostbyname(hostname);
if (!localhost)
- return osd_file::error::NOT_FOUND;
+ return std::errc::no_such_file_or_directory;
struct sockaddr_in sai;
memset(&sai, 0, sizeof(sai));
@@ -167,75 +227,38 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla
int const sock = ::socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
- return errno_to_file_error(errno);
+ return std::error_condition(errno, std::generic_category());
int const flag = 1;
- if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0)
+ if ((::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0) ||
+ (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0))
{
- int const err = errno;
+ std::error_condition sockopterr(errno, std::generic_category());
::close(sock);
- return errno_to_file_error(err);
+ return sockopterr;
}
- if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0)
- {
- int const err = errno;
- ::close(sock);
- return errno_to_file_error(err);
- }
+ return create_socket(sai, sock, openflags, file, filesize);
+}
- // listening socket support
- if (openflags & OPEN_FLAG_CREATE)
- {
- //printf("Listening for client at '%s' on port '%d'\n", hostname, port);
- // bind socket...
- if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0)
- {
- int const err = errno;
- ::close(sock);
- return errno_to_file_error(err);
- }
+std::error_condition posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept
+{
+ struct sockaddr_un sau;
+ memset(&sau, 0, sizeof(sau));
+ sau.sun_family = AF_UNIX;
+ strncpy(sau.sun_path, &path.c_str()[strlen(posixfile_domain_identifier)], sizeof(sau.sun_path)-1);
- // start to listen...
- if (::listen(sock, 1) < 0)
- {
- int const err = errno;
- ::close(sock);
- return errno_to_file_error(err);
- }
+ int const sock = ::socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ return std::error_condition(errno, std::generic_category());
- // mark socket as "listening"
- try
- {
- file = std::make_unique<posix_osd_socket>(sock, true);
- filesize = 0;
- return osd_file::error::NONE;
- }
- catch (...)
- {
- ::close(sock);
- return osd_file::error::OUT_OF_MEMORY;
- }
- }
- else
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
{
- //printf("Connecting to server '%s' on port '%d'\n", hostname, port);
- if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0)
- {
- ::close(sock);
- return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure
- }
- try
- {
- file = std::make_unique<posix_osd_socket>(sock, false);
- filesize = 0;
- return osd_file::error::NONE;
- }
- catch (...)
- {
- ::close(sock);
- return osd_file::error::OUT_OF_MEMORY;
- }
+ std::error_condition cntlerr(errno, std::generic_category());
+ ::close(sock);
+ return cntlerr;
}
+
+ return create_socket(sau, sock, openflags, file, filesize);
}