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) : StreamSocket(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 ENABLE_IPV6
00057 #ifdef IPPROTO_IPV6
00058 if (IsIpv6())
00059 {
00060 Ipv6Address ad(a, p);
00061 return Bind(ad);
00062 }
00063 #endif
00064 #endif
00065 Ipv4Address ad(a, p);
00066 return Bind(ad);
00067 }
00068
00069
00070 int SctpSocket::Bind(SocketAddress& ad)
00071 {
00072 if (!ad.IsValid())
00073 {
00074 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00075 return -1;
00076 }
00077 if (GetSocket() == INVALID_SOCKET)
00078 {
00079 Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
00080 }
00081 if (GetSocket() != INVALID_SOCKET)
00082 {
00083 int n = bind(GetSocket(), ad, ad);
00084 if (n == -1)
00085 {
00086 Handler().LogError(this, "SctpSocket", -1, "bind() failed", LOG_LEVEL_ERROR);
00087 }
00088 return n;
00089 }
00090 return -1;
00091 }
00092
00093
00094 int SctpSocket::AddAddress(const std::string& a,port_t p)
00095 {
00096 #ifdef ENABLE_IPV6
00097 #ifdef IPPROTO_IPV6
00098 if (IsIpv6())
00099 {
00100 Ipv6Address ad(a, p);
00101 return AddAddress(ad);
00102 }
00103 #endif
00104 #endif
00105 Ipv4Address ad(a, p);
00106 return AddAddress(ad);
00107 }
00108
00109
00110 int SctpSocket::AddAddress(SocketAddress& ad)
00111 {
00112 if (!ad.IsValid())
00113 {
00114 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00115 return -1;
00116 }
00117 if (GetSocket() == INVALID_SOCKET)
00118 {
00119 Handler().LogError(this, "SctpSocket", -1, "AddAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
00120 return -1;
00121 }
00122 int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_ADD_ADDR);
00123 if (n == -1)
00124 {
00125 Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
00126 }
00127 return n;
00128 }
00129
00130
00131 int SctpSocket::RemoveAddress(const std::string& a,port_t p)
00132 {
00133 #ifdef ENABLE_IPV6
00134 #ifdef IPPROTO_IPV6
00135 if (IsIpv6())
00136 {
00137 Ipv6Address ad(a, p);
00138 return RemoveAddress(ad);
00139 }
00140 #endif
00141 #endif
00142 Ipv4Address ad(a, p);
00143 return RemoveAddress(ad);
00144 }
00145
00146
00147 int SctpSocket::RemoveAddress(SocketAddress& ad)
00148 {
00149 if (!ad.IsValid())
00150 {
00151 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00152 return -1;
00153 }
00154 if (GetSocket() == INVALID_SOCKET)
00155 {
00156 Handler().LogError(this, "SctpSocket", -1, "RemoveAddress called with invalid file descriptor", LOG_LEVEL_ERROR);
00157 return -1;
00158 }
00159 int n = sctp_bindx(GetSocket(), ad, ad, SCTP_BINDX_REM_ADDR);
00160 if (n == -1)
00161 {
00162 Handler().LogError(this, "SctpSocket", -1, "sctp_bindx() failed", LOG_LEVEL_ERROR);
00163 }
00164 return n;
00165 }
00166
00167
00168 int SctpSocket::Open(const std::string& a,port_t p)
00169 {
00170 #ifdef ENABLE_IPV6
00171 #ifdef IPPROTO_IPV6
00172 if (IsIpv6())
00173 {
00174 Ipv6Address ad(a, p);
00175 return Open(ad);
00176 }
00177 #endif
00178 #endif
00179 Ipv4Address ad(a, p);
00180 return Open(ad);
00181 }
00182
00183
00184 int SctpSocket::Open(SocketAddress& ad)
00185 {
00186 if (!ad.IsValid())
00187 {
00188 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00189 return -1;
00190 }
00191 if (GetSocket() == INVALID_SOCKET)
00192 {
00193 Attach(CreateSocket(ad.GetFamily(), m_type, "sctp"));
00194 }
00195 if (GetSocket() != INVALID_SOCKET)
00196 {
00197 if (!SetNonblocking(true))
00198 {
00199 return -1;
00200 }
00201 int n = connect(GetSocket(), ad, ad);
00202 if (n == -1)
00203 {
00204
00205 #ifdef _WIN32
00206 if (Errno == WSAEWOULDBLOCK)
00207 #else
00208 if (Errno == EINPROGRESS)
00209 #endif
00210 {
00211 Handler().LogError(this, "connect: connection pending", Errno, StrError(Errno), LOG_LEVEL_INFO);
00212 SetConnecting( true );
00213 }
00214 else
00215 {
00216 Handler().LogError(this, "SctpSocket", -1, "connect() failed", LOG_LEVEL_ERROR);
00217 }
00218 }
00219 return n;
00220 }
00221 return -1;
00222 }
00223
00224
00225 #ifndef SOLARIS
00226 int SctpSocket::AddConnection(const std::string& a,port_t p)
00227 {
00228 #ifdef ENABLE_IPV6
00229 #ifdef IPPROTO_IPV6
00230 if (IsIpv6())
00231 {
00232 Ipv6Address ad(a, p);
00233 return AddConnection(ad);
00234 }
00235 #endif
00236 #endif
00237 Ipv4Address ad(a, p);
00238 return AddConnection(ad);
00239 }
00240
00241
00242 int SctpSocket::AddConnection(SocketAddress& ad)
00243 {
00244 if (!ad.IsValid())
00245 {
00246 Handler().LogError(this, "SctpSocket", -1, "invalid address", LOG_LEVEL_ERROR);
00247 return -1;
00248 }
00249 if (GetSocket() == INVALID_SOCKET)
00250 {
00251 Handler().LogError(this, "SctpSocket", -1, "AddConnection called with invalid file descriptor", LOG_LEVEL_ERROR);
00252 return -1;
00253 }
00254 int n = sctp_connectx(GetSocket(), ad, ad);
00255 if (n == -1)
00256 {
00257 Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR);
00258 }
00259 else
00260 {
00261 SetConnecting();
00262 }
00263 return n;
00264 }
00265 #endif
00266
00267
00268 int SctpSocket::getpaddrs(sctp_assoc_t id,std::list<std::string>& vec)
00269 {
00270 struct sockaddr *p = NULL;
00271 int n = sctp_getpaddrs(GetSocket(), id, &p);
00272 if (!n || n == -1)
00273 {
00274 Handler().LogError(this, "SctpSocket", -1, "sctp_getpaddrs failed", LOG_LEVEL_WARNING);
00275 return n;
00276 }
00277 for (int i = 0; i < n; i++)
00278 {
00279 vec.push_back(Utility::Sa2String(&p[i]));
00280 }
00281 sctp_freepaddrs(p);
00282 return n;
00283 }
00284
00285
00286 int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
00287 {
00288 struct sockaddr *p = NULL;
00289 int n = sctp_getladdrs(GetSocket(), id, &p);
00290 if (!n || n == -1)
00291 {
00292 Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
00293 return n;
00294 }
00295 for (int i = 0; i < n; i++)
00296 {
00297 vec.push_back(Utility::Sa2String(&p[i]));
00298 }
00299 sctp_freeladdrs(p);
00300 return n;
00301 }
00302
00303
00304 int SctpSocket::PeelOff(sctp_assoc_t id)
00305 {
00306 int n = sctp_peeloff(GetSocket(), id);
00307 if (n == -1)
00308 {
00309 Handler().LogError(this, "SctpSocket", -1, "PeelOff failed", LOG_LEVEL_WARNING);
00310 return -1;
00311 }
00312 Socket *p = Create();
00313 p -> Attach(n);
00314 p -> SetDeleteByHandler();
00315 Handler().Add(p);
00316 return n;
00317 }
00318
00319
00320 void SctpSocket::OnRead()
00321 {
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 struct sockaddr sa;
00340 socklen_t sa_len = 0;
00341 struct sctp_sndrcvinfo sinfo;
00342 int flags = 0;
00343 int n = sctp_recvmsg(GetSocket(), m_buf, SCTP_BUFSIZE_READ, &sa, &sa_len, &sinfo, &flags);
00344 if (n == -1)
00345 {
00346 Handler().LogError(this, "SctpSocket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00347 SetCloseAndDelete();
00348 }
00349 else
00350 {
00351 OnReceiveMessage(m_buf, n, &sa, sa_len, &sinfo, flags);
00352 }
00353 }
00354
00355
00356 void SctpSocket::OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags)
00357 {
00358 }
00359
00360
00361 void SctpSocket::OnWrite()
00362 {
00363 if (Connecting())
00364 {
00365 int err = SoError();
00366
00367
00369 if (!err)
00370 {
00371 Set(!IsDisableRead(), false);
00372 SetConnecting(false);
00373 SetCallOnConnect();
00374 return;
00375 }
00376 Handler().LogError(this, "sctp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
00377 Set(false, false);
00378
00379
00380 #ifdef ENABLE_SOCKS4
00381 if (Socks4())
00382 {
00383 OnSocks4ConnectFailed();
00384 return;
00385 }
00386 #endif
00387 if (GetConnectionRetry() == -1 ||
00388 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00389 {
00390
00391
00392
00393
00394 return;
00395 }
00396 SetConnecting(false);
00397 SetCloseAndDelete( true );
00399 OnConnectFailed();
00400 return;
00401 }
00402 }
00403
00404
00405 void SctpSocket::OnConnectTimeout()
00406 {
00407 Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
00408 #ifdef ENABLE_SOCKS4
00409 if (Socks4())
00410 {
00411 OnSocks4ConnectFailed();
00412
00413 }
00414 else
00415 #endif
00416 if (GetConnectionRetry() == -1 ||
00417 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00418 {
00419 IncreaseConnectionRetries();
00420
00421 if (OnConnectRetry())
00422 {
00423 SetRetryClientConnect();
00424 }
00425 else
00426 {
00427 SetCloseAndDelete( true );
00429 OnConnectFailed();
00430 }
00431 }
00432 else
00433 {
00434 SetCloseAndDelete(true);
00436 OnConnectFailed();
00437 }
00438
00439 SetConnecting(false);
00440 }
00441
00442
00443 #ifdef _WIN32
00444 void SctpSocket::OnException()
00445 {
00446 if (Connecting())
00447 {
00448 #ifdef ENABLE_SOCKS4
00449 if (Socks4())
00450 OnSocks4ConnectFailed();
00451 else
00452 #endif
00453 if (GetConnectionRetry() == -1 ||
00454 (GetConnectionRetry() &&
00455 GetConnectionRetries() < GetConnectionRetry() ))
00456 {
00457
00458
00459
00460
00461 }
00462 else
00463 {
00464 SetConnecting(false);
00465 SetCloseAndDelete();
00466 OnConnectFailed();
00467 }
00468 return;
00469 }
00470
00471
00472 int err = SoError();
00473 Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
00474 SetCloseAndDelete();
00475 }
00476 #endif // _WIN32
00477
00478
00479 int SctpSocket::Protocol()
00480 {
00481 return IPPROTO_SCTP;
00482 }
00483
00484
00485 #ifdef SOCKETS_NAMESPACE
00486 }
00487 #endif
00488
00489
00490 #endif // USE_SCTP