openMSX
Socket.cc
Go to the documentation of this file.
1#include "Socket.hh"
2
3#include "MSXException.hh" // FatalError
4#include "utf8_checked.hh"
5
6#include <bit>
7#include <cerrno>
8#include <cstring>
9
10namespace openmsx {
11
12std::string sock_error()
13{
14#ifdef _WIN32
15 wchar_t* s = nullptr;
16 FormatMessageW(
17 FORMAT_MESSAGE_ALLOCATE_BUFFER |
18 FORMAT_MESSAGE_FROM_SYSTEM |
19 FORMAT_MESSAGE_IGNORE_INSERTS,
20 nullptr, WSAGetLastError(), 0, reinterpret_cast<LPWSTR>(&s),
21 0, nullptr);
22 std::string result = utf8::utf16to8(s);
23 LocalFree(s);
24 return result;
25#else
26 return strerror(errno);
27#endif
28}
29
31{
32#ifdef _WIN32
33 // MAKEWORD is #define'd as ((WORD)(((BYTE)(a))|(((WORD)((BYTE)(b)))<<8)))
34 // but using that gives old-style-cast warnings
35 WORD w = 1 | (1 << 8); // MAKEWORD(1, 1)
36 WSAData wsaData;
37 if (WSAStartup(w, &wsaData) != 0) {
38 throw FatalError(sock_error());
39 }
40#else
41 // nothing needed for unix
42#endif
43}
44
46{
47#ifdef _WIN32
48 WSACleanup();
49#else
50 // nothing needed for unix
51#endif
52}
53
54// close a connection
56{
57#ifdef _WIN32
58 closesocket(sd);
59#else
60 close(sd);
61#endif
62}
63
64
65ptrdiff_t sock_recv(SOCKET sd, char* buf, size_t count)
66{
67 ptrdiff_t num = recv(sd, buf, count, 0);
68 if (num > 0) return num; // normal case
69 if (num == 0) return -1; // socket was closed by client
70#ifdef _WIN32
71 // Something bad happened on the socket. It could just be a
72 // "would block" notification, or it could be something more
73 // serious. WSAEWOULDBLOCK can happen after select() says a
74 // socket is readable under Win9x, it doesn't happen on
75 // WinNT/2000 or on Unix.
76 int err;
77 int errLen = sizeof(err);
78 getsockopt(sd, SOL_SOCKET, SO_ERROR, std::bit_cast<char*>(&err), &errLen);
79 if (err == WSAEWOULDBLOCK) return 0;
80 return -1;
81#else
82 if (errno == EWOULDBLOCK) return 0;
83 return -1;
84#endif
85}
86
87
88ptrdiff_t sock_send(SOCKET sd, const char* buf, size_t count)
89{
90 ptrdiff_t num = send(sd, buf, count, 0);
91 if (num >= 0) return num; // normal case
92#ifdef _WIN32
93 int err;
94 int errLen = sizeof(err);
95 getsockopt(sd, SOL_SOCKET, SO_ERROR, std::bit_cast<char*>(&err), &errLen);
96 if (err == WSAEWOULDBLOCK) return 0;
97 return -1;
98#else
99 if (errno == EWOULDBLOCK) return 0;
100 return -1;
101#endif
102}
103
104} // namespace openmsx
This file implemented 3 utility functions:
Definition Autofire.cc:11
ptrdiff_t sock_send(SOCKET sd, const char *buf, size_t count)
Definition Socket.cc:88
void sock_close(SOCKET sd)
Definition Socket.cc:55
void sock_startup()
Definition Socket.cc:30
std::string sock_error()
Definition Socket.cc:12
int SOCKET
Definition Socket.hh:25
void sock_cleanup()
Definition Socket.cc:45
ptrdiff_t sock_recv(SOCKET sd, char *buf, size_t count)
Definition Socket.cc:65
octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result)