00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "SctpSocket.h"
00024 #ifdef USE_SCTP
00025 #include <Utility.h>
00026 #include "ISocketHandler.h"
00027 #include <errno.h>
00028 #include "Ipv4Address.h"
00029 #include "Ipv6Address.h"
00030
00031
00032 #ifdef SOCKETS_NAMESPACE
00033 namespace SOCKETS_NAMESPACE
00034 {
00035 #endif
00036
00037
00038 SctpSocket::SctpSocket(ISocketHandler& h,int type) : Socket(h)
00039 ,m_type(type)
00040 ,m_buf(new char[SCTP_BUFSIZE_READ])
00041 {
00042 if (type != SOCK_STREAM && type != SOCK_SEQPACKET)
00043 {
00044 }
00045 }
00046
00047
00048 SctpSocket::~SctpSocket()
00049 {
00050 delete[] m_buf;
00051 }
00052
00053
00054 int SctpSocket::Bind(const std::string& a,port_t p)
00055 {
00056 #ifdef IPPROTO_IPV6
00057 if (IsIpv6())
00058 {
00059 Ipv6Address ad(a, p);
00060 return Bind(ad);
00061 }
00062 #endif
00063 Ipv4Address ad(a, p);
00064 return Bind(ad);
00065 }
00066
00067
00068 int SctpSocket::Bind(SocketAddress& ad)
00069 {
00070 if (!ad.IsValid())
00071 {
00072 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00073 return -1;
00074 }
00075 if (GetSocket() == INVALID_SOCKET)
00076 {
00077 Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
00078 }
00079 if (GetSocket() != INVALID_SOCKET)
00080 {
00081 int n = bind(GetSocket(), ad, ad);
00082 if (n == -1)
00083 {
00084 Handler().LogError(this, "SctpSocket", -1, "bind() failed", LOG_LEVEL_ERROR);
00085 }
00086 return n;
00087 }
00088 return -1;
00089 }
00090
00091
00092 int SctpSocket::AddAddress(const std::string& a,port_t p)
00093 {
00094 #ifdef IPPROTO_IPV6
00095 if (IsIpv6())
00096 {
00097 Ipv6Address ad(a, p);
00098 return AddAddress(ad);
00099 }
00100 #endif
00101 Ipv4Address ad(a, p);
00102 return AddAddress(ad);
00103 }
00104
00105
00106 int SctpSocket::AddAddress(SocketAddress& ad)
00107 {
00108 if (!ad.IsValid())
00109 {
00110 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00111 return -1;
00112 }
00113 if (GetSocket() == INVALID_SOCKET)
00114 {
00115 Handler().LogError(this, "SctpSocket", -1, "AddAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
00116 return -1;
00117 }
00118 int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_ADD_ADDR);
00119 if (n == -1)
00120 {
00121 Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
00122 }
00123 return n;
00124 }
00125
00126
00127 int SctpSocket::RemoveAddress(const std::string& a,port_t p)
00128 {
00129 #ifdef IPPROTO_IPV6
00130 if (IsIpv6())
00131 {
00132 Ipv6Address ad(a, p);
00133 return RemoveAddress(ad);
00134 }
00135 #endif
00136 Ipv4Address ad(a, p);
00137 return RemoveAddress(ad);
00138 }
00139
00140
00141 int SctpSocket::RemoveAddress(SocketAddress& ad)
00142 {
00143 if (!ad.IsValid())
00144 {
00145 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00146 return -1;
00147 }
00148 if (GetSocket() == INVALID_SOCKET)
00149 {
00150 Handler().LogError(this, "SctpSocket", -1, "RemoveAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
00151 return -1;
00152 }
00153 int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_REM_ADDR);
00154 if (n == -1)
00155 {
00156 Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
00157 }
00158 return n;
00159 }
00160
00161
00162 int SctpSocket::Open(const std::string& a,port_t p)
00163 {
00164 #ifdef IPPROTO_IPV6
00165 if (IsIpv6())
00166 {
00167 Ipv6Address ad(a, p);
00168 return Open(ad);
00169 }
00170 #endif
00171 Ipv4Address ad(a, p);
00172 return Open(ad);
00173 }
00174
00175
00176 int SctpSocket::Open(SocketAddress& ad)
00177 {
00178 if (!ad.IsValid())
00179 {
00180 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00181 return -1;
00182 }
00183 if (GetSocket() == INVALID_SOCKET)
00184 {
00185 Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
00186 }
00187 if (GetSocket() != INVALID_SOCKET)
00188 {
00189 if (!SetNonblocking(true))
00190 {
00191 return -1;
00192 }
00193 int n = connect(GetSocket(), ad, ad);
00194 if (n == -1)
00195 {
00196
00197 #ifdef _WIN32
00198 if (Errno == WSAEWOULDBLOCK)
00199 #else
00200 if (Errno == EINPROGRESS)
00201 #endif
00202 {
00203 Handler().LogError(this, "connect: connection pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
00204 SetConnecting( true );
00205 }
00206 else
00207 {
00208 Handler().LogError(this, "SctpSocket", -1, "connect() failed", LOG_LEVEL_ERROR);
00209 }
00210 }
00211 return n;
00212 }
00213 return -1;
00214 }
00215
00216
00217 int SctpSocket::AddConnection(const std::string& a,port_t p)
00218 {
00219 #ifdef IPPROTO_IPV6
00220 if (IsIpv6())
00221 {
00222 Ipv6Address ad(a, p);
00223 return AddConnection(ad);
00224 }
00225 #endif
00226 Ipv4Address ad(a, p);
00227 return AddConnection(ad);
00228 }
00229
00230
00231 int SctpSocket::AddConnection(SocketAddress& ad)
00232 {
00233 if (!ad.IsValid())
00234 {
00235 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00236 return -1;
00237 }
00238 if (GetSocket() == INVALID_SOCKET)
00239 {
00240 Handler().LogError(this, "SctpSocket", -1, "AddConnection called with invalid file descriptor", LOG_LEVEL_ERROR);
00241 return -1;
00242 }
00243 int n = sctp_connectx(GetSocket(), ad, ad);
00244 if (n == -1)
00245 {
00246 Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR);
00247 }
00248 else
00249 {
00250 SetConnecting();
00251 }
00252 return n;
00253 }
00254
00255
00256 int SctpSocket::getpaddrs(sctp_assoc_t id,std::list<std::string>& vec)
00257 {
00258 struct sockaddr *p = NULL;
00259 int n = sctp_getpaddrs(GetSocket(), id, &p);
00260 if (!n || n == -1)
00261 {
00262 Handler().LogError(this, "SctpSocket", -1, "sctp_getpaddrs failed", LOG_LEVEL_WARNING);
00263 return n;
00264 }
00265 for (int i = 0; i < n; i++)
00266 {
00267 vec.push_back(Utility::Sa2String(&p[i]));
00268 }
00269 sctp_freepaddrs(p);
00270 return n;
00271 }
00272
00273
00274 int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
00275 {
00276 struct sockaddr *p = NULL;
00277 int n = sctp_getladdrs(GetSocket(), id, &p);
00278 if (!n || n == -1)
00279 {
00280 Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
00281 return n;
00282 }
00283 for (int i = 0; i < n; i++)
00284 {
00285 vec.push_back(Utility::Sa2String(&p[i]));
00286 }
00287 sctp_freeladdrs(p);
00288 return n;
00289 }
00290
00291
00292 int SctpSocket::PeelOff(sctp_assoc_t id)
00293 {
00294 int n = sctp_peeloff(GetSocket(), id);
00295 if (n == -1)
00296 {
00297 Handler().LogError(this, "SctpSocket", -1, "PeelOff failed", LOG_LEVEL_WARNING);
00298 return -1;
00299 }
00300 Socket *p = Create();
00301 p -> Attach(n);
00302 p -> SetDeleteByHandler();
00303 Handler().Add(p);
00304 return n;
00305 }
00306
00307
00308 void SctpSocket::OnRead()
00309 {
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 struct sockaddr sa;
00328 socklen_t sa_len = 0;
00329 struct sctp_sndrcvinfo sinfo;
00330 int flags = 0;
00331 int n = sctp_recvmsg(GetSocket(), m_buf, SCTP_BUFSIZE_READ, &sa, &sa_len, &sinfo, &flags);
00332 if (n == -1)
00333 {
00334 Handler().LogError(this, "SctpSocket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00335 SetCloseAndDelete();
00336 }
00337 else
00338 {
00339 OnReceiveMessage(m_buf, n, &sa, sa_len, &sinfo, flags);
00340 }
00341 }
00342
00343
00344 void SctpSocket::OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags)
00345 {
00346 }
00347
00348
00349 void SctpSocket::OnWrite()
00350 {
00351 if (Connecting())
00352 {
00353 if (CheckConnect())
00354 {
00355 SetCallOnConnect();
00356 return;
00357 }
00358
00359 if (Socks4())
00360 {
00361 OnSocks4ConnectFailed();
00362 return;
00363 }
00364 if (GetConnectionRetry() == -1 ||
00365 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00366 {
00367
00368
00369
00370
00371 return;
00372 }
00373 SetConnecting(false);
00374 SetCloseAndDelete( true );
00376 OnConnectFailed();
00377 return;
00378 }
00379 }
00380
00381
00382 #ifdef SOCKETS_NAMESPACE
00383 }
00384 #endif
00385
00386
00387 #endif // USE_SCTP