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 int n = sctp_connectx(GetSocket(), ad, ad);
00270 if (n == -1)
00271 {
00272 Handler().LogError(this, "SctpSocket", -1, "sctp_connectx() failed", LOG_LEVEL_ERROR);
00273 }
00274 else
00275 {
00276 SetConnecting();
00277 }
00278 return n;
00279 }
00280 #endif
00281
00282
00283 int SctpSocket::getpaddrs(sctp_assoc_t id,std::list<std::string>& vec)
00284 {
00285 struct sockaddr *p = NULL;
00286 int n = sctp_getpaddrs(GetSocket(), id, &p);
00287 if (!n || n == -1)
00288 {
00289 Handler().LogError(this, "SctpSocket", -1, "sctp_getpaddrs failed", LOG_LEVEL_WARNING);
00290 return n;
00291 }
00292 for (int i = 0; i < n; i++)
00293 {
00294 vec.push_back(Utility::Sa2String(&p[i]));
00295 }
00296 sctp_freepaddrs(p);
00297 return n;
00298 }
00299
00300
00301 int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
00302 {
00303 struct sockaddr *p = NULL;
00304 int n = sctp_getladdrs(GetSocket(), id, &p);
00305 if (!n || n == -1)
00306 {
00307 Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
00308 return n;
00309 }
00310 for (int i = 0; i < n; i++)
00311 {
00312 vec.push_back(Utility::Sa2String(&p[i]));
00313 }
00314 sctp_freeladdrs(p);
00315 return n;
00316 }
00317
00318
00319 int SctpSocket::PeelOff(sctp_assoc_t id)
00320 {
00321 int n = sctp_peeloff(GetSocket(), id);
00322 if (n == -1)
00323 {
00324 Handler().LogError(this, "SctpSocket", -1, "PeelOff failed", LOG_LEVEL_WARNING);
00325 return -1;
00326 }
00327 Socket *p = Create();
00328 p -> Attach(n);
00329 p -> SetDeleteByHandler();
00330 Handler().Add(p);
00331 return n;
00332 }
00333
00334
00335 void SctpSocket::OnRead()
00336 {
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 struct sockaddr sa;
00355 socklen_t sa_len = 0;
00356 struct sctp_sndrcvinfo sinfo;
00357 int flags = 0;
00358 int n = sctp_recvmsg(GetSocket(), m_buf, SCTP_BUFSIZE_READ, &sa, &sa_len, &sinfo, &flags);
00359 if (n == -1)
00360 {
00361 Handler().LogError(this, "SctpSocket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
00362 SetCloseAndDelete();
00363 }
00364 else
00365 {
00366 OnReceiveMessage(m_buf, n, &sa, sa_len, &sinfo, flags);
00367 }
00368 }
00369
00370
00371 void SctpSocket::OnReceiveMessage(const char *buf,size_t sz,struct sockaddr *sa,socklen_t sa_len,struct sctp_sndrcvinfo *sinfo,int msg_flags)
00372 {
00373 }
00374
00375
00376 void SctpSocket::OnWrite()
00377 {
00378 if (Connecting())
00379 {
00380 int err = SoError();
00381
00382
00384 if (!err)
00385 {
00386 Set(!IsDisableRead(), false);
00387 SetConnecting(false);
00388 SetCallOnConnect();
00389 return;
00390 }
00391 Handler().LogError(this, "sctp: connect failed", err, StrError(err), LOG_LEVEL_FATAL);
00392 Set(false, false);
00393
00394
00395 #ifdef ENABLE_SOCKS4
00396 if (Socks4())
00397 {
00398 OnSocks4ConnectFailed();
00399 return;
00400 }
00401 #endif
00402 if (GetConnectionRetry() == -1 ||
00403 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00404 {
00405
00406
00407
00408
00409 return;
00410 }
00411 SetConnecting(false);
00412 SetCloseAndDelete( true );
00414 OnConnectFailed();
00415 return;
00416 }
00417 }
00418
00419
00420 void SctpSocket::OnConnectTimeout()
00421 {
00422 Handler().LogError(this, "connect", -1, "connect timeout", LOG_LEVEL_FATAL);
00423 #ifdef ENABLE_SOCKS4
00424 if (Socks4())
00425 {
00426 OnSocks4ConnectFailed();
00427
00428 }
00429 else
00430 #endif
00431 if (GetConnectionRetry() == -1 ||
00432 (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00433 {
00434 IncreaseConnectionRetries();
00435
00436 if (OnConnectRetry())
00437 {
00438 SetRetryClientConnect();
00439 }
00440 else
00441 {
00442 SetCloseAndDelete( true );
00444 OnConnectFailed();
00445 }
00446 }
00447 else
00448 {
00449 SetCloseAndDelete(true);
00451 OnConnectFailed();
00452 }
00453
00454 SetConnecting(false);
00455 }
00456
00457
00458 #ifdef _WIN32
00459 void SctpSocket::OnException()
00460 {
00461 if (Connecting())
00462 {
00463 #ifdef ENABLE_SOCKS4
00464 if (Socks4())
00465 OnSocks4ConnectFailed();
00466 else
00467 #endif
00468 if (GetConnectionRetry() == -1 ||
00469 (GetConnectionRetry() &&
00470 GetConnectionRetries() < GetConnectionRetry() ))
00471 {
00472
00473
00474
00475
00476 }
00477 else
00478 {
00479 SetConnecting(false);
00480 SetCloseAndDelete();
00481 OnConnectFailed();
00482 }
00483 return;
00484 }
00485
00486
00487 int err = SoError();
00488 Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
00489 SetCloseAndDelete();
00490 }
00491 #endif // _WIN32
00492
00493
00494 int SctpSocket::Protocol()
00495 {
00496 return IPPROTO_SCTP;
00497 }
00498
00499
00500 #ifdef SOCKETS_NAMESPACE
00501 }
00502 #endif
00503
00504
00505 #endif // USE_SCTP
00506