+ /**
+ * Get a string socket option.
+ * \param option The option to set.
+ * \param value The new value.
+ * \param level The layer to handle the option.
+ * \return 0 on success, -1 on failure.
+ */
+ int get(int option, std::string& value, int level = SOL_SOCKET) const
+ {
+ char str[256] = {'\0'};
+ socklen_t size = sizeof(str);
+
+ int result = getsockopt(mImpl.fd, level, option, &str, &size);
+ value.assign(str, size);
+ return result;
+ }
+
+
+ void setBlocking(bool isBlocking)
+ {
+ int value = isBlocking;
+#ifdef HAVE_FCNTL
+ int flags = fcntl(mImpl.fd, F_GETFL);
+ fcntl(mImpl.fd, F_SETFL, flags | (value ? O_NONBLOCK : 0));
+#else
+ ioctl(mImpl.fd, FIONBIO, value);
+#endif
+ }
+
+ bool isBlocking() const
+ {
+#ifdef HAVE_FCNTL
+ int flags = fcntl(mImpl.fd, F_GETFL);
+ return flags & O_NONBLOCK;
+#else
+ int value;
+ ioctl(mImpl.fd, FIONBIO, &value);
+ return value;
+#endif
+ }
+
+
+ /**
+ * Write some bytes to the socket. Use this for connected sockets.
+ * \param bytes The bytes.
+ * \param size The number of bytes.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const void* bytes, size_t size, int flags = 0)
+ {
+ return send(mImpl.fd, bytes, size, flags);
+ }
+
+ /**
+ * Write some bytes to the socket using the given address. Use this
+ * for unconnected sockets.
+ * \param bytes The bytes.
+ * \param size The number of bytes.
+ * \param address The address to send to.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const void* bytes,
+ size_t size,
+ const SocketAddress& address,
+ int flags = 0)
+ {
+ return sendto(mImpl.fd, bytes, size, flags,
+ address.address(), address.size());
+ }
+
+ /**
+ * Write a packet to the socket. Use this for connected sockets.
+ * \param packet The packet.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const Packet& packet, int flags = 0)
+ {
+ return write(packet.bytes(), packet.size(), flags);
+ }
+
+ /**
+ * Write a packet to the socket using the given address. Use this for
+ * unconnected sockets.
+ * \param packet The packet.
+ * \param address The address to send to.
+ * \param flags The send options.
+ * \return The number of bytes written.
+ */
+ ssize_t write(const Packet& packet,
+ const SocketAddress& address,
+ int flags = 0)
+ {
+ return write(packet.bytes(), packet.size(), address, flags);
+ }
+
+
+ /**
+ * Read some bytes from the socket. Use this for connected sockets.
+ * \param bytes The buffer to store the bytes.
+ * \param size The size of the buffer.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(void* bytes, size_t size, int flags = 0)
+ {
+ ssize_t result = recv(mImpl.fd, bytes, size, flags);
+ if (result == 0) mImpl.isConnected = false;
+ return result;
+ }
+
+ /**
+ * Read some bytes from the socket using the given address. Use this
+ * for unconnected sockets.
+ * \param bytes The buffer to store the bytes.
+ * \param size The size of the buffer.
+ * \param address The address to read from.
+ * \param flags The recv options.
+ * \return The number of bytes read.
+ */
+ ssize_t read(void* bytes,
+ size_t size,
+ SocketAddress& address,
+ int flags = 0)