24 #define _WIN32_WINNT 0x0501
30 #include <sys/socket.h>
33 #include <sys/types.h>
50 #define RC_SockType SOCKET
51 #define RC_InvSock INVALID_SOCKET
52 #define RC_SockErr SOCKET_ERROR
53 #define RC_CloseSock closesocket
54 #define RC_WouldBlock WSAEWOULDBLOCK
55 #define RC_SockErrorAt WSAGetLastError()
56 #define RC_SockReturn int
58 #define RC_SockType int
61 #define RC_CloseSock close
62 #define RC_WouldBlock EWOULDBLOCK
63 #define RC_SockErrorAt errno
64 #define RC_SockReturn ssize_t
88 inline ~SockHelper() {
106 inline bool DataReady(
bool do_block =
true)
const {
109 FD_SET(socket, &readset);
110 struct timeval *timeptr = NULL;
111 struct timeval timeout;
117 int result = select(socket+1, &readset, NULL, NULL, timeptr);
122 inline bool CanSend(
bool do_block =
true)
const {
125 FD_SET(socket, &writeset);
126 struct timeval *timeptr = NULL;
127 struct timeval timeout;
133 int result = select(socket+1, NULL, &writeset, NULL, timeptr);
138 inline void ReadMore(
size_t amnt_wanted = -1,
bool do_block =
true) {
139 size_t amnt_left = full_to - index;
140 if (amnt_wanted < amnt_left) {
144 bool got_data =
false;
152 if (amnt_wanted ==
size_t(-1)) {
153 amnt_wanted = buf.size();
156 if (amnt_wanted > buf.size()) {
157 buf.Resize(amnt_wanted);
160 if (index + amnt_wanted > buf.size()) {
161 buf.CopyData(0, index, amnt_left);
164 amnt_wanted = amnt_wanted - amnt_left;
167 bytes_recv = recv(socket,
reinterpret_cast<char*
>(buf.Raw()) +
168 full_to, amnt_wanted, 0);
178 full_to += bytes_recv;
180 }
while (do_block && !got_data);
184 size_t SendData(
const char* arr,
size_t len,
bool do_block =
true) {
185 const char *arr_current = arr;
186 size_t len_left = len;
194 bytes_sent = send(socket, arr, len, 0);
203 arr_current += bytes_sent;
204 len_left -= bytes_sent;
205 }
while (do_block && len_left > 0);
211 std::atomic<RC_SockType> socket;
234 helper =
new SockHelper(new_sock);
237 bool is_non_blocking =
false;
240 unsigned long mode = 1;
241 if (ioctlsocket(new_sock, FIONBIO, &mode) == NO_ERROR) {
242 is_non_blocking =
true;
245 int flags = fcntl(new_sock, F_GETFL, 0);
247 if (fcntl(new_sock, F_SETFL, flags | O_NONBLOCK) != -1) {
248 is_non_blocking =
true;
252 if (!is_non_blocking) {
269 helper->remote_addr = remote_addr;
270 helper->remote_port = remote_port;
275 return helper->remote_addr;
280 return helper->remote_port;
289 inline bool DataReady(
bool block_until_ready =
false)
const {
290 return helper->DataReady(block_until_ready);
298 inline bool CanSend(
bool block_until_ready =
false)
const {
299 return helper->CanSend(block_until_ready);
309 FILE* sfp = fdopen(helper->socket,
"a+");
315 frw.
SetFilename(helper->remote_addr +
" " + helper->remote_port);
322 return helper->socket;
336 helper->ReadMore(amnt_to_read, do_block);
338 size_t elem_in_helper = (helper->full_to - helper->index)
340 size_t elem_to_copy =
341 buf.
size() < elem_in_helper ? buf.
size() : elem_in_helper;
343 size_t bytes_to_copy = elem_to_copy * buf.
TypeSize();
345 buf.
CopyFrom(helper->buf, helper->index, bytes_to_copy);
346 helper->index += bytes_to_copy;
359 inline size_t Recv(
RStr& str,
bool crop_newline =
true,
360 bool do_block =
true) {
367 if (helper->full_to == helper->index) {
368 helper->ReadMore(-1, do_block);
369 if (helper->full_to == 0) {
374 char c = helper->buf[helper->index];
392 while (arr.
size() > 0 && arr[arr.
size()-1] ==
'\r') {
412 return helper->SendData(buf.
Raw(), buf.Size()*buf.
TypeSize(), do_block);
422 inline size_t Send(
RStr str,
bool do_block =
true) {
423 return helper->SendData(str.
c_str(), str.
size(), do_block);
444 err = WSAStartup(0x0202, &wsa_data);
450 memset (&sa, 0,
sizeof(sa));
451 sa.sa_handler = SIG_IGN;
452 sigaction(SIGPIPE, &sa, NULL);
466 const RStr& port,
bool quiet_fail=
true) {
468 struct addrinfo hints;
469 struct addrinfo *ai_list, *addr;
475 memset(&hints, 0,
sizeof(hints));
476 hints.ai_family = AF_UNSPEC;
477 hints.ai_socktype = SOCK_STREAM;
479 int aierr = getaddrinfo(host.
c_str(), port.
c_str(), &hints, &ai_list);
487 for (addr = ai_list; addr != NULL; addr = addr->ai_next) {
488 sfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
494 if (connect(sfd, addr->ai_addr, addr->ai_addrlen) !=
RC_SockErr) {
501 freeaddrinfo(ai_list);
511 connection =
Sock(sfd);
533 struct addrinfo hints;
534 struct addrinfo *ai_list, *addr;
539 memset(&hints, 0,
sizeof(hints));
540 hints.ai_family = AF_UNSPEC;
541 hints.ai_socktype = SOCK_STREAM;
542 hints.ai_flags = AI_PASSIVE;
544 int aierr = getaddrinfo(NULL, port.
c_str(), &hints, &ai_list);
549 for (addr = ai_list; addr != NULL; addr = addr->ai_next) {
550 sfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
555 if (::bind(sfd, addr->ai_addr, addr->ai_addrlen) == 0) {
567 freeaddrinfo(ai_list);
597 struct sockaddr_in6 addr;
598 socklen_t len =
sizeof(addr);
602 acc_sock = accept(sockfd,
reinterpret_cast<sockaddr*
>(&addr), &len);
611 connection =
Sock(acc_sock);
615 if (getnameinfo(
reinterpret_cast<sockaddr*
>(&addr),
sizeof(addr), host,
616 2048, port, 2048, NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
A reference counting ptr that is auto-deleted as the last copy leaves scope.
Provides a one-dimensional vector-like structure.
Provides informative exception handling.
#define Throw_RC_Type(Type, err)
Use this to throw an RC:ErrorMsg subtype exception.
Definition: Errors.h:282
#define Throw_RC_Error(err)
Use this to throw an RC:ErrorMsg exception.
Definition: Errors.h:274
Provides file input and output, and file / directory tools.
#define RC_SockReturn
The return type for send and recv calls.
Definition: Net.h:56
#define RC_SockType
The standard socket type used in socket calls for a given system.
Definition: Net.h:50
#define RC_SockErr
The value returned for a socket error.
Definition: Net.h:52
#define RC_WouldBlock
The return value for a socket call which would block.
Definition: Net.h:54
#define RC_CloseSock
The function for manually closing sockets.
Definition: Net.h:53
#define RC_SockErrorAt
The variable or function call for obtaining the last error.
Definition: Net.h:55
#define RC_InvSock
The value returned for an invalid socket.
Definition: Net.h:51
Provides a robust value-added wrapper for std::string.
Provides typedefs and routines for working with primitives.
#define RC_THREAD_LOCAL
Provides thread_local if available.
Definition: Types.h:61
A reference counting ptr that auto-deletes what it points to when the last copy leaves scope or is ot...
Definition: APtr.h:39
A bounds-safe one-dimensional vector-like structure.
Definition: Data1D.h:49
size_t TypeSize() const
Returns the size of this Data1D's type.
Definition: Data1D.h:361
T * Raw() const
Access a raw unprotected C-pointer to the enclosed data.
Definition: Data1D.h:356
void Reserve(const size_t reserve_size)
Reserve storage without resizing the array.
Definition: Data1D.h:271
size_t size() const
Returns the current number of elements.
Definition: Data1D.h:359
void Resize(const size_t resize_size)
Resize the array, reallocating if necessary.
Definition: Data1D.h:302
Data1D & CopyFrom(const Data1D< T2 > &other)
Copy data from any type with a compatible assignment operator.
Definition: Data1D.h:389
void SetFilename(const RStr &newfilename) const
Manually changes the associated filename.
Definition: File.h:356
A file class for both reading and writing that provides buffered and unbuffered output to files.
Definition: File.h:1124
Listens to the specified port for incoming TCP connections.
Definition: Net.h:519
~Listener()
If open, this closes the port being listened to.
Definition: Net.h:578
SOCKET Raw() const
Provides the raw socket descriptor being listened to.
Definition: Net.h:586
Listener(const RStr &port)
Begin listening to the specified port for incoming TCP connections.
Definition: Net.h:530
bool Accept(Sock &connection, bool quiet_fail=true)
Accept an incoming connection, with read/write access through the FileRW connection.
Definition: Net.h:595
Provides both client and server sides of blocking TCP connections.
Definition: Net.h:429
static void InitializeSockets()
Automatically called by Connect and Listener.
Definition: Net.h:438
static bool Connect(Sock &connection, const RStr &host, const RStr &port, bool quiet_fail=true)
Opens a TCP connection to host:port.
Definition: Net.h:465
A bounds-safe string class which provides an identical interface to std::string plus many convenience...
Definition: RStr.h:110
size_t size() const
Returns the length of the string.
Definition: RStr.h:263
const char * c_str() const
Provides a null-terminated C style string corresponding to RStr.
Definition: RStr.h:622
A portable socket interface for reading and writing to an open socket.
Definition: Net.h:74
size_t Send(Data1D< T > buf, bool do_block=true)
Sends the contents of buf through the socket.
Definition: Net.h:411
SOCKET Raw() const
Return the raw encapsulated socket.
Definition: Net.h:321
size_t Recv(RStr &str, bool crop_newline=true, bool do_block=true)
Receive characters into str until a newline or the end of data.
Definition: Net.h:359
RStr GetRemoteAddr() const
Get the remote address this socket is connected to.
Definition: Net.h:274
void Close()
Manually close the socket.
Definition: Net.h:263
void SetRemote(RStr remote_addr, RStr remote_port)
For record-keeping, set the remote address and port.
Definition: Net.h:268
bool DataReady(bool block_until_ready=false) const
Returns true if data is ready for reading.
Definition: Net.h:289
bool CanSend(bool block_until_ready=false) const
Returns true if the socket is ready to send data.
Definition: Net.h:298
FileRW ToFileRW()
On unix-based systems, return a FileRW coresponding to this socket.
Definition: Net.h:306
Sock(SOCKET new_sock=INVALID_SOCKET)
Encapsulate a new socket, receiving the base socket type of the system (int or SOCKET).
Definition: Net.h:233
RStr GetRemotePort() const
Get the remote port this socket is connected to.
Definition: Net.h:279
size_t Recv(Data1D< T > buf, bool do_block=true)
Receive data from the socket into buf, up to the size of buf.
Definition: Net.h:332
size_t Send(RStr str, bool do_block=true)
Sends the contents of str through the socket.
Definition: Net.h:422