SOCK_SEQPACK_Association.cpp

Go to the documentation of this file.
00001 // SOCK_SEQPACK_Association.cpp,v 4.15 2006/04/19 19:13:09 jwillemsen Exp
00002 
00003 #include "ace/SOCK_SEQPACK_Association.h"
00004 
00005 #include "ace/Auto_Ptr.h"
00006 #include "ace/Log_Msg.h"
00007 #include "ace/OS_Memory.h"
00008 #include "ace/OS_NS_string.h"
00009 
00010 #if !defined (__ACE_INLINE__)
00011 #include "ace/SOCK_SEQPACK_Association.inl"
00012 #endif /* __ACE_INLINE__ */
00013 
00014 ACE_RCSID(ace, SOCK_SEQPACK_Association, "SOCK_SEQPACK_Association.cpp,v 4.15 2006/04/19 19:13:09 jwillemsen Exp")
00015 
00016 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00017 
00018 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_SEQPACK_Association)
00019 
00020 void
00021 ACE_SOCK_SEQPACK_Association::dump (void) const
00022 {
00023 #if defined (ACE_HAS_DUMP)
00024   ACE_TRACE ("ACE_SOCK_SEQPACK_Association::dump");
00025 #endif /* ACE_HAS_DUMP */
00026 }
00027 
00028 int
00029 ACE_SOCK_SEQPACK_Association::close (void)
00030 {
00031 #if defined (ACE_WIN32)
00032   // We need the following call to make things work correctly on
00033   // Win32, which requires use to do a <close_writer> before doing the
00034   // close in order to avoid losing data.  Note that we don't need to
00035   // do this on UNIX since it doesn't have this "feature".  Moreover,
00036   // this will cause subtle problems on UNIX due to the way that
00037   // fork() works.
00038   this->close_writer ();
00039 #endif /* ACE_WIN32 */
00040   // Close down the socket.
00041   return ACE_SOCK::close ();
00042 }
00043 
00044 // Developed according to the API discussed in 7.1.4 of
00045 // draft-ietf-tsvwg-sctpsocket-09.txt to abruptly free a transport
00046 // transport association's resources.
00047 int
00048 ACE_SOCK_SEQPACK_Association::abort (void)
00049 {
00050   //
00051   // setsockopt() SO_LINGER configures socket to reap immediately.
00052   // Normal close then aborts the association.
00053   //
00054   linger slinger;
00055 
00056   slinger.l_onoff = 1;
00057   slinger.l_linger = 0;
00058 
00059   if (-1 == ACE_OS::setsockopt (this->get_handle (),
00060                                 SOL_SOCKET,
00061                                 SO_LINGER,
00062                                 reinterpret_cast<const char *> (&slinger),
00063                                 sizeof (linger)))
00064   {
00065     return -1;
00066   }
00067 
00068   return this->close ();
00069 }
00070 
00071 int
00072 ACE_SOCK_SEQPACK_Association::get_local_addrs (ACE_INET_Addr *addrs, size_t &size) const
00073 {
00074   ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_local_addrs");
00075 
00076 #if defined (ACE_HAS_LKSCTP)
00077   /*
00078     The size of ACE_INET_Addr must be large enough to hold the number of
00079     local addresses on the machine.  If the array is too small, the function
00080     will only return the number of addresses that will fit.  If the array is
00081     too large, the 'size' parameter will be modified to indicate the number
00082     of addrs.
00083 
00084     We will call sctp_getladdrs() which accepts 3 parameters
00085     1. a socket fd
00086     2. a sctp association_id which will be ignored since we are using
00087        tcp sockets
00088     3. a pointer to sockaddr
00089 
00090     lksctp/draft will allocate memory and we are responsible for freeing
00091     it by calling sctp_freeladdrs().
00092   */
00093 
00094   sockaddr_in *si = 0;
00095   sockaddr *laddrs = 0;
00096   int err = 0;
00097   size_t len = 0;
00098 
00099   err = sctp_getladdrs(this->get_handle(), 0, &laddrs);
00100   if (err > 0)
00101   {
00102     len = err;
00103     // check to see if we have more addresses than we have
00104     // space in our ACE_INET_Addr array
00105     if (len > size)
00106     {
00107       // since our array is too small, we will only copy the first
00108       // few that fit
00109       len = size;
00110     }
00111 
00112     for (size_t i = 0; i < len; i++)
00113     {
00114       // first we cast the sockaddr to sockaddr_in
00115       // since we only support ipv4 at this time.
00116       si = (sockaddr_in *) (&(laddrs[i]));
00117 
00118       // now we fillup the ace_inet_addr array
00119       addrs[i].set_addr(si, sizeof(sockaddr_in));
00120       addrs[i].set_type(si->sin_family);
00121       addrs[i].set_size(sizeof(sockaddr_in));
00122     }
00123   }
00124   else /* err < 0 */
00125   {
00126     // sctp_getladdrs will return -1 on error
00127     return -1;
00128   }
00129 
00130   // indicate the num of addrs returned to the calling function
00131   size = len;
00132 
00133   // make sure we free the struct using the system function
00134   sctp_freeladdrs(laddrs);
00135 
00136 #else
00137 
00138   /*
00139     We will be calling ACE_OS::getsockname, which accepts (and
00140     potentially modifies) two reference parameters:
00141 
00142     1.  a sockaddr_in* that points to a buffer
00143     2.  an int* that points to the size of this buffer
00144 
00145     The OpenSS7 implementation of SCTP copies an array of ipv4
00146     sockaddr_in into the buffer.  Then, if the size of the buffer is
00147     greater than the size used, the size parameter is reduced
00148     accordingly.
00149 
00150   */
00151 
00152   // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
00153   // which causes dynamically-allocated memory to be released as soon
00154   // as the ACE_Auto_Array_Ptr goes out of scope.
00155   ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;
00156 
00157   // Allocate memory for this array.  Return -1 if the memory cannot
00158   // be allocated.  (This activity requires a temporary variable---a
00159   // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
00160   // an ACE_Auto_Array_Ptr.)
00161   {
00162     sockaddr_in *addr_structs_bootstrap = 0;
00163     ACE_NEW_RETURN (addr_structs_bootstrap, sockaddr_in[size], -1);
00164     addr_structs.reset(addr_structs_bootstrap);
00165   }
00166 
00167   // Physical size of this array is its logical size multiplied by
00168   // the physical size of one of its elements.
00169   size_t physical_size = size * sizeof(sockaddr_in);
00170 
00171   /* Clear the array */
00172   ACE_OS::memset(addr_structs.get(),
00173                  0,
00174                  physical_size);
00175 
00176   /*
00177   ** Populate the array with real values from the getsockname system
00178   ** call.  addr_structs is modified, and name_size is modified to contain
00179   ** the number of bytes written to addr_structs.
00180   ** Use name_size to get the data types right across the call.
00181   */
00182   int name_size = static_cast<int> (physical_size);
00183   if (ACE_OS::getsockname (this->get_handle (),
00184                            reinterpret_cast<sockaddr *> (addr_structs.get()),
00185                            &name_size) == -1)
00186     return -1;
00187 
00188   /* Calculate the NEW physical size of the array */
00189   name_size /= sizeof (sockaddr_in);
00190   size = static_cast<size_t> (name_size);
00191 
00192   /* Copy each sockaddr_in to the address structure of an ACE_Addr from
00193      the passed-in array */
00194   const int addrlen (static_cast<int> (sizeof (sockaddr_in)));
00195   for (int i = 0; i < name_size; ++i)
00196     {
00197       addrs[i].set_addr (&(addr_structs[i]), addrlen);
00198       addrs[i].set_type (addr_structs[i].sin_family);
00199       addrs[i].set_size (addrlen);
00200     }
00201 #endif /* ACE_HAS_LKSCTP */
00202   return 0;
00203 }
00204 
00205 
00206 int
00207 ACE_SOCK_SEQPACK_Association::get_remote_addrs (ACE_INET_Addr *addrs, size_t &size) const
00208 {
00209   ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_remote_addrs");
00210 #if defined (ACE_HAS_LKSCTP)
00211   /*
00212     The size of ACE_INET_Addr must be large enough to hold the number of
00213     remotes addresses in the association.  If the array is too small, the
00214     function will only return the number of addresses that will fit.  If the
00215     array is too large, the 'size' parameter will be modified to indicate
00216     the number of addrs.
00217 
00218     We will call sctp_getpaddrs() which accepts 3 parameters
00219     1. a socket fd
00220     2. a sctp association_id which will be ignored since we are using
00221        tcp sockets
00222     3. a pointer to a sockaddr
00223 
00224     lksctp/draft will allocate memory and we are responsible for freeing
00225     it by calling sctp_freepaddrs().
00226   */
00227 
00228   sockaddr_in *si = 0;
00229   sockaddr *paddrs = 0;
00230   int err = 0;
00231   size_t len = 0;
00232 
00233   err = sctp_getpaddrs(this->get_handle(), 0, &paddrs);
00234   if (err > 0)
00235   {
00236     len = err;
00237     // check to see if we have more addresses than we have
00238     // space in our ACE_INET_Addr array
00239     if (len > size)
00240     {
00241       // since our array is too small, we will only copy the first
00242       // few that fit
00243       len = size;
00244     }
00245 
00246     for (size_t i = 0; i < len; i++)
00247     {
00248       // first we cast the sockaddr to sockaddr_in
00249       // since we only support ipv4 at this time.
00250       si = (sockaddr_in *) (&(paddrs[i]));
00251 
00252       // now we fillup the ace_inet_addr array
00253       addrs[i].set_addr(si, sizeof(sockaddr_in));
00254       addrs[i].set_type(si->sin_family);
00255       addrs[i].set_size(sizeof(sockaddr_in));
00256     }
00257   }
00258   else /* err < 0 */
00259   {
00260     // sctp_getpaddrs will return -1 on error
00261     return -1;
00262   }
00263 
00264   // indicate the num of addrs returned to the calling function
00265   size = len;
00266 
00267   // make sure we free the struct using the system function
00268   sctp_freepaddrs(paddrs);
00269 
00270 #else
00271 
00272   /*
00273     We will be calling ACE_OS::getpeername, which accepts (and
00274     potentially modifies) two reference parameters:
00275 
00276     1.  a sockaddr_in* that points to a buffer
00277     2.  an int* that points to the size of this buffer
00278 
00279     The OpenSS7 implementation of SCTP copies an array of ipv4
00280     sockaddr_in into the buffer.  Then, if the size of the buffer is
00281     greater than the size used, the size parameter is reduced
00282     accordingly.
00283 
00284   */
00285 
00286   // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
00287   // which causes dynamically-allocated memory to be released as soon
00288   // as the ACE_Auto_Array_Ptr goes out of scope.
00289   ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;
00290 
00291   // Allocate memory for this array.  Return -1 if the memory cannot
00292   // be allocated.  (This activity requires a temporary variable---a
00293   // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
00294   // an ACE_Auto_Array_Ptr.)
00295   {
00296     sockaddr_in *addr_structs_bootstrap = 0;
00297     ACE_NEW_RETURN (addr_structs_bootstrap, sockaddr_in[size], -1);
00298     addr_structs.reset(addr_structs_bootstrap);
00299   }
00300 
00301   // Physical size of this array is its logical size multiplied by
00302   // the physical size of one of its elements.
00303   size_t physical_size = size * sizeof(sockaddr_in);
00304 
00305   /* Clear the array */
00306   ACE_OS::memset(addr_structs.get(),
00307                  0,
00308                  physical_size);
00309 
00310   /*
00311   ** Populate the array with real values from the getpeername system
00312   ** call.  addr_structs is modified, and name_size is modified to contain
00313   ** the number of bytes written to addr_structs.
00314   ** Use name_size to get the data types right across the call.
00315   */
00316   int name_size = static_cast<int> (physical_size);
00317   if (ACE_OS::getpeername (this->get_handle (),
00318                            reinterpret_cast<sockaddr *> (addr_structs.get()),
00319                            &name_size) == -1)
00320     return -1;
00321 
00322   /* Calculate the NEW physical size of the array */
00323   name_size /= sizeof (sockaddr_in);
00324   size = static_cast<size_t> (name_size);
00325 
00326   /* Copy each sockaddr_in to the address structure of an ACE_Addr from
00327      the passed-in array */
00328   const int addrlen (static_cast<int> (sizeof (sockaddr_in)));
00329   for (int i = 0; i < name_size; ++i)
00330     {
00331       addrs[i].set_addr (&(addr_structs[i]), addrlen);
00332       addrs[i].set_type (addr_structs[i].sin_family);
00333       addrs[i].set_size (addrlen);
00334     }
00335 #endif /* ACE_HAS_LKSCTP */
00336   return 0;
00337 }
00338 
00339 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:04 2006 for ACE by doxygen 1.3.6