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