diff --git a/include/NetworkEncoding.h b/include/NetworkEncoding.h index d6992e1..6e4b4f1 100644 --- a/include/NetworkEncoding.h +++ b/include/NetworkEncoding.h @@ -67,6 +67,7 @@ inline void *get_sin_addr(struct sockaddr *sa) #define SOCKET_ERROR -1 #include #include +#include #endif diff --git a/include/Socket.h b/include/Socket.h index c083db8..7531941 100644 --- a/include/Socket.h +++ b/include/Socket.h @@ -6,6 +6,7 @@ #define FRNETLIB_SOCKET_H +#include "NetworkEncoding.h" #include "Packet.h" namespace fr @@ -21,9 +22,11 @@ namespace fr BindFailed = 3, Disconnected = 4, Error = 5, + WouldBlock = 6, }; Socket() + : is_blocking(true) { } @@ -88,9 +91,33 @@ namespace fr return socket_descriptor; } + /*! + * Sets the socket to blocking or non-blocking. + * + * @param should_block True for blocking (default argument), false otherwise. + */ + inline virtual void set_blocking(bool should_block = true) + { + //Don't update it if we're already in that mode + if(should_block == is_blocking) + return; + + //Different API calls needed for both windows and unix + #ifdef WIN32 + u_long non_blocking = should_block ? 0 : 1; + ioctlsocket(socket_descriptor, FIONBIO, &non_blocking); + #else + int flags = fcntl(socket_descriptor, F_GETFL, 0); + fcntl(socket_descriptor, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags ^= O_NONBLOCK); + #endif + + is_blocking = should_block; + } + protected: int32_t socket_descriptor; std::string remote_address; + bool is_blocking; }; } diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp index 736393e..4801ccf 100644 --- a/src/TcpSocket.cpp +++ b/src/TcpSocket.cpp @@ -44,17 +44,15 @@ namespace fr { sent += status; } - else + else if(errno != EWOULDBLOCK && errno != EAGAIN) //Don't exit if the socket just couldn't block { if(status == -1) { return Socket::Status::Error; } - else - { - is_connected = false; - return Socket::Status::Disconnected; - } + + is_connected = false; + return Socket::Status::Disconnected; } } return Socket::Status::Success; @@ -122,15 +120,17 @@ namespace fr } else { - if(status == -1) + if(errno == EWOULDBLOCK || errno == EAGAIN) + { + return Socket::Status::WouldBlock; + } + else if(status == -1) { return Socket::Status::Error; } - else - { - is_connected = false; - return Socket::Status::Disconnected; - } + + is_connected = false; + return Socket::Status::Disconnected; } if(received > data_size)