ACE_Ping_Socket Class Reference

This class is useful to perform ICMP echo checks (pinging) on the party of your interest. It may be used as well to check LAN-adapters against 3rd parties. More...

#include <Ping_Socket.h>

Inheritance diagram for ACE_Ping_Socket:

Inheritance graph
[legend]
Collaboration diagram for ACE_Ping_Socket:

Collaboration graph
[legend]
List of all members.

Public Types

enum  { PING_BUFFER_SIZE = (1024 * 2) }

Public Member Functions

 ACE_Ping_Socket (void)
 Default constructor.

 ACE_Ping_Socket (ACE_Addr const &local, int protocol=IPPROTO_ICMP, int reuse_addr=0)
 ~ACE_Ping_Socket (void)
 Destructor.

int open (ACE_Addr const &local=ACE_Addr::sap_any, int protocol=IPPROTO_ICMP, int reuse_addr=0)
 Wrapper around the BSD-style socket system call (no QoS).

int send_echo_check (ACE_INET_Addr &remote_addr, int to_connect=0)
 toConnect = 1 - makes connect to remote address

int process_incoming_dgram (char *ptr, ssize_t len)
int make_echo_check (ACE_INET_Addr &remote_addr, int to_connect=0, ACE_Time_Value const *timeout=&time_default_)
 toConnect = 1 - makes connect to remote address

char * icmp_recv_buff (void)
void dump (void) const
 Dump the state of an object.


Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.


Static Public Attributes

ACE_Time_Value const  time_default_

Private Types

typedef ACE_ICMP_Socket inherited

Private Member Functions

int receive_echo_reply (ACE_Time_Value const *timeout)
int get_remote_addr (ACE_INET_Addr &addr) const
 Do not allow this function to percolate up to this interface.


Private Attributes

char icmp_send_buff_ [PING_BUFFER_SIZE]
char icmp_recv_buff_ [PING_BUFFER_SIZE]
ACE_UINT16 sequence_number_
int connected_socket_

Detailed Description

This class is useful to perform ICMP echo checks (pinging) on the party of your interest. It may be used as well to check LAN-adapters against 3rd parties.

Definition at line 40 of file Ping_Socket.h.


Member Typedef Documentation

typedef ACE_ICMP_Socket ACE_Ping_Socket::inherited [private]
 

Definition at line 42 of file Ping_Socket.h.


Member Enumeration Documentation

anonymous enum
 

Enumeration values:
PING_BUFFER_SIZE 

Definition at line 86 of file Ping_Socket.h.

00087     {
00088       PING_BUFFER_SIZE = (1024 * 2)
00089     };


Constructor & Destructor Documentation

ACE_Ping_Socket::ACE_Ping_Socket void   ) 
 

Default constructor.

Definition at line 98 of file Ping_Socket.cpp.

References ACE_TRACE.

00099 {
00100   ACE_TRACE ("ACE_Ping_Socket::ACE_Ping_Socket");
00101 }

ACE_Ping_Socket::ACE_Ping_Socket ACE_Addr const &  local,
int  protocol = IPPROTO_ICMP,
int  reuse_addr = 0
 

Definition at line 103 of file Ping_Socket.cpp.

References ACE_DEBUG, ACE_LIB_TEXT, ACE_TRACE, icmp_recv_buff_, icmp_send_buff_, LM_DEBUG, ACE_OS::memset(), open(), and ACE_SOCK::set_option().

00106   : sequence_number_ (0),
00107     connected_socket_ (0)
00108 {
00109   ACE_TRACE ("ACE_Ping_Socket::ACE_Ping_Socket");
00110 
00111   ACE_OS::memset (icmp_send_buff_, 0, sizeof (icmp_send_buff_));
00112   ACE_OS::memset (icmp_recv_buff_, 0, sizeof (icmp_recv_buff_));
00113 
00114   if (this->open (local, protocol, reuse_addr) == -1)
00115     {
00116       ACE_DEBUG ((LM_DEBUG,
00117                   ACE_LIB_TEXT ("ACE_Ping_Socket::ACE_Ping_Socket: %p\n"),
00118                   ACE_LIB_TEXT ("open")));
00119       return;
00120     }
00121 
00122   // trying to increase the size of socket receive buffer - some
00123   // protection from multiple responces e.g., when falling to the
00124   // multi-cast address
00125   int size = 64 * 1024;
00126   ACE_SOCK::set_option (SOL_SOCKET,
00127                         SO_RCVBUF,
00128                         (void *) &size,
00129                         sizeof (size));
00130 }

