summaryrefslogtreecommitdiffstats
path: root/socket_channel.cpp
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2016-08-10 06:36:33 -0500
committerPatrick Williams <patrick@stwcx.xyz>2016-11-08 19:13:25 +0000
commitaaeb29e3ee61064e40aee935d952faef89c589a5 (patch)
tree1f8fd02e28f4b8e4b8230e19cfca3e7cc315e98d /socket_channel.cpp
parent9b672192023546296aeaad77252daccdf09ffbf3 (diff)
downloadphosphor-net-ipmid-aaeb29e3ee61064e40aee935d952faef89c589a5.tar.gz
phosphor-net-ipmid-aaeb29e3ee61064e40aee935d952faef89c589a5.zip
IPMI Socket Class to encapsulate the socket operations
This class represents the details regarding an IPMI client like IP address, port number and the file descriptor associated with it. The operations provided are reading the UDP packet, writing the packet. Change-Id: I58cde0edb04fd2fbedd3068de83379eebea8508d Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
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