#include "IOR_Multicast.h" #include "tao/debug.h" #include "ace/SOCK_Connector.h" #include "ace/SString.h" ACE_RCSID (orbsvcs, IOR_Multicast, "$Id$") ACE_HANDLE TAO_IOR_Multicast::get_handle (void) const { return this->mcast_dgram_.get_handle (); } TAO_IOR_Multicast::TAO_IOR_Multicast (void) : service_id_ ((TAO_Service_ID) 0), ior_ (0), mcast_nic_ (0) { } TAO_IOR_Multicast::TAO_IOR_Multicast (const char *ior, u_short port, const char *mcast_addr, TAO_Service_ID service_id) : mcast_nic_ (0) { if (this->init (ior, port, mcast_addr, service_id) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("TAO_IOR_Multicast"))); } // destructor TAO_IOR_Multicast::~TAO_IOR_Multicast (void) { this->mcast_dgram_.leave (this->mcast_addr_); } int TAO_IOR_Multicast::init (const char *ior, u_short port, const char *mcast_addr, TAO_Service_ID service_id) { if (this->mcast_addr_.set (port, mcast_addr) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "set"), -1); return common_init (ior, service_id); } int TAO_IOR_Multicast::init (const char *ior, const char *mcast_addr, TAO_Service_ID service_id) { // Look for a '@' incase a nic is specified. this->mcast_nic_ = ACE_OS::strchr (mcast_addr, '@'); CORBA::String_var actual_mcast_addr; CORBA::ULong length_addr; if (this->mcast_nic_ != 0) { // i.e. a nic name has been specified length_addr = this->mcast_nic_ - mcast_addr + 1; actual_mcast_addr = CORBA::string_alloc (length_addr); ACE_OS::strncpy (actual_mcast_addr.inout (), mcast_addr, length_addr - 1); actual_mcast_addr[length_addr - 1] = '\0'; /// Save for use later. this->mcast_nic_ = this->mcast_nic_ + 1; } else { actual_mcast_addr = CORBA::string_alloc (ACE_static_cast (CORBA::ULong, ACE_OS::strlen (mcast_addr))); actual_mcast_addr = mcast_addr; } if (this->mcast_addr_.set (actual_mcast_addr.in ()) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "set"), -1); return common_init (ior, service_id); } int TAO_IOR_Multicast::common_init (const char *ior, TAO_Service_ID service_id) { this->service_id_ = service_id; this->ior_ = ior; if (this->response_addr_.set ((u_short) 0) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "set"), -1); else if (this->response_.open (this->response_addr_) == -1) { ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "set"), -1); } // Use ACE_SOCK_Dgram_Mcast factory to subscribe to multicast group. if (this->mcast_nic_ != 0) { if (this->mcast_dgram_.subscribe (this->mcast_addr_, 1, ACE_TEXT_CHAR_TO_TCHAR(this->mcast_nic_)) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "subscribe"), -1); } else { if (this->mcast_dgram_.subscribe (this->mcast_addr_) == -1) ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "subscribe"), -1); } return 0; } int TAO_IOR_Multicast::handle_timeout (const ACE_Time_Value &, const void *) { return 0; } int TAO_IOR_Multicast::handle_input (ACE_HANDLE) { if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "Entered TAO_IOR_Multicast::handle_input\n")); // The length of the service name string that follows. CORBA::Short header; // Port to which to reply. ACE_UINT16 remote_port; // Name of the service for which the client is looking. char service_name[BUFSIZ]; ACE_INET_Addr remote_addr; // Take a peek at the header to find out how long is the service // name string we should receive. ssize_t n = this->mcast_dgram_.recv (&header, sizeof (header), remote_addr, MSG_PEEK); if (n <= 0) ACE_ERROR_RETURN ((LM_ERROR, "TAO_IOR_Multicast::handle_input - peek %d\n", n), 0); else if (ACE_NTOHS (header) <= 0) ACE_ERROR_RETURN ((LM_ERROR, "Header value < 1\n"), 0); // Receive full client multicast request. const int iovcnt = 3; iovec iov[iovcnt]; iov[0].iov_base = (char *) &header; iov[0].iov_len = sizeof (header); iov[1].iov_base = (char *) &remote_port; iov[1].iov_len = sizeof (ACE_UINT16); iov[2].iov_base = (char *) service_name; iov[2].iov_len = ACE_NTOHS (header); // Read the iovec. n = this->mcast_dgram_.recv (iov, iovcnt, remote_addr); if (n <= 0) ACE_ERROR_RETURN ((LM_ERROR, "TAO_IOR_Multicast::handle_input recv = %d\n", n), 0); if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) Received multicast.\n" "Service Name received : %s\n" "Port received : %u\n", service_name, ACE_NTOHS (remote_port))); // Our reply data. ACE_CString ior (this->ior_); if (ACE_OS::strcmp (service_name, "NameService") != 0 && ACE_OS::strcmp (service_name, "TradingService") != 0 && ACE_OS::strcmp (service_name, "ImplRepoService") != 0 && ACE_OS::strcmp (service_name, "InterfaceRepository") != 0 && ACE_OS::strcmp (service_name, "MCASTServer") != 0) { ACE_ERROR_RETURN ((LM_ERROR, "Unknown service requested.\n"), 0); } // Reply to the multicast message. ACE_SOCK_Connector connector; ACE_INET_Addr peer_addr (ACE_NTOHS (remote_port), remote_addr.get_host_addr ()); ACE_SOCK_Stream stream; // Connect. if (connector.connect (stream, peer_addr) == -1) ACE_ERROR_RETURN ((LM_ERROR, "IOR_Multicast::connect failed\n"), 0); // Send the IOR back to the client. (Send iovec, which contains ior // length as the first element, and ior itself as the second.) // Length of ior to be sent. CORBA::Short data_len = ACE_static_cast (CORBA::Short, ACE_HTONS (ior.length () + 1)); // Vector to be sent. const int cnt = 2; iovec iovp[cnt]; // The length of ior to be sent. iovp[0].iov_base = (char *) &data_len; iovp[0].iov_len = sizeof (CORBA::Short); // The ior. iovp[1].iov_base = ACE_const_cast (char*, ior.c_str ()); iovp[1].iov_len = ACE_static_cast (u_long, ior.length () + 1); ssize_t result = stream.sendv_n (iovp, cnt); // Close the stream. stream.close (); // Check for error. if (result == -1) return 0; if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, "(%P|%t) ior_: <%s>\n" "sent to %s:%u.\n" "result from send = %d\n", ior.c_str (), peer_addr.get_host_name (), peer_addr.get_port_number (), result)); return 0; }