ACE_Ping_Socket::~ACE_Ping_Socket void   ) 
 

Destructor.

Definition at line 132 of file Ping_Socket.cpp.

References ACE_TRACE.

00133 {
00134   ACE_TRACE ("ACE_Ping_Socket::~ACE_Ping_Socket");
00135 }


Member Function Documentation

void ACE_Ping_Socket::dump void   )  const
 

Dump the state of an object.

Reimplemented from ACE_ICMP_Socket.

Definition at line 93 of file Ping_Socket.cpp.

References ACE_TRACE.

00094 {
00095   ACE_TRACE ("ACE_Ping_Socket::dump");
00096 }

int ACE_Ping_Socket::get_remote_addr ACE_INET_Addr addr  )  const [private]
 

Do not allow this function to percolate up to this interface.

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE char * ACE_Ping_Socket::icmp_recv_buff void   ) 
 

Definition at line 8 of file Ping_Socket.inl.

References icmp_recv_buff_.

00009 {
00010   return this->icmp_recv_buff_;
00011 }

int ACE_Ping_Socket::make_echo_check ACE_INET_Addr remote_addr,
int  to_connect = 0,
ACE_Time_Value const *  timeout = &time_default_
 

toConnect = 1 - makes connect to remote address

Definition at line 357 of file Ping_Socket.cpp.

References ACE_DEBUG, ACE_LIB_TEXT, LM_DEBUG, receive_echo_reply(), and send_echo_check().

00360 {
00361   int rval_send = -1;
00362 
00363   if ((rval_send = this->send_echo_check (remote_addr,
00364                                           to_connect)) == -1)
00365     return -1;
00366 
00367   ACE_DEBUG
00368     ((LM_DEBUG,
00369       ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::make_echo_check - sent %d.\n"),
00370       rval_send));
00371 
00372   return this->receive_echo_reply (timeout);
00373 }

int ACE_Ping_Socket::open ACE_Addr const &  local = ACE_Addr::sap_any,
int  protocol = IPPROTO_ICMP,
int  reuse_addr = 0
 

Wrapper around the BSD-style socket system call (no QoS).

Reimplemented from ACE_ICMP_Socket.

Definition at line 138 of file Ping_Socket.cpp.

References ACE_TRACE.

Referenced by ACE_Ping_Socket().

00141 {
00142   ACE_TRACE ("ACE_Ping_Socket::open");
00143   return inherited::open (local, protocol, reuse_addr);
00144 }

int ACE_Ping_Socket::process_incoming_dgram char *  ptr,
ssize_t  len
 

To receive ICMP_ECHOREPLY. To be called after successfully sending ICMP_ECHO.

Definition at line 207 of file Ping_Socket.cpp.

References ACE_DEBUG, ACE_ERROR_RETURN, ACE_LIB_TEXT, ICMP_ECHOREPLY, ICMP_MIN, LM_DEBUG, LM_ERROR, and ssize_t.

Referenced by receive_echo_reply().

