Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SOCK_Dgram.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 #include "ace/SOCK_Dgram.h"
00003 #include "ace/Handle_Set.h"
00004 #include "ace/Synch.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/INET_Addr.h"
00007 #include "ace/ACE.h"
00008 
00009 #if defined (ACE_LACKS_INLINE_FUNCTIONS)
00010 #include "ace/SOCK_Dgram.i"
00011 #endif
00012 
00013 ACE_RCSID (ace,
00014            SOCK_Dgram,
00015            "$Id: SOCK_Dgram.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00016 
00017 ACE_ALLOC_HOOK_DEFINE (ACE_SOCK_Dgram)
00018 
00019 void
00020 ACE_SOCK_Dgram::dump (void) const
00021 {
00022   ACE_TRACE ("ACE_SOCK_Dgram::dump");
00023 }
00024 
00025 // Allows a client to read from a socket without having to provide a
00026 // buffer to read.  This method determines how much data is in the
00027 // socket, allocates a buffer of this size, reads in the data, and
00028 // returns the number of bytes read.
00029 
00030 ssize_t
00031 ACE_SOCK_Dgram::recv (iovec *io_vec,
00032                       ACE_Addr &addr,
00033                       int flags,
00034                       const ACE_Time_Value *timeout) const
00035 {
00036   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00037 #if defined (FIONREAD)
00038   ACE_Handle_Set handle_set;
00039   handle_set.reset ();
00040   handle_set.set_bit (this->get_handle ());
00041 
00042   // Check the status of the current socket to make sure there's data
00043   // to recv (or time out).
00044   int select_width;
00045 #  if defined (ACE_WIN64)
00046   // This arg is ignored on Windows and causes pointer truncation
00047   // warnings on 64-bit compiles.
00048   select_width = 0;
00049 #  else
00050   select_width = int (this->get_handle ()) + 1;
00051 #  endif /* ACE_WIN64 */
00052   switch (ACE_OS::select (select_width,
00053                           handle_set,
00054                           0, 0,
00055                           timeout))
00056     {
00057     case -1:
00058       return -1;
00059       /* NOTREACHED */
00060     case 0:
00061       errno = ETIME;
00062       return -1;
00063       /* NOTREACHED */
00064     default:
00065       // Goes fine, fallthrough to get data
00066       break;
00067     }
00068 
00069   sockaddr *saddr = (sockaddr *) addr.get_addr ();
00070   int addr_len = addr.get_size ();
00071   u_long inlen;
00072 
00073   if (ACE_OS::ioctl (this->get_handle (),
00074                      FIONREAD, (u_long *) &inlen) == -1)
00075     return -1;
00076   else if (inlen > 0)
00077     {
00078       ACE_NEW_RETURN (io_vec->iov_base,
00079                       char[inlen],
00080                       -1);
00081       io_vec->iov_len = ACE_OS::recvfrom (this->get_handle (),
00082                                           (char *) io_vec->iov_base,
00083                                           inlen,
00084                                           flags,
00085                                           (sockaddr *) saddr,
00086                                           &addr_len);
00087       addr.set_size (addr_len);
00088       return io_vec->iov_len;
00089     }
00090   else
00091     return 0;
00092 #else
00093   ACE_UNUSED_ARG (flags);
00094   ACE_UNUSED_ARG (addr);
00095   ACE_UNUSED_ARG (io_vec);
00096   ACE_UNUSED_ARG (timeout);
00097   ACE_NOTSUP_RETURN (-1);
00098 #endif /* FIONREAD */
00099 }
00100 
00101 // Here's the shared open function.  Note that if we are using the
00102 // PF_INET protocol family and the address of LOCAL == the address of
00103 // the special variable SAP_ANY then we are going to arbitrarily bind
00104 // to a portnumber.
00105 
00106 int
00107 ACE_SOCK_Dgram::shared_open (const ACE_Addr &local,
00108                              int protocol_family)
00109 {
00110   ACE_TRACE ("ACE_SOCK_Dgram::shared_open");
00111   int error = 0;
00112 
00113   if (local == ACE_Addr::sap_any)
00114     {
00115       if (protocol_family == PF_INET
00116 #if defined (ACE_HAS_IPV6)
00117           || protocol_family == PF_INET6
00118 #endif /* ACE_HAS_IPV6 */
00119           )
00120         {
00121           if (ACE::bind_port (this->get_handle ()) == -1)
00122             error = 1;
00123         }
00124     }
00125   else if (ACE_OS::bind (this->get_handle (),
00126                          ACE_reinterpret_cast (sockaddr *,
00127                                                local.get_addr ()),
00128                          local.get_size ()) == -1)
00129     error = 1;
00130 
00131   if (error != 0)
00132     this->close ();
00133 
00134   return error ? -1 : 0;
00135 }
00136 
00137 int
00138 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00139                       int protocol_family,
00140                       int protocol,
00141                       ACE_Protocol_Info *protocolinfo,
00142                       ACE_SOCK_GROUP g,
00143                       u_long flags,
00144                       int reuse_addr)
00145 {
00146   if (ACE_SOCK::open (SOCK_DGRAM,
00147                       protocol_family,
00148                       protocol,
00149                       protocolinfo,
00150                       g,
00151                       flags,
00152                       reuse_addr) == -1)
00153     return -1;
00154   else if (this->shared_open (local,
00155                               protocol_family) == -1)
00156     return -1;
00157   else
00158     return 0;
00159 }
00160 
00161 // Here's the general-purpose open routine.
00162 
00163 int
00164 ACE_SOCK_Dgram::open (const ACE_Addr &local,
00165                       int protocol_family,
00166                       int protocol,
00167                       int reuse_addr)
00168 {
00169   ACE_TRACE ("ACE_SOCK_Dgram::open");
00170 
00171   if (local != ACE_Addr::sap_any)
00172     protocol_family = local.get_type ();
00173   else if (protocol_family == PF_UNSPEC)
00174     {
00175 #if defined (ACE_HAS_IPV6)
00176       protocol_family = ACE_Sock_Connect::ipv6_enabled () ? PF_INET6 : PF_INET;
00177 #else
00178       protocol_family = PF_INET;
00179 #endif /* ACE_HAS_IPV6 */
00180     }
00181 
00182   if (ACE_SOCK::open (SOCK_DGRAM,
00183                       protocol_family,
00184                       protocol,
00185                       reuse_addr) == -1)
00186     return -1;
00187   else
00188     return this->shared_open (local,
00189                               protocol_family);
00190 }
00191 
00192 // Here's the general-purpose constructor used by a connectionless
00193 // datagram ``server''...
00194 
00195 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00196                                 int protocol_family,
00197                                 int protocol,
00198                                 int reuse_addr)
00199 {
00200   ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00201 
00202   if (this->open (local,
00203                   protocol_family,
00204                   protocol,
00205                   reuse_addr) == -1)
00206     ACE_ERROR ((LM_ERROR,
00207                 ACE_LIB_TEXT ("%p\n"),
00208                 ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
00209 }
00210 
00211 ACE_SOCK_Dgram::ACE_SOCK_Dgram (const ACE_Addr &local,
00212                                 int protocol_family,
00213                                 int protocol,
00214                                 ACE_Protocol_Info *protocolinfo,
00215                                 ACE_SOCK_GROUP g,
00216                                 u_long flags,
00217                                 int reuse_addr)
00218 {
00219   ACE_TRACE ("ACE_SOCK_Dgram::ACE_SOCK_Dgram");
00220   if (this->open (local,
00221                   protocol_family,
00222                   protocol,
00223                   protocolinfo,
00224                   g,
00225                   flags,
00226                   reuse_addr) == -1)
00227     ACE_ERROR ((LM_ERROR,
00228                 ACE_LIB_TEXT ("%p\n"),
00229                 ACE_LIB_TEXT ("ACE_SOCK_Dgram")));
00230 }
00231 
00232 #if defined (ACE_HAS_MSG)
00233 // Send an iovec of size N to ADDR as a datagram (connectionless
00234 // version).
00235 
00236 ssize_t
00237 ACE_SOCK_Dgram::send (const iovec iov[],
00238                       int n,
00239                       const ACE_Addr &addr,
00240                       int flags) const
00241 {
00242   ACE_TRACE ("ACE_SOCK_Dgram::send");
00243   msghdr send_msg;
00244 
00245   send_msg.msg_iov = (iovec *) iov;
00246   send_msg.msg_iovlen = n;
00247 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00248   send_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00249 #else
00250   send_msg.msg_name = (char *) addr.get_addr ();
00251 #endif /* ACE_HAS_SOCKADDR_MSG_NAME */
00252   send_msg.msg_namelen = addr.get_size ();
00253 
00254 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00255   send_msg.msg_control = 0;
00256   send_msg.msg_controllen = 0;
00257   send_msg.msg_flags = 0;
00258 #else
00259   send_msg.msg_accrights    = 0;
00260   send_msg.msg_accrightslen = 0;
00261 #endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
00262 
00263   return ACE_OS::sendmsg (this->get_handle (),
00264                           &send_msg,
00265                           flags);
00266 }
00267 
00268 // Recv an iovec of size N to ADDR as a datagram (connectionless
00269 // version).
00270 
00271 ssize_t
00272 ACE_SOCK_Dgram::recv (iovec iov[],
00273                       int n,
00274                       ACE_Addr &addr,
00275                       int flags) const
00276 {
00277   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00278   msghdr recv_msg;
00279 
00280   recv_msg.msg_iov = (iovec *) iov;
00281   recv_msg.msg_iovlen = n;
00282 #if defined (ACE_HAS_SOCKADDR_MSG_NAME)
00283   recv_msg.msg_name = (struct sockaddr *) addr.get_addr ();
00284 #else
00285   recv_msg.msg_name = (char *) addr.get_addr ();
00286 #endif /* ACE_HAS_SOCKADDR_MSG_NAME */
00287   recv_msg.msg_namelen = addr.get_size ();
00288 
00289 #if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG)
00290   recv_msg.msg_control = 0 ;
00291   recv_msg.msg_controllen = 0 ;
00292 #else
00293   recv_msg.msg_accrights = 0;
00294   recv_msg.msg_accrightslen = 0;
00295 #endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */
00296 
00297   ssize_t status = ACE_OS::recvmsg (this->get_handle (),
00298                                     &recv_msg,
00299                                     flags);
00300   addr.set_size (recv_msg.msg_namelen);
00301   return status;
00302 }
00303 
00304 #else /* ACE_HAS_MSG */
00305 
00306 // Send an iovec of size N to ADDR as a datagram (connectionless
00307 // version).
00308 
00309 ssize_t
00310 ACE_SOCK_Dgram::send (const iovec iov[],
00311                       int n,
00312                       const ACE_Addr &addr,
00313                       int flags) const
00314 {
00315   ACE_TRACE ("ACE_SOCK_Dgram::send");
00316 
00317   size_t length = 0;
00318   int i;
00319 
00320   // Determine the total length of all the buffers in <iov>.
00321   for (i = 0; i < n; i++)
00322 #if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
00323     // The iov_len is unsigned in Borland. If we go ahead and try the
00324     // if, it will emit a warning.
00325     if (iov[i].iov_len < 0)
00326       return -1;
00327     else
00328 #endif
00329       length += iov[i].iov_len;
00330 
00331   char *buf;
00332 
00333 #if defined (ACE_HAS_ALLOCA)
00334   buf = alloca (length);
00335 #else
00336   ACE_NEW_RETURN (buf,
00337                   char[length],
00338                   -1);
00339 #endif /* !defined (ACE_HAS_ALLOCA) */
00340 
00341   char *ptr = buf;
00342 
00343   for (i = 0; i < n; i++)
00344     {
00345       ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len);
00346       ptr += iov[i].iov_len;
00347     }
00348 
00349   ssize_t result = ACE_SOCK_Dgram::send (buf, length, addr, flags);
00350 #if !defined (ACE_HAS_ALLOCA)
00351   delete [] buf;
00352 #endif /* !defined (ACE_HAS_ALLOCA) */
00353   return result;
00354 }
00355 
00356 // Recv an iovec of size N to ADDR as a datagram (connectionless
00357 // version).
00358 
00359 ssize_t
00360 ACE_SOCK_Dgram::recv (iovec iov[],
00361                       int n,
00362                       ACE_Addr &addr,
00363                       int flags) const
00364 {
00365   ACE_TRACE ("ACE_SOCK_Dgram::recv");
00366 
00367   ssize_t length = 0;
00368   int i;
00369 
00370   for (i = 0; i < n; i++)
00371 #if ! (defined(__BORLANDC__) && (__BORLANDC__ >= 0x0530))
00372     // The iov_len is unsigned in Borland. If we go ahead and try the
00373     // if, it will emit a warning.
00374     if (iov[i].iov_len < 0)
00375       return -1;
00376     else
00377 #endif
00378       length += iov[i].iov_len;
00379 
00380   char *buf;
00381 
00382 #if defined (ACE_HAS_ALLOCA)
00383   buf = alloca (length);
00384 #else
00385   ACE_NEW_RETURN (buf,
00386                   char[length],
00387                   -1);
00388 #endif /* !defined (ACE_HAS_ALLOCA) */
00389 
00390   length = ACE_SOCK_Dgram::recv (buf, length, addr, flags);
00391 
00392   if (length != -1)
00393     {
00394       char *ptr = buf;
00395       int copyn = length;
00396 
00397       for (i = 0;
00398            i < n && copyn > 0;
00399            i++)
00400         {
00401           ACE_OS::memcpy (iov[i].iov_base, ptr,
00402                           // iov_len is int on some platforms, size_t on others
00403                           copyn > (int) iov[i].iov_len
00404                             ? (size_t) iov[i].iov_len
00405                             : (size_t) copyn);
00406           ptr += iov[i].iov_len;
00407           copyn -= iov[i].iov_len;
00408         }
00409     }
00410 
00411 #if !defined (ACE_HAS_ALLOCA)
00412   delete [] buf;
00413 #endif /* !defined (ACE_HAS_ALLOCA) */
00414   return length;
00415 }
00416 
00417 #endif /* ACE_HAS_MSG */
00418 
00419 ssize_t
00420 ACE_SOCK_Dgram::recv (void *buf,
00421                       size_t n,
00422                       ACE_Addr &addr,
00423                       int flags,
00424                       const ACE_Time_Value *timeout) const
00425 {
00426   ACE_Handle_Set handle_set;
00427   handle_set.reset ();
00428   handle_set.set_bit (this->get_handle ());
00429 
00430   // Check the status of the current socket.
00431   int select_width;
00432 #if defined (ACE_WIN64)
00433   // This arg is ignored on Windows and causes pointer truncation
00434   // warnings on 64-bit compiles.
00435   select_width = 0;
00436 #else
00437   select_width = int (this->get_handle ()) + 1;
00438 #endif /* ACE_WIN64 */
00439   switch (ACE_OS::select (select_width,
00440                           handle_set,
00441                           0,
00442                           0,
00443                           timeout))
00444     {
00445     case -1:
00446       return -1;
00447       /* NOTREACHED */
00448     case 0:
00449       errno = ETIME;
00450       return -1;
00451       /* NOTREACHED */
00452     default:
00453       // Goes fine, call <recv> to get data
00454       return this->recv (buf, n, addr, flags);
00455     }
00456 }
00457 
00458 ssize_t
00459 ACE_SOCK_Dgram::send (const void *buf,
00460                       size_t n,
00461                       const ACE_Addr &addr,
00462                       int flags,
00463                       const ACE_Time_Value *timeout) const
00464 {
00465   ACE_Handle_Set handle_set;
00466   handle_set.reset ();
00467   handle_set.set_bit (this->get_handle ());
00468 
00469   // Check the status of the current socket.
00470   int select_width;
00471 #if defined (ACE_WIN64)
00472   // This arg is ignored on Windows and causes pointer truncation
00473   // warnings on 64-bit compiles.
00474   select_width = 0;
00475 #else
00476   select_width = int (this->get_handle ()) + 1;
00477 #endif /* ACE_WIN64 */
00478   switch (ACE_OS::select (select_width,
00479                           0,
00480                           handle_set,
00481                           0,
00482                           timeout))
00483     {
00484     case -1:
00485       return -1;
00486       /* NOTREACHED */
00487     case 0:
00488       errno = ETIME;
00489       return -1;
00490       /* NOTREACHED */
00491     default:
00492       // Goes fine, call <send> to transmit the data.
00493       return this->send (buf, n, addr, flags);
00494     }
00495 }
00496 
00497 void
00498 ACE_SOCK_Dgram::set_nic (const char *option_value)
00499 {
00500   /* The first step would be to get the interface address for the
00501      nic_name specified */
00502   ip_mreq multicast_address;
00503   ACE_INET_Addr mcast_addr;
00504 #if defined (ACE_WIN32)
00505   // This port number is not necessary, just convenient
00506   ACE_INET_Addr interface_addr;
00507   if (interface_addr.set (mcast_addr.get_port_number (),
00508                           option_value) == -1)
00509     return;
00510   multicast_address.imr_interface.s_addr =
00511     htonl (interface_addr.get_ip_address ());
00512 #else
00513   ifreq if_address;
00514 
00515 #if defined (ACE_PSOS)
00516   // Look up the interface by number, not name.
00517   if_address.ifr_ifno = ACE_OS::atoi (option_value);
00518 #else
00519   ACE_OS::strcpy (if_address.ifr_name, option_value);
00520 #endif /* defined (ACE_PSOS) */
00521 
00522   if (ACE_OS::ioctl (this->get_handle (),
00523                      SIOCGIFADDR,
00524                      &if_address) == -1)
00525         return;
00526 
00527   /* Cast this into the required format */
00528   sockaddr_in *socket_address;
00529   socket_address = ACE_reinterpret_cast(sockaddr_in *,
00530                                         &if_address.ifr_addr);
00531   multicast_address.imr_interface.s_addr = socket_address->sin_addr.s_addr;
00532 #endif /* ACE_WIN32 */
00533 
00534   /*
00535    * Now. I got the interface address for the 'nic' specified.
00536    * Use that to set the nic option.
00537    */
00538 
00539   this->ACE_SOCK::set_option (IPPROTO_IP,
00540                               IP_MULTICAST_IF,
00541                               &multicast_address.imr_interface.s_addr,
00542                               sizeof (struct in_addr));
00543 }

Generated on Mon Jun 16 11:21:19 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002