blob: b6332cf6e146d6585d3e790964d8ac71babfdddb [file] [log] [blame]
Ratan Gupta37a7a072016-12-14 00:51:23 +05301#include "sock_channel.hpp"
2
3#include <errno.h>
4#include <netinet/in.h>
5#include <sys/ioctl.h>
6#include <sys/socket.h>
7#include <unistd.h>
8
9#include <iostream>
10#include <string>
11
12namespace udpsocket
13{
14
15std::string Channel::getRemoteAddress() const
16{
Patrick Venture537ff142018-11-01 16:37:09 -070017 char tmp[INET_ADDRSTRLEN] = {0};
Ratan Gupta70b85272017-01-05 20:52:18 +053018 inet_ntop(AF_INET6, &address.inAddr.sin6_addr, tmp, sizeof(tmp));
Ratan Gupta37a7a072016-12-14 00:51:23 +053019 return std::string(tmp);
20}
21
22std::tuple<int, buffer> Channel::read()
23{
24 int rc = 0;
25 int readSize = 0;
26 ssize_t readDataLen = 0;
27 buffer outBuffer(0);
28
29 if (ioctl(sockfd, FIONREAD, &readSize) < 0)
30 {
Ratan Gupta1ee36392017-02-10 22:25:59 +053031 std::cerr << "Channel::Read : ioctl failed with errno = " << errno;
Ratan Gupta37a7a072016-12-14 00:51:23 +053032 rc = -errno;
33 return std::make_tuple(rc, std::move(outBuffer));
34 }
35
36 outBuffer.resize(readSize);
37 auto bufferSize = outBuffer.size();
38 auto outputPtr = outBuffer.data();
39
Ratan Gupta5e008872017-02-10 12:01:46 +053040 address.addrSize = static_cast<socklen_t>(sizeof(address.inAddr));
Ratan Gupta37a7a072016-12-14 00:51:23 +053041
42 do
43 {
Patrick Venture537ff142018-11-01 16:37:09 -070044 readDataLen = recvfrom(sockfd, // File Descriptor
45 outputPtr, // Buffer
46 bufferSize, // Bytes requested
47 0, // Flags
48 &address.sockAddr, // Address
49 &address.addrSize); // Address Length
Ratan Gupta37a7a072016-12-14 00:51:23 +053050
Ratan Gupta908dee32017-03-21 15:02:06 +053051 if (readDataLen == 0) // Peer has performed an orderly shutdown
Ratan Gupta37a7a072016-12-14 00:51:23 +053052 {
Ratan Gupta37a7a072016-12-14 00:51:23 +053053 outBuffer.resize(0);
54 rc = -1;
55 }
56 else if (readDataLen < 0) // Error
57 {
58 rc = -errno;
Ratan Gupta1ee36392017-02-10 22:25:59 +053059 std::cerr << "Channel::Read : Receive Error Fd[" << sockfd << "]"
Ratan Gupta37a7a072016-12-14 00:51:23 +053060 << "errno = " << rc << "\n";
61 outBuffer.resize(0);
62 }
Patrick Venture537ff142018-11-01 16:37:09 -070063 } while ((readDataLen < 0) && (-(rc) == EINTR));
Ratan Gupta37a7a072016-12-14 00:51:23 +053064
65 // Resize the vector to the actual data read from the socket
66 outBuffer.resize(readDataLen);
67 return std::make_tuple(rc, std::move(outBuffer));
68}
69
70int Channel::write(buffer& inBuffer)
71{
72 int rc = 0;
73 auto outputPtr = inBuffer.data();
74 auto bufferSize = inBuffer.size();
75 auto spuriousWakeup = false;
76 ssize_t writeDataLen = 0;
77 timeval varTimeout = timeout;
78
79 fd_set writeSet;
80 FD_ZERO(&writeSet);
81 FD_SET(sockfd, &writeSet);
82
83 do
84 {
85 spuriousWakeup = false;
86
87 rc = select((sockfd + 1), nullptr, &writeSet, NULL, &varTimeout);
88
89 if (rc > 0)
90 {
91 if (FD_ISSET(sockfd, &writeSet))
92 {
Patrick Venture537ff142018-11-01 16:37:09 -070093 address.addrSize =
94 static_cast<socklen_t>(sizeof(address.inAddr));
Ratan Gupta37a7a072016-12-14 00:51:23 +053095 do
96 {
Patrick Venture537ff142018-11-01 16:37:09 -070097 writeDataLen =
98 sendto(sockfd, // File Descriptor
99 outputPtr, // Message
100 bufferSize, // Length
101 MSG_NOSIGNAL, // Flags
102 &address.sockAddr, // Destination Address
103 address.addrSize); // Address Length
Ratan Gupta37a7a072016-12-14 00:51:23 +0530104
105 if (writeDataLen < 0)
106 {
107 rc = -errno;
Patrick Venture537ff142018-11-01 16:37:09 -0700108 std::cerr
109 << "Channel::Write: Write failed with errno:" << rc
110 << "\n";
Ratan Gupta37a7a072016-12-14 00:51:23 +0530111 }
112 else if (static_cast<size_t>(writeDataLen) < bufferSize)
113 {
114 rc = -1;
115 std::cerr << "Channel::Write: Complete data not written"
Patrick Venture537ff142018-11-01 16:37:09 -0700116 " to the socket\n";
Ratan Gupta37a7a072016-12-14 00:51:23 +0530117 }
Patrick Venture537ff142018-11-01 16:37:09 -0700118 } while ((writeDataLen < 0) && (-(rc) == EINTR));
Ratan Gupta37a7a072016-12-14 00:51:23 +0530119 }
120 else
121 {
122 // Spurious wake up
Ratan Gupta1ee36392017-02-10 22:25:59 +0530123 std::cerr << "Spurious wake up on select (writeset)\n";
Ratan Gupta37a7a072016-12-14 00:51:23 +0530124 spuriousWakeup = true;
125 }
126 }
127 else
128 {
129 if (rc == 0)
130 {
131 // Timed out
132 rc = -1;
Ratan Gupta1ee36392017-02-10 22:25:59 +0530133 std::cerr << "We timed out on select call (writeset)\n";
Ratan Gupta37a7a072016-12-14 00:51:23 +0530134 }
135 else
136 {
137 // Error
Patrick Venture537ff142018-11-01 16:37:09 -0700138 rc = -errno;
139 std::cerr << "select call (writeset) had an error : " << rc
140 << "\n";
Ratan Gupta37a7a072016-12-14 00:51:23 +0530141 }
Ratan Gupta37a7a072016-12-14 00:51:23 +0530142 }
Patrick Venture537ff142018-11-01 16:37:09 -0700143 } while (spuriousWakeup);
Ratan Gupta37a7a072016-12-14 00:51:23 +0530144
145 return rc;
146}
147
148} // namespace udpsocket