Logo
~Sockets~
~Examples~
~Contact~


SctpSocket.cpp

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007  Anders Hedstrom
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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                         // check error code that means a connect is in progress
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 ); // this flag will control fd_set's
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         int sctp_recvmsg(int sd, void * msg, size_t * len,
00312                 struct sockaddr * from, socklen_t * fromlen,
00313                 struct sctp_sndrcvinfo * sinfo, int * msg_flags);
00314 
00315         DESCRIPTION
00316         sctp_recvmsg  is  a  wrapper library function that can be used to receive a message from a socket while using the advanced
00317         features of SCTP.  sd is the socket descriptor on which the message pointed to by msg of length len is received.
00318 
00319         If from is not NULL, the source address of the message is filled in. The argument fromlen  is  a  value-result  parameter.
00320         initialized  to  the  size  of the buffer associated with from , and modified on return to indicate the actual size of the
00321         address stored.
00322 
00323         sinfo is a pointer to a sctp_sndrcvinfo structure to be filled upon receipt of the message.  msg_flags is a pointer  to  a
00324         integer that is filled with any message flags like MSG_NOTIFICATION or MSG_EOR.
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                 // failed
00359                 if (Socks4())
00360                 {
00361                         OnSocks4ConnectFailed();
00362                         return;
00363                 }
00364                 if (GetConnectionRetry() == -1 ||
00365                         (GetConnectionRetry() && GetConnectionRetries() < GetConnectionRetry()) )
00366                 {
00367                         // even though the connection failed at once, only retry after
00368                         // the connection timeout.
00369                         // should we even try to connect again, when CheckConnect returns
00370                         // false it's because of a connection error - not a timeout...
00371                         return;
00372                 }
00373                 SetConnecting(false);
00374                 SetCloseAndDelete( true );
00376                 OnConnectFailed();
00377                 return;
00378         }
00379 }
00380 
00381 
00382 #ifdef SOCKETS_NAMESPACE
00383 } // namespace SOCKETS_NAMESPACE
00384 #endif
00385 
00386 
00387 #endif // USE_SCTP
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4