summaryrefslogtreecommitdiffstats
path: root/socket_channel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'socket_channel.cpp')
-rw-r--r--socket_channel.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/socket_channel.cpp b/socket_channel.cpp
new file mode 100644
index 0000000..4a6d827
--- /dev/null
+++ b/socket_channel.cpp
@@ -0,0 +1,156 @@
+#include "socket_channel.hpp"
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <string>
+
+namespace udpsocket
+{
+
+std::string Channel::getRemoteAddress() const
+{
+ char tmp[INET_ADDRSTRLEN] = { 0 };
+ inet_ntop(AF_INET, &address.inAddr.sin_addr, tmp, sizeof(tmp));
+ return std::string(tmp);
+}
+
+std::tuple<int, buffer> Channel::read()
+{
+ int rc = 0;
+ int readSize = 0;
+ ssize_t readDataLen = 0;
+ buffer outBuffer(0);
+
+ if (ioctl(sockfd, FIONREAD, &readSize) < 0)
+ {
+ std::cerr << "E> Channel::Read : ioctl failed with errno = " << errno;
+ rc = -errno;
+ return std::make_tuple(rc, std::move(outBuffer));
+ }
+
+ outBuffer.resize(readSize);
+ auto bufferSize = outBuffer.size();
+ auto outputPtr = outBuffer.data();
+
+ address.addrSize = sizeof(address.inAddr);
+
+ do
+ {
+ readDataLen = recvfrom(sockfd, // File Descriptor
+ outputPtr , // Buffer
+ bufferSize, // Bytes requested
+ 0, // Flags
+ &address.sockAddr, // Address
+ &address.addrSize); // Address Length
+
+ if (readDataLen > 0) // Data read from the socket
+ {
+ std::cout << "I> Channel::Read : DataIn Fd[" << sockfd << "] Req["
+ << bufferSize << "] Recv[" << readDataLen << "]\n";
+ }
+ else if (readDataLen == 0) // Peer has performed an orderly shutdown
+ {
+ std::cerr << "E> Channel::Read : Connection Closed Fd[" << sockfd
+ << "]\n";
+ outBuffer.resize(0);
+ rc = -1;
+ }
+ else if (readDataLen < 0) // Error
+ {
+ rc = -errno;
+ std::cerr << "E> Channel::Read : Receive Error Fd[" << sockfd << "]"
+ << "errno = " << rc << "\n";
+ outBuffer.resize(0);
+ }
+ }
+ while ((readDataLen < 0) && (-(rc) == EINTR));
+
+ // Resize the vector to the actual data read from the socket
+ outBuffer.resize(readDataLen);
+ return std::make_tuple(rc, std::move(outBuffer));
+}
+
+int Channel::write(buffer& inBuffer)
+{
+ int rc = 0;
+ auto outputPtr = inBuffer.data();
+ auto bufferSize = inBuffer.size();
+ auto spuriousWakeup = false;
+ ssize_t writeDataLen = 0;
+ timeval varTimeout = timeout;
+
+ fd_set writeSet;
+ FD_ZERO(&writeSet);
+ FD_SET(sockfd, &writeSet);
+
+ do
+ {
+ spuriousWakeup = false;
+
+ rc = select((sockfd + 1), nullptr, &writeSet, NULL, &varTimeout);
+
+ if (rc > 0)
+ {
+ if (FD_ISSET(sockfd, &writeSet))
+ {
+ address.addrSize = sizeof(address.inAddr);
+ do
+ {
+ writeDataLen = sendto(sockfd, // File Descriptor
+ outputPtr, // Message
+ bufferSize, // Length
+ MSG_NOSIGNAL, // Flags
+ &address.sockAddr,// Destination Address
+ address.addrSize);// Address Length
+
+ if (writeDataLen < 0)
+ {
+ rc = -errno;
+ std::cerr << "Channel::Write: Write failed with errno:"
+ << rc << "\n";
+ }
+ else if (static_cast<size_t>(writeDataLen) < bufferSize)
+ {
+ rc = -1;
+ std::cerr << "Channel::Write: Complete data not written"
+ " to the socket\n";
+ }
+ }
+ while ((writeDataLen < 0) && (-(rc) == EINTR));
+ }
+ else
+ {
+ // Spurious wake up
+ std::cerr << "E> Spurious wake up on select (writeset)\n";
+ spuriousWakeup = true;
+ }
+ }
+ else
+ {
+ if (rc == 0)
+ {
+ // Timed out
+ rc = -1;
+ std::cerr << "E> We timed out on select call (writeset)\n";
+ }
+ else
+ {
+ // Error
+ rc = -errno;
+ std::cerr << "E> select call (writeset) had an error : "
+ << rc << "\n";
+ }
+
+ }
+ }
+ while (spuriousWakeup);
+
+ return rc;
+}
+
+} // namespace udpsocket
OpenPOWER on IntegriCloud