summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/UdpTransceiver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Ice/UdpTransceiver.cpp')
-rw-r--r--cpp/src/Ice/UdpTransceiver.cpp213
1 files changed, 213 insertions, 0 deletions
diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp
new file mode 100644
index 00000000000..5ec525de5f3
--- /dev/null
+++ b/cpp/src/Ice/UdpTransceiver.cpp
@@ -0,0 +1,213 @@
+// **********************************************************************
+//
+// Copyright (c) 2001
+// MutableRealms, Inc.
+// Huntsville, AL, USA
+//
+// All Rights Reserved
+//
+// **********************************************************************
+
+#include <Ice/UdpTransceiver.h>
+#include <Ice/Instance.h>
+#include <Ice/TraceLevels.h>
+#include <Ice/Logger.h>
+#include <Ice/Buffer.h>
+#include <Ice/Network.h>
+#include <Ice/LocalException.h>
+#include <sstream>
+
+using namespace std;
+using namespace Ice;
+using namespace IceInternal;
+
+int
+IceInternal::UdpTransceiver::fd()
+{
+ return _fd;
+}
+
+void
+IceInternal::UdpTransceiver::close()
+{
+#ifndef ICE_NO_TRACE
+ if (_traceLevels->network >= 1)
+ {
+ ostringstream s;
+ if (_sender)
+ s << "stopping to send packets to " << toString();
+ else
+ s << "stopping to receive packets at " << toString();
+ _logger->trace(_traceLevels->networkCat, s.str());
+ }
+#endif
+
+ int fd = _fd;
+ _fd = INVALID_SOCKET;
+ closeSocket(fd);
+}
+
+void
+IceInternal::UdpTransceiver::shutdown()
+{
+}
+
+void
+IceInternal::UdpTransceiver::write(Buffer& buf, int)
+{
+ assert(_sender);
+ assert(buf.i == buf.b.begin());
+ const int packetSize = 64 * 1024; // TODO: configurable
+ assert(packetSize >= static_cast<int>(buf.b.size())); // TODO: exception
+
+repeat:
+ int ret = ::send(_fd, buf.b.begin(), buf.b.size(), 0);
+
+ if (ret == SOCKET_ERROR)
+ {
+ if (interrupted())
+ goto repeat;
+
+ throw SocketException(__FILE__, __LINE__);
+ }
+
+#ifndef ICE_NO_TRACE
+ if (_traceLevels->network >= 3)
+ {
+ ostringstream s;
+ s << "sent " << ret << " bytes via UDP to " << toString();
+ _logger->trace(_traceLevels->networkCat, s.str());
+ }
+#endif
+
+ assert(ret == static_cast<int>(buf.b.size()));
+ buf.i = buf.b.end();
+}
+
+void
+IceInternal::UdpTransceiver::read(Buffer& buf, int)
+{
+ assert(!_sender);
+ assert(buf.i == buf.b.begin());
+ const int packetSize = 64 * 1024; // TODO: configurable
+ assert(packetSize >= static_cast<int>(buf.b.size())); // TODO: exception
+ buf.b.resize(packetSize);
+ buf.i = buf.b.begin();
+
+repeat:
+ int ret = ::recv(_fd, buf.b.begin(), packetSize, 0);
+
+ if (ret == SOCKET_ERROR)
+ {
+ if (interrupted())
+ goto repeat;
+
+ throw SocketException(__FILE__, __LINE__);
+ }
+
+#ifndef ICE_NO_TRACE
+ if (_traceLevels->network >= 3)
+ {
+ ostringstream s;
+ s << "received " << ret << " bytes via UDP at " << toString();
+ _logger->trace(_traceLevels->networkCat, s.str());
+ }
+#endif
+
+ buf.b.resize(ret);
+ buf.i = buf.b.end();
+}
+
+string
+IceInternal::UdpTransceiver::toString() const
+{
+ return addrToString(_addr);
+}
+
+bool
+IceInternal::UdpTransceiver::equivalent(const string& host, int port) const
+{
+ if (_sender)
+ return false;
+
+ struct sockaddr_in addr;
+ getAddress(host.c_str(), port, addr);
+ if (addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ return port == ntohs(_addr.sin_port);
+
+ struct sockaddr_in localAddr;
+ getLocalAddress(ntohs(_addr.sin_port), localAddr);
+ return memcmp(&addr, &localAddr, sizeof(struct sockaddr_in)) == 0;
+}
+
+IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const string& host, int port) :
+ _instance(instance),
+ _sender(true)
+{
+#ifndef ICE_NO_TRACE
+ _traceLevels = _instance->traceLevels();
+ _logger = _instance->logger();
+#endif
+
+ try
+ {
+ getAddress(host.c_str(), port, _addr);
+
+ _fd = createSocket(true);
+ doConnect(_fd, _addr, -1);
+
+#ifndef ICE_NO_TRACE
+ if (_traceLevels->network >= 1)
+ {
+ ostringstream s;
+ s << "starting to send packets to " << toString();
+ _logger->trace(_traceLevels->networkCat, s.str());
+ }
+#endif
+ }
+ catch(...)
+ {
+ _fd = INVALID_SOCKET;
+ throw;
+ }
+}
+
+IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, int port) :
+ _instance(instance),
+ _sender(false)
+{
+#ifndef ICE_NO_TRACE
+ _traceLevels = _instance->traceLevels();
+ _logger = _instance->logger();
+#endif
+
+ try
+ {
+ memset(&_addr, 0, sizeof(_addr));
+ _addr.sin_family = AF_INET;
+ _addr.sin_port = htons(port);
+ _addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ _fd = createSocket(true);
+ doBind(_fd, _addr);
+
+#ifndef ICE_NO_TRACE
+ if (_traceLevels->network >= 1)
+ {
+ ostringstream s;
+ s << "starting to receive packets at " << toString();
+ _logger->trace(_traceLevels->networkCat, s.str());
+ }
+#endif
+ }
+ catch(...)
+ {
+ _fd = INVALID_SOCKET;
+ throw;
+ }
+}
+
+IceInternal::UdpTransceiver::~UdpTransceiver()
+{
+ assert(_fd == INVALID_SOCKET);
+}