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