00208 {
00209   unsigned char hlen1;
00210   int icmplen;
00211   struct ip * ip;
00212   struct icmp * icmp;
00213 
00214   ip = (struct ip *) ptr;                 // start of IP header
00215 
00216   // Warning... using knowledge of IP header layout. This avoids a maze of
00217   // #if blocks for various systems. The first byte of the header has the
00218   // IP version in the left-most 4 bits and the length in the other 4 bits.
00219 #if 0
00220   hlen1 = ip->ip_hl;                      // length of IP header
00221 #else
00222   hlen1 = static_cast<unsigned char>(*ptr);
00223   hlen1 <<= 4;                            // Bump the version off
00224   hlen1 >>= 4;                            // Zero-extended length remains
00225 #endif
00226   hlen1 <<= 2;                            // Now it counts bytes, not words
00227 
00228   icmp = (struct icmp *) (ptr + hlen1);   // start of ICMP header
00229 
00230   if ((icmplen = len - hlen1) < ICMP_MIN)
00231     {
00232       ACE_DEBUG
00233         ((LM_DEBUG,
00234           ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram")
00235           ACE_LIB_TEXT (" - ICMP length is %d < 8.\n"),
00236           icmplen));
00237       ACE_ERROR_RETURN
00238         ((LM_ERROR,
00239           ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram - ")
00240           ACE_LIB_TEXT ("The ICMP header either not received or is corrupted.")),
00241          -1);
00242     }
00243 
00244   if (icmp->icmp_type == ICMP_ECHOREPLY)
00245     {
00246       ACE_DEBUG
00247         ((LM_DEBUG,
00248           ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::process_incoming_dgram")
00249           ACE_LIB_TEXT (" - ICMP_ECHOREPLY received.\n")));
00250 
00251       if (icmp->icmp_id != getpid ())
00252         {
00253           ACE_ERROR_RETURN
00254             ((LM_ERROR,
00255               ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::")
00256               ACE_LIB_TEXT ("process_incoming_dgram ")
00257               ACE_LIB_TEXT ("- The ICMP header received is a reply")
00258               ACE_LIB_TEXT (" to request of another process.")),
00259              -1);
00260         }
00261       if (icmplen < 16)
00262         {
00263           ACE_ERROR_RETURN
00264             ((LM_ERROR,
00265               ACE_LIB_TEXT ("(%P|%t) ACE_Ping_Socket::")
00266               ACE_LIB_TEXT ("process_incoming_dgram - ICMP length ")
00267               ACE_LIB_TEXT ("is %d < 16."),
00268               icmplen),
00269              -1);
00270         }
00271 
00272       ACE_DEBUG
00273         ((LM_DEBUG,
00274           ACE_LIB_TEXT ("(%P|%t) ACE::Ping_Socket::process_incoming_dgram - ")
00275           ACE_LIB_TEXT ("received ")
00276           ACE_LIB_TEXT ("ICMP datagram with length of %d bytes (not counting ")
00277           ACE_LIB_TEXT ("IP-header): seq=%u, ttl=%d.\n"),
00278           icmplen, icmp->icmp_seq, ip->ip_ttl));
00279 
00280       return 0; //= success
00281     }
00282 
00283   ACE_DEBUG
00284     ((LM_DEBUG,
00285       ACE_LIB_TEXT ("(%P|%t) ACE::Ping_Socket::process_incoming_dgram - ")
00286       ACE_LIB_TEXT ("received datagram that is not ICMP_ECHOREPLY.\n")));
00287 
00288   return -1;
00289 }

int ACE_Ping_Socket::receive_echo_reply ACE_Time_Value const *  timeout  )  [private]
 

Definition at line 147 of file Ping_Socket.cpp.

References ACE_TRACE, ETIMEDOUT, ACE_OS::gettimeofday(), icmp_recv_buff_, ACE_OS::memset(), and process_incoming_dgram().

Referenced by make_echo_check().

00148 {
00149   ACE_TRACE ("ACE_Ping_Socket::receive_echo_reply");
00150 
00151   ACE_Time_Value before = ACE_OS::gettimeofday ();
00152   ACE_Time_Value after;
00153   ACE_Time_Value time_left;
00154   ACE_Time_Value *wait_time = const_cast<ACE_Time_Value *> (timeout);
00155   const ACE_Time_Value half_millisec (0, 500);
00156 
00157   ACE_OS::memset (icmp_recv_buff_, 0, sizeof icmp_recv_buff_);
00158 
00159   do
00160     {
00161       int rval_recv = inherited::recv (icmp_recv_buff_,
00162                                        sizeof icmp_recv_buff_,
00163                                        0,
00164                                        wait_time);
00165       if (rval_recv < 0)
00166         {
00167           if (errno == EINTR)
00168             {
00169               after = ACE_OS::gettimeofday ();
00170               time_left = *timeout - after + before;
00171 
00172               // If more than .5 ms left, wait on select()
00173               if (time_left > half_millisec)
00174                 {
00175                   wait_time = &time_left; // coming back to wait on select()
00176                   continue;
00177                 }
00178               else
00179                 {
00180                   break;
00181                 }
00182             }
00183           return -1;
00184         }
00185       else if (!this->process_incoming_dgram (icmp_recv_buff_, rval_recv))
00186         {
00187           return 0; //= success
00188         }
00189       else
00190         {
00191           after = ACE_OS::gettimeofday ();
00192           if ((after - before) >= *timeout)
00193             {
00194               errno = ETIMEDOUT;
00195               break;
00196             }
00197           // new timeout, we are coming back to sit on select
00198           *wait_time = *timeout - after + before;
00199         }
00200     } while (*wait_time >= half_millisec);
00201 
00202   errno = ETIMEDOUT;
00203   return -1;
00204 }

