summaryrefslogtreecommitdiff
path: root/cpp/src/IceBT/Util.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2015-11-06 11:24:22 -0800
committerMark Spruiell <mes@zeroc.com>2015-11-06 11:24:22 -0800
commit61f9f44b8eda9c9cdb9139436d4ad87e6e7d5839 (patch)
tree286025a254ce57d02068551f11cf69b89fa66a72 /cpp/src/IceBT/Util.cpp
parentA few changes to support move of Freeze (diff)
downloadice-61f9f44b8eda9c9cdb9139436d4ad87e6e7d5839.tar.bz2
ice-61f9f44b8eda9c9cdb9139436d4ad87e6e7d5839.tar.xz
ice-61f9f44b8eda9c9cdb9139436d4ad87e6e7d5839.zip
initial commit of C++ Bluetooth transport
Diffstat (limited to 'cpp/src/IceBT/Util.cpp')
-rw-r--r--cpp/src/IceBT/Util.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/cpp/src/IceBT/Util.cpp b/cpp/src/IceBT/Util.cpp
new file mode 100644
index 00000000000..baf3edff738
--- /dev/null
+++ b/cpp/src/IceBT/Util.cpp
@@ -0,0 +1,228 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceBT/Util.h>
+
+#include <Ice/LocalException.h>
+#include <Ice/Network.h>
+#include <IceUtil/StringUtil.h>
+
+using namespace std;
+using namespace Ice;
+using namespace IceBT;
+
+bool
+IceBT::isValidDeviceAddress(const string& str)
+{
+ //
+ // Format is 01:23:45:67:89:0A
+ //
+
+ if(str.size() != 17 || str[2] != ':' || str[5] != ':' || str[8] != ':' || str[11] != ':' || str[14] != ':')
+ {
+ return false;
+ }
+
+ for(string::size_type i = 0; i < str.size(); i += 3)
+ {
+ if(!isxdigit(str[i]) || !isxdigit(str[i + 1]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+IceBT::parseDeviceAddress(const string& str, DeviceAddress& addr)
+{
+ uint8_t b0, b1, b2, b3, b4, b5;
+
+ if(isValidDeviceAddress(str) &&
+ sscanf(str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &b5, &b4, &b3, &b2, &b1, &b0) == 6)
+ {
+ addr.b[0] = b0;
+ addr.b[1] = b1;
+ addr.b[2] = b2;
+ addr.b[3] = b3;
+ addr.b[4] = b4;
+ addr.b[5] = b5;
+ return true;
+ }
+
+ return false;
+}
+
+string
+IceBT::formatDeviceAddress(const DeviceAddress& addr)
+{
+ char buf[64];
+ sprintf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", addr.b[5], addr.b[4], addr.b[3], addr.b[2], addr.b[1],
+ addr.b[0]);
+ return IceUtilInternal::toUpper(string(buf));
+}
+
+string
+IceBT::addrToString(const string& addr, Int channel)
+{
+ ostringstream ostr;
+ ostr << addr << '#' << channel;
+ return ostr.str();
+}
+
+string
+IceBT::addrToString(const SocketAddress& addr)
+{
+ return addrToString(formatDeviceAddress(addr.rc_bdaddr), addr.rc_channel);
+}
+
+SocketAddress
+IceBT::createAddr(const string& addr, Ice::Int channel)
+{
+ SocketAddress ret;
+ memset(&ret, 0, sizeof(ret));
+ ret.rc_family = AF_BLUETOOTH;
+ ret.rc_channel = static_cast<uint8_t>(channel);
+ parseDeviceAddress(addr, ret.rc_bdaddr);
+ return ret;
+}
+
+namespace
+{
+
+void
+fdToLocalAddress(SOCKET fd, SocketAddress& addr)
+{
+ socklen_t len = static_cast<socklen_t>(sizeof(SocketAddress));
+ if(::getsockname(fd, reinterpret_cast<struct sockaddr*>(&addr), &len) == SOCKET_ERROR)
+ {
+ IceInternal::closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = IceInternal::getSocketErrno();
+ throw ex;
+ }
+}
+
+bool
+fdToRemoteAddress(SOCKET fd, SocketAddress& addr)
+{
+ socklen_t len = static_cast<socklen_t>(sizeof(SocketAddress));
+ if(::getpeername(fd, reinterpret_cast<struct sockaddr*>(&addr), &len) == SOCKET_ERROR)
+ {
+ if(IceInternal::notConnected())
+ {
+ return false;
+ }
+ else
+ {
+ IceInternal::closeSocketNoThrow(fd);
+ SocketException ex(__FILE__, __LINE__);
+ ex.error = IceInternal::getSocketErrno();
+ throw ex;
+ }
+ }
+
+ return true;
+}
+
+string
+addressesToString(const SocketAddress& localAddr, const SocketAddress& remoteAddr, bool peerConnected)
+{
+ ostringstream s;
+ s << "local address = " << addrToString(localAddr);
+ if(peerConnected)
+ {
+ s << "\nremote address = " << addrToString(remoteAddr);
+ }
+ else
+ {
+ s << "\nremote address = <not connected>";
+ }
+ return s.str();
+}
+
+void
+addrToAddressAndChannel(const SocketAddress& addr, string& address, int& channel)
+{
+ address = formatDeviceAddress(addr.rc_bdaddr);
+ channel = addr.rc_channel;
+}
+
+}
+
+string
+IceBT::fdToString(SOCKET fd)
+{
+ if(fd == INVALID_SOCKET)
+ {
+ return "<closed>";
+ }
+
+ SocketAddress localAddr;
+ fdToLocalAddress(fd, localAddr);
+
+ SocketAddress remoteAddr;
+ bool peerConnected = fdToRemoteAddress(fd, remoteAddr);
+
+ return addressesToString(localAddr, remoteAddr, peerConnected);
+}
+
+void
+IceBT::fdToAddressAndChannel(SOCKET fd, string& localAddress, int& localChannel, string& remoteAddress,
+ int& remoteChannel)
+{
+ if(fd == INVALID_SOCKET)
+ {
+ localAddress.clear();
+ remoteAddress.clear();
+ localChannel = -1;
+ remoteChannel = -1;
+ return;
+ }
+
+ SocketAddress localAddr;
+ fdToLocalAddress(fd, localAddr);
+ addrToAddressAndChannel(localAddr, localAddress, localChannel);
+
+ SocketAddress remoteAddr;
+ if(fdToRemoteAddress(fd, remoteAddr))
+ {
+ addrToAddressAndChannel(remoteAddr, remoteAddress, remoteChannel);
+ }
+ else
+ {
+ remoteAddress.clear();
+ remoteChannel = -1;
+ }
+}
+
+int
+IceBT::compareAddress(const SocketAddress& addr1, const SocketAddress& addr2)
+{
+ if(addr1.rc_family < addr2.rc_family)
+ {
+ return -1;
+ }
+ else if(addr2.rc_family < addr1.rc_family)
+ {
+ return 1;
+ }
+
+ if(addr1.rc_channel < addr2.rc_channel)
+ {
+ return -1;
+ }
+ else if(addr2.rc_channel < addr1.rc_channel)
+ {
+ return 1;
+ }
+
+ return ::memcmp(&addr1.rc_bdaddr, &addr2.rc_bdaddr, sizeof(DeviceAddress));
+}