2#include "SockAddress.h"
3#include "TempFailure.h"
11struct sctp_status getStatus( int socket)
13 struct sctp_status status;
14 socklen_t size =
sizeof(status);
15 if( ::getsockopt( socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0)
16 throw SocketException(
"SCTPSocket::getsockopt failed");
22SCTPSocket::SCTPSocket( uint16_t numOutStreams ,
23 uint16_t maxInStreams ,
24 uint16_t maxAttempts ,
25 uint16_t maxInitTimeout )
29 setInitValues( numOutStreams, maxInStreams, maxAttempts, maxInitTimeout);
32SCTPSocket::SCTPSocket(
Handle&& handle)
37int SCTPSocket::bind(
const std::vector<std::string>& localAddresses,
unsigned short localPort )
39 std::vector<sockaddr_in> dest;
40 dest.reserve(localAddresses.size());
42 for(
const auto& address : localAddresses)
44 SockAddress addr( AddressFamily::IPv4, address, localPort);
46 std::memcpy( &native, addr.data(),
sizeof(native));
47 dest.push_back(native);
50 int ret = sctp_bindx( m_socket,
reinterpret_cast<sockaddr*
>(dest.data()),
static_cast<int>(dest.size()), SCTP_BINDX_ADD_ADDR);
52 throw SocketException(
"Set of local address and port failed (sctp_bindx)");
56int SCTPSocket::connect(
const std::vector<std::string>& foreignAddresses,
unsigned short foreignPort )
58 std::vector<sockaddr_in> dest;
59 dest.reserve(foreignAddresses.size());
61 for(
const auto& address : foreignAddresses)
63 SockAddress addr( AddressFamily::IPv4, address, foreignPort);
65 std::memcpy( &native, addr.data(),
sizeof(native));
66 dest.push_back(native);
70 int ret = sctp_connectx( m_socket,
reinterpret_cast<sockaddr*
>(dest.data()),
static_cast<int>(dest.size()), 0);
72 throw SocketException(
"Connect failed (sctp_connectx)");
74 m_peerDisconnected =
false;
78int SCTPSocket::state()
const
80 return getStatus(m_socket).sstat_state;
83int SCTPSocket::notAckedData()
const
85 return getStatus(m_socket).sstat_unackdata;
88int SCTPSocket::pendingData()
const
90 return getStatus(m_socket).sstat_penddata;
93unsigned SCTPSocket::inStreams()
const
95 return getStatus(m_socket).sstat_instrms;
98unsigned SCTPSocket::outStreams()
const
100 return getStatus(m_socket).sstat_outstrms;
103unsigned SCTPSocket::fragmentationPoint()
const
105 return getStatus(m_socket).sstat_fragmentation_point;
108std::string SCTPSocket::primaryAddress()
const
110 return std::string();
113int SCTPSocket::send(
const void* data,
size_t length, uint16_t stream,
unsigned ttl ,
unsigned context ,
114 unsigned ppid , abortFlag abort , switchAddressFlag switchAddr )
116 int ret = sctp_sendmsg( m_socket, data, length,
nullptr, 0, ppid, abort + switchAddr, stream, ttl, context);
118 throw SocketException(
"SCTPSocket::send failed (sctp_sendmsg)");
119 else if (
static_cast<size_t>(ret) < length)
120 throw SocketException(
"SCTP sent a fragemented packet!");
124int SCTPSocket::sendUnordered(
const void* data,
size_t length, uint16_t stream,
unsigned ttl ,
unsigned context ,
125 unsigned ppid , abortFlag abort ,
126 switchAddressFlag switchAddr )
128 int ret = sctp_sendmsg( m_socket, data, length,
nullptr, 0, ppid, abort + switchAddr + SCTP_UNORDERED, stream, ttl, context);
130 throw SocketException(
"SCTPSocket::send failed (sctp_sendmsg)");
131 else if (
static_cast<size_t>(ret) < length)
132 throw SocketException(
"SCTP sent a fragemented packet!");
136int SCTPSocket::receive(
void* data,
size_t maxLen, uint16_t& stream)
138 struct sctp_sndrcvinfo info;
140 if( (ret = sctp_recvmsg( m_socket, data, maxLen, 0, 0, &info, 0)) < 0)
141 throw SocketException(
"SCTPSocket::receive failed (sctp_recvmsg)");
142 stream = info.sinfo_stream;
146int SCTPSocket::receive(
void* data,
size_t maxLen, uint16_t& stream, receiveFlag& flag)
148 struct sctp_sndrcvinfo info;
150 if( (ret = sctp_recvmsg( m_socket, data, maxLen, 0, 0, &info, 0)) < 0)
151 throw SocketException(
"SCTPSocket::receive failed (sctp_recvmsg)");
152 stream = info.sinfo_stream;
153 flag =
static_cast<receiveFlag
>(info.sinfo_flags);
157int SCTPSocket::timedReceive(
void* data,
size_t maxLen, uint16_t& stream,
int timeout)
161 poll.events = POLLIN | POLLPRI | POLLRDHUP;
163 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout));
165 if( ret == 0)
return 0;
166 if( ret < 0)
throw SocketException(
"SCTPSocket::timedReceive failed (poll)");
168 if( poll.revents & POLLRDHUP || poll.revents & POLLHUP)
169 m_peerDisconnected =
true;
171 if( poll.revents & POLLIN || poll.revents & POLLPRI)
172 return receive( data, maxLen, stream);
174 if( poll.revents & (POLLERR | POLLNVAL))
175 throw SocketException(
"SCTPSocket::timedReceive failed (poll)");
180int SCTPSocket::timedReceive(
void* data,
size_t maxLen, uint16_t& stream, receiveFlag& flag,
int timeout)
184 poll.events = POLLIN | POLLPRI | POLLRDHUP;
186 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout));
188 if( ret == 0)
return 0;
189 if( ret < 0)
throw SocketException(
"SCTPSocket::timedReceive failed (poll)");
191 if( poll.revents & POLLRDHUP || poll.revents & POLLHUP)
192 m_peerDisconnected =
true;
194 if( poll.revents & POLLIN || poll.revents & POLLPRI)
195 return receive( data, maxLen, stream, flag);
197 if( poll.revents & (POLLERR | POLLNVAL))
198 throw SocketException(
"SCTPSocket::timedReceive failed (poll)");
215void SCTPSocket::setInitValues( uint16_t numOutStreams, uint16_t maxInStreams, uint16_t maxAttempts, uint16_t maxInitTimeout)
217 struct sctp_initmsg init;
218 init.sinit_num_ostreams = numOutStreams;
219 init.sinit_max_instreams = maxInStreams;
220 init.sinit_max_attempts = maxAttempts;
221 init.sinit_max_init_timeo = maxInitTimeout;
223 if( ::setsockopt( m_socket, IPPROTO_SCTP, SCTP_INITMSG, &init,
sizeof(init)) < 0)
224 throw SocketException(
"SCTPSocket construction failed (setsockopt)");
InternetSocket(int sockfd)
create socket from a SocketHandle returned by an accept() call
SocketHandle< SCTPSocket > Handle
Handle for a new socket returned by accept().
int accept() const
allows stream sockets to accept connections into Handles
int timedAccept(int timeout) const
allows stream sockets timed accept