simple-socket library 1.1.5
|
00001 #include "SCTPSocket.h" 00002 #include "TempFailure.h" 00003 00004 #include <vector> 00005 #include <netinet/in.h> 00006 #include <poll.h> 00007 00008 using namespace NET; 00009 00010 SCTPSocket::SCTPSocket( unsigned numOutStreams /* = 10 */, 00011 unsigned maxInStreams /* = 65535 */, 00012 unsigned maxAttempts /* = 4 */, 00013 unsigned maxInitTimeout /* = 0 */) 00014 : InternetSocket( STREAM, IPPROTO_SCTP) 00015 { 00016 setInitValues( numOutStreams, maxInStreams, maxAttempts, maxInitTimeout); 00017 } 00018 00019 SCTPSocket::SCTPSocket( Handle handle) 00020 : InternetSocket( handle.release() ) 00021 {} 00022 00023 int SCTPSocket::bind( const std::vector<std::string>& localAddresses, unsigned short localPort /* = 0 */) 00024 { 00025 size_t size = localAddresses.size(); 00026 std::vector<sockaddr_in> dest(size); 00027 00028 for( size_t i = 0; i < size; ++i) 00029 fillAddress( localAddresses[i], localPort, dest[i]); 00030 00031 int ret = sctp_bindx( m_socket, reinterpret_cast<sockaddr*>(dest.data()), size, SCTP_BINDX_ADD_ADDR); 00032 if(ret < 0) 00033 throw SocketException("Set of local address and port failed (sctp_bindx)"); 00034 return ret; 00035 } 00036 00037 int SCTPSocket::connect( const std::vector<std::string>& foreignAddresses, unsigned short foreignPort /* = 0 */) 00038 { 00039 size_t size = foreignAddresses.size(); 00040 std::vector<sockaddr_in> dest(size); 00041 00042 for( size_t i = 0; i < size; ++i) 00043 fillAddress( foreignAddresses[i], foreignPort, dest[i]); 00044 00045 // TODO maybe save connection id for later use 00046 int ret = sctp_connectx( m_socket, reinterpret_cast<sockaddr*>(dest.data()), size, 0); 00047 if(ret < 0) 00048 throw SocketException("Connect failed (sctp_connectx)"); 00049 00050 m_peerDisconnected = false; 00051 return ret; 00052 } 00053 00054 int SCTPSocket::state() const 00055 { 00056 struct sctp_status status; 00057 socklen_t size = sizeof(status); 00058 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00059 throw SocketException("SCTPSocket::state failed (getsockopt)"); 00060 return status.sstat_state; 00061 } 00062 00063 int SCTPSocket::notAckedData() const 00064 { 00065 struct sctp_status status; 00066 socklen_t size = sizeof(status); 00067 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00068 throw SocketException("SCTPSocket::notAckedData failed (getsockopt)"); 00069 return status.sstat_unackdata; 00070 } 00071 00072 int SCTPSocket::pendingData() const 00073 { 00074 struct sctp_status status; 00075 socklen_t size = sizeof(status); 00076 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00077 throw SocketException("SCTPSocket::pendingData failed (getsockopt)"); 00078 return status.sstat_penddata; 00079 } 00080 00081 unsigned SCTPSocket::inStreams() const 00082 { 00083 struct sctp_status status; 00084 socklen_t size = sizeof(status); 00085 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00086 throw SocketException("SCTPSocket::inStreams failed (getsockopt)"); 00087 return status.sstat_instrms; 00088 } 00089 00090 unsigned SCTPSocket::outStreams() const 00091 { 00092 struct sctp_status status; 00093 socklen_t size = sizeof(status); 00094 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00095 throw SocketException("SCTPSocket::outStreams failed (getsockopt)"); 00096 return status.sstat_outstrms; 00097 } 00098 00099 unsigned SCTPSocket::fragmentationPoint() const 00100 { 00101 struct sctp_status status; 00102 socklen_t size = sizeof(status); 00103 if( getsockopt( m_socket, IPPROTO_SCTP, SCTP_STATUS, &status, &size) < 0) 00104 throw SocketException("SCTPSocket::fragmentationPoint failed (getsockopt)"); 00105 return status.sstat_fragmentation_point; 00106 } 00107 00108 std::string SCTPSocket::primaryAddress() const 00109 { 00110 return std::string(); // TODO 00111 } 00112 00113 int SCTPSocket::send( const void* data, int length, unsigned stream, unsigned ttl /* = 0 */, unsigned context /* = 0 */, 00114 unsigned ppid /* = 0 */, abortFlag abort /* = KEEPALIVE */, switchAddressFlag switchAddr /* = KEEP_PRIMARY */) 00115 { 00116 int ret = sctp_sendmsg( m_socket, data, length, NULL, 0, ppid, abort + switchAddr, stream, ttl, context); 00117 if( ret < 0) 00118 throw SocketException("SCTPSocket::send failed (sctp_sendmsg)"); 00119 else if (ret < length) 00120 throw SocketException("SCTP sent a fragemented packet!"); 00121 return ret; 00122 } 00123 00124 int SCTPSocket::sendUnordered( const void* data, int length, unsigned stream, unsigned ttl /* = 0 */, unsigned context /* = 0 */, 00125 unsigned ppid /* = 0 */, abortFlag abort /* = KEEPALIVE */, 00126 switchAddressFlag switchAddr /* = KEEP_PRIMARY */) 00127 { 00128 int ret = sctp_sendmsg( m_socket, data, length, NULL, 0, ppid, abort + switchAddr + SCTP_UNORDERED, stream, ttl, context); 00129 if( ret < 0) 00130 throw SocketException("SCTPSocket::send failed (sctp_sendmsg)"); 00131 else if (ret < length) 00132 throw SocketException("SCTP sent a fragemented packet!"); 00133 return ret; 00134 } 00135 00136 int SCTPSocket::receive( void* data, int maxLen, unsigned& stream) 00137 { 00138 struct sctp_sndrcvinfo info; 00139 int ret; 00140 if( (ret = sctp_recvmsg( m_socket, data, maxLen, 0, 0, &info, 0)) < 0) 00141 throw SocketException("SCTPSocket::receive failed (sctp_recvmsg)"); 00142 stream = info.sinfo_stream; 00143 return ret; 00144 } 00145 00146 int SCTPSocket::receive( void* data, int maxLen, unsigned& stream, receiveFlag& flag) 00147 { 00148 struct sctp_sndrcvinfo info; 00149 int ret; 00150 if( (ret = sctp_recvmsg( m_socket, data, maxLen, 0, 0, &info, 0)) < 0) 00151 throw SocketException("SCTPSocket::receive failed (sctp_recvmsg)"); 00152 stream = info.sinfo_stream; 00153 flag = static_cast<receiveFlag>(info.sinfo_flags); 00154 return ret; 00155 } 00156 00157 int SCTPSocket::timedReceive( void* data, int maxLen, unsigned& stream, unsigned timeout) 00158 { 00159 struct pollfd poll; 00160 poll.fd = m_socket; 00161 poll.events = POLLIN | POLLPRI | POLLRDHUP; 00162 00163 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout)); 00164 00165 if( ret == 0) return 0; 00166 if( ret < 0) throw SocketException("SCTPSocket::timedReceive failed (poll)"); 00167 00168 if( poll.revents & POLLRDHUP) 00169 m_peerDisconnected = true; 00170 00171 if( poll.revents & POLLIN || poll.revents & POLLPRI) 00172 return receive( data, maxLen, stream); 00173 00174 return 0; 00175 } 00176 00177 int SCTPSocket::timedReceive( void* data, int maxLen, unsigned& stream, receiveFlag& flag, unsigned timeout) 00178 { 00179 struct pollfd poll; 00180 poll.fd = m_socket; 00181 poll.events = POLLIN | POLLPRI | POLLRDHUP; 00182 00183 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout)); 00184 00185 if( ret == 0) return 0; 00186 if( ret < 0) throw SocketException("SCTPSocket::timedReceive failed (poll)"); 00187 00188 if( poll.revents & POLLRDHUP) 00189 m_peerDisconnected = true; 00190 00191 if( poll.revents & POLLIN || poll.revents & POLLPRI) 00192 return receive( data, maxLen, stream, flag); 00193 00194 return 0; 00195 } 00196 00197 void SCTPSocket::listen( int backlog /* = 5 */) 00198 { 00199 int ret = ::listen( m_socket, backlog); 00200 if( ret < 0) 00201 throw SocketException("listen failed, most likely another socket is already listening on the same port"); 00202 } 00203 00204 SCTPSocket::Handle SCTPSocket::accept() const 00205 { 00206 int ret = ::accept( m_socket, 0, 0); 00207 if( ret < 0) 00208 throw SocketException("SCTPSocket::accept failed (accept)"); 00209 return Handle(ret); 00210 } 00211 00212 SCTPSocket::Handle SCTPSocket::timedAccept( unsigned timeout) const 00213 { 00214 struct pollfd poll; 00215 poll.fd = m_socket; 00216 poll.events = POLLIN; 00217 00218 int ret = TEMP_FAILURE_RETRY (::poll( &poll, 1, timeout)); 00219 00220 if( ret == 0) return Handle(); 00221 if( ret < 0) throw SocketException("SCTPSocket::timedAccept failed (poll)"); 00222 00223 ret = ::accept( m_socket, 0, 0); 00224 if( ret < 0) 00225 throw SocketException("SCTPSocket::timedAccept failed (accept)"); 00226 return Handle(ret); 00227 } 00228 00229 void SCTPSocket::setInitValues( unsigned numOutStreams, unsigned maxInStreams, unsigned maxAttempts, unsigned maxInitTimeout) 00230 { 00231 struct sctp_initmsg init; 00232 init.sinit_num_ostreams = numOutStreams; 00233 init.sinit_max_instreams = maxInStreams; 00234 init.sinit_max_attempts = maxAttempts; 00235 init.sinit_max_init_timeo = maxInitTimeout; 00236 00237 int ret = setsockopt( m_socket, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)); 00238 if( ret < 0) 00239 throw SocketException("SCTPSocket construction failed (setsockopt)"); 00240 }