int ACE_Ping_Socket::send_echo_check ACE_INET_Addr remote_addr,
int  to_connect = 0
 

toConnect = 1 - makes connect to remote address

Definition at line 292 of file Ping_Socket.cpp.

References ACE_OS::connect(), connected_socket_, ACE_INET_Addr::get_addr(), ACE_IPC_SAP::get_handle(), ACE_Addr::get_size(), ICMP_DATA_LENGTH, ICMP_ECHO, ICMP_MIN, icmp_send_buff_, ACE_OS::memset(), ACE_ICMP_Socket::send(), and sequence_number_.

Referenced by make_echo_check().

00294 {
00295   if (this->get_handle () == ACE_INVALID_HANDLE)
00296     {
00297       errno = EBADF;
00298       return -1;
00299     }
00300 
00301   sockaddr_in *addr_connect = 0;
00302   addr_connect = (sockaddr_in *) remote_addr.get_addr ();
00303 
00304   /*
00305    * Nulling port field to prevent strange behavior, when a raw
00306    * socket is "connected" to a sockaddr_in with a non-nulled port.
00307    */
00308   ACE_OS::memset ((void*) &addr_connect->sin_port,
00309                   0,
00310                   sizeof (addr_connect->sin_port));
00311 
00312   // to connect the socket
00313   if (to_connect && !this->connected_socket_)
00314     {
00315       if (ACE_OS::connect (this->get_handle (),
00316                            (sockaddr*) addr_connect,
00317                            remote_addr.get_size ()) == -1)
00318         {
00319           if (errno != EINTR)
00320             return -1;
00321        }
00322       this->connected_socket_ = 1;
00323     }
00324 
00325   ACE_OS::memset (this->icmp_send_buff_, 0, sizeof this->icmp_send_buff_);
00326   int datalen = ICMP_DATA_LENGTH;
00327   struct icmp *_icmp;
00328 
00329   _icmp = (struct icmp *) this->icmp_send_buff_;
00330   _icmp->icmp_type = ICMP_ECHO;
00331   _icmp->icmp_code = 0;
00332   _icmp->icmp_id = getpid ();
00333   _icmp->icmp_seq = sequence_number_++;
00334 
00335 #if defined (ACE_WIN32)
00336   _icmp->icmp_data = GetTickCount ();
00337 #else  /* #if defined (ACE_WIN32) */
00338   gettimeofday ((struct timeval *) &_icmp->icmp_data, 0);
00339 #endif  /* #if defined (ACE_WIN32) */
00340 
00341   int length_icmp = ICMP_MIN + datalen; // checksum ICMP header and data.
00342   _icmp->icmp_cksum = 0;
00343   _icmp->icmp_cksum = inherited::calculate_checksum ((u_short *) _icmp,
00344                                                      length_icmp);
00345   int rval_send = -1;
00346 
00347   if ((rval_send = send ((void const *) icmp_send_buff_,
00348                          length_icmp,
00349                          remote_addr)) != length_icmp)
00350     {
00351       return -1;
00352     }
00353   return 0;
00354 }


Member Data Documentation

ACE_Ping_Socket::ACE_ALLOC_HOOK_DECLARE
 

Declare the dynamic allocation hooks.

Reimplemented from ACE_ICMP_Socket.

Definition at line 82 of file Ping_Socket.h.

int ACE_Ping_Socket::connected_socket_ [private]
 

Definition at line 105 of file Ping_Socket.h.

Referenced by send_echo_check().

char ACE_Ping_Socket::icmp_recv_buff_[PING_BUFFER_SIZE] [private]
 

Definition at line 101 of file Ping_Socket.h.

Referenced by ACE_Ping_Socket(), icmp_recv_buff(), and receive_echo_reply().

char ACE_Ping_Socket::icmp_send_buff_[PING_BUFFER_SIZE] [private]
 

Definition at line 100 of file Ping_Socket.h.

Referenced by ACE_Ping_Socket(), and send_echo_check().

ACE_UINT16 ACE_Ping_Socket::sequence_number_ [private]
 

Definition at line 103 of file Ping_Socket.h.

Referenced by send_echo_check().

ACE_Time_Value const ACE_Ping_Socket::time_default_ [static]
 


The documentation for this class was generated from the following files:
Generated on Thu Nov 9 11:26:24 2006 for ACE by doxygen 1.3.6