summaryrefslogtreecommitdiffstats
path: root/krfb/srvloc
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitbcb704366cb5e333a626c18c308c7e0448a8e69f (patch)
treef0d6ab7d78ecdd9207cf46536376b44b91a1ca71 /krfb/srvloc
downloadtdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.tar.gz
tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krfb/srvloc')
-rw-r--r--krfb/srvloc/Makefile.am17
-rw-r--r--krfb/srvloc/getifaddrs.cpp261
-rw-r--r--krfb/srvloc/getifaddrs.h96
-rw-r--r--krfb/srvloc/kinetinterface.cpp277
-rw-r--r--krfb/srvloc/kinetinterface.h186
-rw-r--r--krfb/srvloc/kinetinterfacewatcher.cpp59
-rw-r--r--krfb/srvloc/kinetinterfacewatcher.h122
-rw-r--r--krfb/srvloc/kserviceregistry.cpp181
-rw-r--r--krfb/srvloc/kserviceregistry.h161
-rw-r--r--krfb/srvloc/uuid.cpp245
-rw-r--r--krfb/srvloc/uuid.h29
11 files changed, 1634 insertions, 0 deletions
diff --git a/krfb/srvloc/Makefile.am b/krfb/srvloc/Makefile.am
new file mode 100644
index 00000000..162e2062
--- /dev/null
+++ b/krfb/srvloc/Makefile.am
@@ -0,0 +1,17 @@
+METASOURCES = AUTO
+
+# Code
+noinst_LTLIBRARIES = libsrvloc.la
+
+libsrvloc_la_SOURCES = kserviceregistry.cpp uuid.cpp \
+ kinetinterface.cpp kinetinterfacewatcher.cpp \
+ getifaddrs.cpp
+
+libsrvloc_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_SLP)
+libsrvloc_la_LDFLAGS = $(all_libraries) -no-undefined
+noinst_HEADERS = kserviceregistry.h uuid.h \
+ getifaddrs.h kinetinterface.h kinetinterfacewatcher.h
+
+# set the include path for X, qt and KDE
+INCLUDES= $(all_includes)
+
diff --git a/krfb/srvloc/getifaddrs.cpp b/krfb/srvloc/getifaddrs.cpp
new file mode 100644
index 00000000..cff9e81e
--- /dev/null
+++ b/krfb/srvloc/getifaddrs.cpp
@@ -0,0 +1,261 @@
+/* getifaddrs -- get names and addresses of all network interfaces
+ Copyright (C) 1999,2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/**
+ * 02-12-26, tim@tjansen.de: put in kde_ namespace, C++ fixes,
+ * included ifreq.h
+ * removed glibc dependencies
+ */
+
+#include "config.h"
+
+#ifndef HAVE_GETIFADDRS
+
+#include "getifaddrs.h"
+#include <net/if.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdio.h>
+
+#ifndef IF_NAMESIZE
+#define IF_NAMESIZE IFNAMSIZ
+#endif
+
+#ifdef SIOCGIFCONF
+
+#define old_siocgifconf 0
+
+static inline void
+__ifreq (struct ifreq **ifreqs, int *num_ifs, int sockfd)
+{
+ int fd = sockfd;
+ struct ifconf ifc;
+ int rq_len;
+ int nifs;
+# define RQ_IFS 4
+
+ if (fd < 0)
+ fd = socket (AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ {
+ *num_ifs = 0;
+ *ifreqs = NULL;
+ return;
+ }
+
+ ifc.ifc_buf = NULL;
+
+ /* We may be able to get the needed buffer size directly, rather than
+ guessing. */
+ if (! old_siocgifconf)
+ {
+ ifc.ifc_buf = NULL;
+ ifc.ifc_len = 0;
+ if (ioctl (fd, SIOCGIFCONF, &ifc) < 0 || ifc.ifc_len == 0)
+ {
+ rq_len = RQ_IFS * sizeof (struct ifreq);
+ }
+ else
+ rq_len = ifc.ifc_len;
+ }
+ else
+ rq_len = RQ_IFS * sizeof (struct ifreq);
+
+ /* Read all the interfaces out of the kernel. */
+ while (1)
+ {
+ ifc.ifc_len = rq_len;
+ ifc.ifc_buf = (char*) realloc (ifc.ifc_buf, ifc.ifc_len);
+ if (ifc.ifc_buf == NULL || ioctl (fd, SIOCGIFCONF, &ifc) < 0)
+ {
+ if (ifc.ifc_buf)
+ free (ifc.ifc_buf);
+
+ if (fd != sockfd)
+ close (fd);
+
+ *num_ifs = 0;
+ *ifreqs = NULL;
+ return;
+ }
+
+ if (!old_siocgifconf || ifc.ifc_len < rq_len)
+ break;
+
+ rq_len *= 2;
+ }
+
+ nifs = ifc.ifc_len / sizeof (struct ifreq);
+
+ if (fd != sockfd)
+ close (fd);
+
+ *num_ifs = nifs;
+ *ifreqs = (ifreq*)realloc (ifc.ifc_buf, nifs * sizeof (struct ifreq));
+}
+
+static inline struct ifreq *
+__if_nextreq (struct ifreq *ifr)
+{
+ return ifr + 1;
+}
+
+static inline void
+__if_freereq (struct ifreq *ifreqs, int num_ifs)
+{
+ free (ifreqs);
+}
+
+/* Create a linked list of `struct kde_ifaddrs' structures, one for each
+ network interface on the host machine. If successful, store the
+ list in *IFAP and return 0. On errors, return -1 and set `errno'. */
+int
+kde_getifaddrs (struct kde_ifaddrs **ifap)
+{
+ /* This implementation handles only IPv4 interfaces.
+ The various ioctls below will only work on an AF_INET socket.
+ Some different mechanism entirely must be used for IPv6. */
+ int fd = socket (AF_INET, SOCK_DGRAM, 0);
+ struct ifreq *ifreqs;
+ int nifs;
+
+ if (fd < 0)
+ return -1;
+
+ __ifreq (&ifreqs, &nifs, fd);
+ if (ifreqs == NULL) /* XXX doesn't distinguish error vs none */
+ {
+ close (fd);
+ return -1;
+ }
+
+ /* Now we have the list of interfaces and each one's address.
+ Put it into the expected format and fill in the remaining details. */
+ if (nifs == 0)
+ *ifap = NULL;
+ else
+ {
+ struct Storage
+ {
+ struct kde_ifaddrs ia;
+ struct sockaddr addr, netmask, broadaddr;
+ char name[IF_NAMESIZE];
+ } *storage;
+ struct ifreq *ifr;
+ int i;
+
+ storage = (Storage*) malloc (nifs * sizeof storage[0]);
+ if (storage == NULL)
+ {
+ close (fd);
+ __if_freereq (ifreqs, nifs);
+ return -1;
+ }
+
+ i = 0;
+ ifr = ifreqs;
+ do
+ {
+ /* Fill in all pointers to the storage we've already allocated. */
+ storage[i].ia.ifa_next = &storage[i + 1].ia;
+ storage[i].ia.ifa_addr = &storage[i].addr;
+ storage[i].ia.ifa_netmask = &storage[i].netmask;
+ storage[i].ia.ifa_broadaddr = &storage[i].broadaddr; /* & dstaddr */
+
+ /* Now copy the information we already have from SIOCGIFCONF. */
+ storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name,
+ sizeof storage[i].name);
+ storage[i].addr = ifr->ifr_addr;
+
+ /* The SIOCGIFCONF call filled in only the name and address.
+ Now we must also ask for the other information we need. */
+
+ if (ioctl (fd, SIOCGIFFLAGS, ifr) < 0)
+ break;
+ storage[i].ia.ifa_flags = ifr->ifr_flags;
+
+ ifr->ifr_addr = storage[i].addr;
+
+ if (ioctl (fd, SIOCGIFNETMASK, ifr) < 0)
+ break;
+ storage[i].netmask = ifr->ifr_netmask;
+
+ if (ifr->ifr_flags & IFF_BROADCAST)
+ {
+ ifr->ifr_addr = storage[i].addr;
+ if (ioctl (fd, SIOCGIFBRDADDR, ifr) < 0)
+ break;
+ storage[i].broadaddr = ifr->ifr_broadaddr;
+ }
+ else if (ifr->ifr_flags & IFF_POINTOPOINT)
+ {
+ ifr->ifr_addr = storage[i].addr;
+ if (ioctl (fd, SIOCGIFDSTADDR, ifr) < 0)
+ break;
+ storage[i].broadaddr = ifr->ifr_dstaddr;
+ }
+ else
+ /* Just 'cause. */
+ memset (&storage[i].broadaddr, 0, sizeof storage[i].broadaddr);
+
+ storage[i].ia.ifa_data = NULL; /* Nothing here for now. */
+
+ ifr = __if_nextreq (ifr);
+ } while (++i < nifs);
+ if (i < nifs) /* Broke out early on error. */
+ {
+ close (fd);
+ free (storage);
+ __if_freereq (ifreqs, nifs);
+ return -1;
+ }
+
+ storage[i - 1].ia.ifa_next = NULL;
+
+ *ifap = &storage[0].ia;
+
+ close (fd);
+ __if_freereq (ifreqs, nifs);
+ }
+
+ return 0;
+}
+
+void
+kde_freeifaddrs (struct kde_ifaddrs *ifa)
+{
+ free (ifa);
+}
+
+#else
+int kde_getifaddrs(struct kde_ifaddrs **) {
+ return 1;
+}
+void kde_freeifaddrs(struct kde_ifaddrs *) {
+}
+struct { } kde_ifaddrs;
+
+#endif
+
+#endif
diff --git a/krfb/srvloc/getifaddrs.h b/krfb/srvloc/getifaddrs.h
new file mode 100644
index 00000000..65d40c01
--- /dev/null
+++ b/krfb/srvloc/getifaddrs.h
@@ -0,0 +1,96 @@
+/* ifaddrs.h -- declarations for getting network interface addresses
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/**
+ * 02-12-26, tim@tjansen.de: added kde_ prefix, fallback-code,
+ * removed glibs dependencies
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <sys/socket.h>
+#include <net/if.h>
+
+#ifdef HAVE_GETIFADDRS
+ #include <ifaddrs.h>
+
+#define kde_getifaddrs(a) getifaddrs(a)
+#define kde_freeifaddrs(a) freeifaddrs(a)
+#define kde_ifaddrs ifaddrs
+
+#else
+
+#ifndef _GETIFADDRS_H
+#define _GETIFADDRS_H
+
+
+#include <sys/socket.h>
+
+/* The `getifaddrs' function generates a linked list of these structures.
+ Each element of the list describes one network interface. */
+struct kde_ifaddrs
+{
+ struct kde_ifaddrs *ifa_next; /* Pointer to the next structure. */
+
+ char *ifa_name; /* Name of this network interface. */
+ unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */
+
+ struct sockaddr *ifa_addr; /* Network address of this interface. */
+ struct sockaddr *ifa_netmask; /* Netmask of this interface. */
+ union
+ {
+ /* At most one of the following two is valid. If the IFF_BROADCAST
+ bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the
+ IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid.
+ It is never the case that both these bits are set at once. */
+ struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */
+ struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */
+ } ifa_ifu;
+ /* These very same macros are defined by <net/if.h> for `struct ifaddr'.
+ So if they are defined already, the existing definitions will be fine. */
+# ifndef ifa_broadaddr
+# define ifa_broadaddr ifa_ifu.ifu_broadaddr
+# endif
+# ifndef ifa_dstaddr
+# define ifa_dstaddr ifa_ifu.ifu_dstaddr
+# endif
+
+ void *ifa_data; /* Address-specific data (may be unused). */
+};
+
+
+/* Create a linked list of `struct kde_ifaddrs' structures, one for each
+ network interface on the host machine. If successful, store the
+ list in *IFAP and return 0. On errors, return -1 and set `errno'.
+
+ The storage returned in *IFAP is allocated dynamically and can
+ only be properly freed by passing it to `freeifaddrs'. */
+extern int kde_getifaddrs (struct kde_ifaddrs **__ifap);
+
+/* Reclaim the storage allocated by a previous `getifaddrs' call. */
+extern void kde_freeifaddrs (struct kde_ifaddrs *__ifa);
+
+#endif
+
+#endif
+
diff --git a/krfb/srvloc/kinetinterface.cpp b/krfb/srvloc/kinetinterface.cpp
new file mode 100644
index 00000000..7ba5c15b
--- /dev/null
+++ b/krfb/srvloc/kinetinterface.cpp
@@ -0,0 +1,277 @@
+/*
+ * Represents an Inet interface
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "kinetinterface.h"
+
+#include "getifaddrs.h"
+
+#include <netinet/in.h>
+#include <ksockaddr.h>
+
+
+class KInetInterfacePrivate {
+public:
+ QString name;
+ int flags;
+ KInetSocketAddress *address;
+ KInetSocketAddress *netmask;
+ KInetSocketAddress *broadcast;
+ KInetSocketAddress *destination;
+
+ KInetInterfacePrivate() :
+ flags(0),
+ address(0),
+ netmask(0),
+ broadcast(0),
+ destination(0) {
+ }
+
+ KInetInterfacePrivate(const QString _name,
+ int _flags,
+ KInetSocketAddress *_address,
+ KInetSocketAddress *_netmask,
+ KInetSocketAddress *_broadcast,
+ KInetSocketAddress *_destination) :
+ name(_name),
+ flags(_flags),
+ address(_address),
+ netmask(_netmask),
+ broadcast(_broadcast),
+ destination(_destination) {
+ }
+
+ ~KInetInterfacePrivate() {
+ if (address)
+ delete address;
+ if (netmask)
+ delete netmask;
+ if (broadcast)
+ delete broadcast;
+ if (destination)
+ delete destination;
+ }
+
+ KInetInterfacePrivate& operator =(const KInetInterfacePrivate& i) {
+ name = i.name;
+ flags = i.flags;
+ if (i.address)
+ address = new KInetSocketAddress(*i.address);
+ else
+ address = 0;
+ if (i.netmask)
+ netmask = new KInetSocketAddress(*i.netmask);
+ else
+ netmask = 0;
+ if (i.broadcast)
+ broadcast = new KInetSocketAddress(*i.broadcast);
+ else
+ broadcast = 0;
+ if (i.destination)
+ destination = new KInetSocketAddress(*i.destination);
+ else
+ destination = 0;
+ return *this;
+ }
+
+};
+
+
+KInetInterface::KInetInterface() :
+ d(0) {
+}
+
+KInetInterface::KInetInterface(const QString &_name,
+ int _flags,
+ KInetSocketAddress *_address,
+ KInetSocketAddress *_netmask,
+ KInetSocketAddress *_broadcast,
+ KInetSocketAddress *_destination) {
+ d = new KInetInterfacePrivate(_name, _flags,
+ _address, _netmask,
+ _broadcast, _destination);
+}
+
+KInetInterface::KInetInterface(const KInetInterface &i) :
+ d(0) {
+ if (!i.d)
+ return;
+
+ d = new KInetInterfacePrivate();
+ *d = *i.d;
+}
+
+KInetInterface::~KInetInterface() {
+ if (d)
+ delete d;
+}
+
+KInetInterface& KInetInterface::operator =(const KInetInterface& i) {
+ if (this == &i)
+ return *this;
+
+ if (d)
+ delete d;
+ d = 0;
+ if (!i.d)
+ return *this;
+
+ d = new KInetInterfacePrivate();
+ *d = *i.d;
+ return *this;
+}
+
+bool KInetInterface::isValid() const {
+ return d == 0;
+}
+
+QString KInetInterface::displayName() const {
+ return d->name;
+}
+
+QString KInetInterface::name() const {
+ return d->name;
+}
+
+int KInetInterface::flags() const {
+ return d->flags;
+}
+
+KInetSocketAddress *KInetInterface::address() const {
+ return d->address;
+}
+
+KInetSocketAddress *KInetInterface::netmask() const {
+ return d->netmask;
+}
+
+KInetSocketAddress *KInetInterface::broadcastAddress() const {
+ return d->broadcast;
+}
+
+KInetSocketAddress *KInetInterface::destinationAddress() const {
+ return d->destination;
+}
+
+KInetSocketAddress *KInetInterface::getPublicInetAddress() {
+ QValueVector<KInetInterface> v = getAllInterfaces(true);
+
+ // TODO: first step: take the default route interface
+
+ // try to find point-2-point interface, because it may be
+ // a dial-up connection. Take it.
+ QValueVector<KInetInterface>::const_iterator it = v.begin();
+ while (it != v.end()) {
+ if (((*it).flags() & (PointToPoint | Up | Running)) &&
+ (!((*it).flags() & Loopback)) &&
+ (*it).address() &&
+ ((*it).address()->family() == AF_INET))
+ return new KInetSocketAddress(*(*it).address());
+ it++;
+ }
+
+ // otherwise, just take the first non-loopback interface
+ it = v.begin();
+ while (it != v.end()) {
+ if (((*it).flags() & (Up | Running)) &&
+ (!((*it).flags() & Loopback)) &&
+ (*it).address() &&
+ ((*it).address()->family() == AF_INET))
+ return new KInetSocketAddress(*(*it).address());
+ it++;
+ }
+
+ // ok, giving up, try to take loopback
+ it = v.begin();
+ while (it != v.end()) {
+ if (((*it).flags() & (Up | Running)) &&
+ (*it).address())
+ return new KInetSocketAddress(*(*it).address());
+ it++;
+ }
+
+ // not even loopback..
+ return 0;
+}
+
+namespace {
+ KInetSocketAddress *createAddress(struct sockaddr *a) {
+ if (!a)
+ return 0;
+ else if (a->sa_family == AF_INET)
+ return new KInetSocketAddress((struct sockaddr_in*) a,
+ sizeof(struct sockaddr_in));
+#ifdef AF_INET6
+ else if (a->sa_family == AF_INET6)
+ return new KInetSocketAddress((struct sockaddr_in6*) a,
+ sizeof(struct sockaddr_in6));
+#endif
+ else
+ return 0;
+ }
+
+ int convertFlags(int flags) {
+ int r = 0;
+ if (flags & IFF_UP)
+ r |= KInetInterface::Up;
+ if (flags & IFF_BROADCAST)
+ r |= KInetInterface::Broadcast;
+ if (flags & IFF_LOOPBACK)
+ r |= KInetInterface::Loopback;
+ if (flags & IFF_POINTOPOINT)
+ r |= KInetInterface::PointToPoint;
+ if (flags & IFF_RUNNING)
+ r |= KInetInterface::Running;
+ if (flags & IFF_MULTICAST)
+ r |= KInetInterface::Multicast;
+
+ return r;
+ }
+}
+
+QValueVector<KInetInterface> KInetInterface::getAllInterfaces(bool includeLoopback) {
+ struct kde_ifaddrs *ads;
+ struct kde_ifaddrs *a;
+ QValueVector<KInetInterface> r;
+ if (kde_getifaddrs(&ads))
+ return r;
+
+ a = ads;
+ while (a) {
+ if ((a->ifa_flags & IFF_LOOPBACK) && !includeLoopback) {
+ a = a->ifa_next;
+ continue;
+ }
+ r.push_back(KInetInterface(QString::fromUtf8(a->ifa_name),
+ convertFlags(a->ifa_flags),
+ createAddress(a->ifa_addr),
+ createAddress(a->ifa_netmask),
+ (a->ifa_flags & IFF_BROADCAST) ?
+ createAddress(a->ifa_broadaddr) : 0,
+ (a->ifa_flags & IFF_POINTOPOINT) ?
+ createAddress(a->ifa_dstaddr) : 0));
+ a = a->ifa_next;
+ }
+
+ kde_freeifaddrs(ads);
+ return r;
+}
+
diff --git a/krfb/srvloc/kinetinterface.h b/krfb/srvloc/kinetinterface.h
new file mode 100644
index 00000000..30005547
--- /dev/null
+++ b/krfb/srvloc/kinetinterface.h
@@ -0,0 +1,186 @@
+/*
+ * Represents an Inet interface
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef KINETINTERFACE_H
+#define KINETINTERFACE_H
+
+#include <qvaluevector.h>
+#include <qcstring.h>
+#include <qstring.h>
+
+
+class KInetInterfacePrivate;
+class KInetSocketAddress;
+
+/**
+ * An Internet (IPv4 or IPv6) network interface.
+ *
+ * Represents a snapshot of the network interface's state. It is
+ * not possible to modify the interface using this class, only
+ * to read it. Note that the interfaces can change it any time
+ * (for example when the internet connection goes up or down),
+ * so when you use it in a server you may want to use it together
+ * with a @ref KInetInterfaceWatcher.
+ * Use @ref getAllInterfaces() to get all interfaces of a system.
+ *
+ * @author Tim Jansen <tim@tjansen.de>
+ * @short Represents an IPv4 or IPv6 Network Interface
+ * @see KInetInterfaceWatcher
+ * @since 3.2
+ */
+class KInetInterface {
+private:
+ KInetInterface(const QString &name,
+ int flags,
+ KInetSocketAddress *address,
+ KInetSocketAddress *netmask,
+ KInetSocketAddress *broadcast,
+ KInetSocketAddress *destination);
+
+public:
+ /**
+ * Default constructor. Creates an uninitialized KInetInterface.
+ * @see isValid()
+ */
+ KInetInterface();
+
+ /**
+ * Copy constructor. Makes a deep copy.
+ * @param i the KInetInterface to copy
+ */
+ KInetInterface(const KInetInterface &i);
+
+ /**
+ * Destructor
+ */
+ virtual ~KInetInterface();
+
+ /**
+ * Assignment, makes a deep copy of @p i.
+ * @param i the KInetInterface to copy
+ * @return this KInetInterface
+ */
+ KInetInterface& operator =(const KInetInterface& i);
+
+ /**
+ * Checks whether the object is valid. Only interfaces that
+ * have been created using the default constructor are invalid.
+ * @return true if valid, false if invalid
+ */
+ bool isValid() const;
+
+ /**
+ * Returns a user-readable name of the interface, if available.
+ * Otherwise it returns the same value as @ref name().
+ * @return the display name of the interface
+ * @see name()
+ */
+ QString displayName() const;
+
+ /**
+ * Returns the name of the interface, e.g. 'eth0'.
+ * @return the name of the interface
+ * @see displayName()
+ */
+ QString name() const;
+
+ /**
+ * Flags describing the interface. These flags
+ * can be ORed.
+ */
+ enum Flags {
+ Up = 1, ///< Interface is up.
+ Broadcast = 2, ///< Broadcast address (@ref broadcastAddress()) is valid..
+ Loopback = 8, ///< Interface is a loopback interface.
+ PointToPoint = 16, ///< Interface is a point-to-point interface.
+ Running = 128, ///< Interface is running.
+ Multicast = 65536 ///< Interface is multicast-capable.
+ };
+
+ /**
+ * A set of ORed flags describing the interface. See
+ * @ref Flags for description of the flags.
+ * @return the ORed @ref Flags of the interface
+ */
+ int flags() const;
+
+ /**
+ * Returns the address of the interface.
+ * The returned object is valid as long as this object
+ * exists.
+ * @return the address of this interface, can be 0 if the interface
+ * does not have an address
+ */
+ KInetSocketAddress *address() const;
+
+ /**
+ * Returns the netmask of the interface.
+ * The returned object is valid as long as this object
+ * exists.
+ * @return the netmask of this interface, can be 0 if the interface
+ * does not have an address
+ */
+ KInetSocketAddress *netmask() const;
+
+ /**
+ * Returns the broadcast address of the interface.
+ * The returned object is valid as long as this object
+ * exists.
+ * @return the broadcast address of this interface. Can be 0 if
+ * the interface is a peer-to-peer interface (like PPP)
+ */
+ KInetSocketAddress *broadcastAddress() const;
+
+ /**
+ * Returns the destination / peer address of the interface.
+ * It is used for peer-to-peer interfaces like PPP.
+ * The returned object is valid as long as this object
+ * exists.
+ * @return the destination address of this interface. Can be 0
+ * if the interface is not a peer-to-peer interface
+ */
+ KInetSocketAddress *destinationAddress() const;
+
+ /**
+ * Tries to guess the public internet address of this computer.
+ * This is not always successful, especially when the computer
+ * is behind a firewall or NAT gateway. In the worst case, it
+ * returns localhost.
+ * @return a KInetAddress object that contains the best match.
+ * The caller takes ownership of the object and is
+ * responsible for freeing it
+ */
+ static KInetSocketAddress *getPublicInetAddress();
+
+ /**
+ * Returns all active interfaces of the system.
+ *
+ * @param includeLoopback if true, include the loopback interface's
+ * name
+ * @return the list of IP addresses
+ */
+ static QValueVector<KInetInterface> getAllInterfaces(bool includeLoopback = false);
+
+private:
+ KInetInterfacePrivate* d;
+};
+
+#endif
diff --git a/krfb/srvloc/kinetinterfacewatcher.cpp b/krfb/srvloc/kinetinterfacewatcher.cpp
new file mode 100644
index 00000000..31b972f5
--- /dev/null
+++ b/krfb/srvloc/kinetinterfacewatcher.cpp
@@ -0,0 +1,59 @@
+/*
+ * Watches Inet interfaces
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "kinetinterfacewatcher.h"
+#include "kinetinterfacewatcher.moc"
+
+class KInetInterfaceWatcherPrivate {
+public:
+ QString interface;
+ int minInterval; // not used yet, but my be when a daemon watches
+
+
+ KInetInterfaceWatcherPrivate(const QString &iface,
+ int minIntv) :
+ interface(iface),
+ minInterval(minIntv) {
+ }
+};
+
+/*
+ * or all network interfaces.
+ * @param interface the name of the interface to watch (e.g.'eth0')
+ * or QString::null to watch all interfaces
+ * @param minInterval the minimum interval between two checks in
+ * seconds. Be careful not to check too often, to
+ * avoid unneccessary wasting of CPU time
+ */
+KInetInterfaceWatcher::KInetInterfaceWatcher(const QString &interface,
+ int minInterval) {
+ d = new KInetInterfaceWatcherPrivate(interface, minInterval);
+}
+
+QString KInetInterfaceWatcher::interface() const {
+ return d->interface;
+}
+
+KInetInterfaceWatcher::~KInetInterfaceWatcher() {
+ delete d;
+}
+
diff --git a/krfb/srvloc/kinetinterfacewatcher.h b/krfb/srvloc/kinetinterfacewatcher.h
new file mode 100644
index 00000000..3651b87d
--- /dev/null
+++ b/krfb/srvloc/kinetinterfacewatcher.h
@@ -0,0 +1,122 @@
+/*
+ * Watches Inet interfaces
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * $Id$
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef KINETINTERFACEWATCHER_H
+#define KINETINTERFACEWATCHER_H
+
+#include <kinetinterface.h>
+#include <qobject.h>
+#include <qvaluevector.h>
+#include <qcstring.h>
+#include <qstring.h>
+
+
+class KInetInterfaceWatcherPrivate;
+
+
+/**
+ * KInetInterfaceWatcher can watch the state of one or all
+ * of the system's network interfaces.
+ * The watcher will emit the signal @ref changed() when an
+ * interface changed or a interface has been added or removed.
+ *
+ * @author Tim Jansen <tim@tjansen.de>
+ * @short Watches the state of the network interfaces
+ * @see KInetInterface
+ * @since 3.2
+ */
+class KInetInterfaceWatcher : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Creates a new KInetInterfaceWatcher. Before you can use it,
+ * you must @ref start() it.
+ *
+ * @param interface the name of the interface to watch (e.g.'eth0')
+ * or QString::null to watch all interfaces
+ * @param minInterval the minimum interval between two checks in
+ * seconds. Be careful not to check too often, to
+ * avoid unneccessary wasting of CPU time
+ */
+ KInetInterfaceWatcher(const QString &interface = QString::null,
+ int minInterval = 60);
+
+ /**
+ * Returns the name of the interface that is being watched.
+ * @return the name of the interface, or QString::null if all
+ * interfaces are watched
+ */
+ QString interface() const;
+
+ /**
+ * Starts the KInetInterfaceWatcher. It watches either one
+ * or all network interfaces. When one of them changed.
+ * it emits a @ref changed() signal.
+ * @param interface the name of the interface to watch (e.g.'eth0')
+ * or QString::null to watch all interfaces
+ * @param minInterval the minimum interval between two checks in
+ * seconds. Be careful not to check too often, to
+ * avoid unneccessary wasting of CPU time
+ * @see changed()
+ * @see stop()
+ */
+ void start(const QString &interface = QString::null,
+ int minInterval = 60);
+
+ /**
+ * Stops watching the interfaces.
+ * @see start()
+ */
+ void stop();
+
+ /**
+ * Destructor
+ */
+ virtual ~KInetInterfaceWatcher();
+
+signals:
+ /**
+ * Emitted when one or more watched interfaces have changed. The
+ * @p interfaceName is the name of the interface being watched, not
+ * the interface that has changed (because more than one interface
+ * may have changed).
+ * A change occurred, when
+ * @li a new interface has been added (when watching a single interface,
+ * only when an interface of that name has been added)
+ * @li an interface has been removed (when watching a single interface,
+ * only when this interface has been removed)
+ * @li the address or netmask of the interface changed
+ *
+ * No change will be emitted when the broadcast address or destination
+ * address has changed.
+ *
+ * @param interfaceName the name of the interface that is watched,
+ * by the emitter, or QString::null if all
+ * interfaces are being watched
+ * @see start()
+ */
+ void changed(QString interfaceName);
+
+private:
+ KInetInterfaceWatcherPrivate* d;
+};
+
+#endif
diff --git a/krfb/srvloc/kserviceregistry.cpp b/krfb/srvloc/kserviceregistry.cpp
new file mode 100644
index 00000000..1a14f9b0
--- /dev/null
+++ b/krfb/srvloc/kserviceregistry.cpp
@@ -0,0 +1,181 @@
+/*
+ * Interface to register SLP services.
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * TODO: see below..
+ */
+
+#include "config.h"
+#include "kserviceregistry.h"
+#include <kdebug.h>
+
+
+#ifdef HAVE_SLP
+#include <slp.h>
+
+class KServiceRegistryPrivate {
+public:
+ KServiceRegistryPrivate(const QString &lang) :
+ m_opened(false),
+ m_lang(lang) {
+ }
+ bool ensureOpen();
+
+ bool m_opened;
+ QString m_lang;
+
+ SLPHandle m_handle;
+ friend void KServiceRegistryRegReport(SLPHandle slp,
+ SLPError errcode,
+ void* cookie);
+ bool m_cbSuccess;
+};
+
+void KServiceRegistryRegReport(SLPHandle,
+ SLPError errcode,
+ void* cookie) {
+ KServiceRegistryPrivate *s = (KServiceRegistryPrivate*) cookie;
+ s->m_cbSuccess = (errcode == SLP_OK);
+ if (errcode < 0)
+ kdDebug() << "KServiceRegistry: error in callback:" << errcode <<endl;
+}
+
+
+KServiceRegistry::KServiceRegistry(const QString &lang) {
+ d = new KServiceRegistryPrivate(lang);
+}
+
+KServiceRegistry::~KServiceRegistry() {
+ if (d->m_opened)
+ SLPClose(d->m_handle);
+ delete d;
+}
+
+bool KServiceRegistryPrivate::ensureOpen() {
+ SLPError e;
+
+ if (m_opened)
+ return true;
+
+ e = SLPOpen(m_lang.latin1(), SLP_FALSE, &m_handle);
+ if (e != SLP_OK) {
+ kdDebug() << "KServiceRegistry: error while opening:" << e <<endl;
+ return false;
+ }
+ m_opened = true;
+ return true;
+}
+
+bool KServiceRegistry::available() {
+ return d->ensureOpen();
+}
+
+bool KServiceRegistry::registerService(const QString &serviceURL,
+ QString attributes,
+ unsigned short lifetime) {
+ if (!d->ensureOpen())
+ return false;
+
+ d->m_cbSuccess = true;
+ SLPError e = SLPReg(d->m_handle,
+ serviceURL.latin1(),
+ lifetime > 0 ? lifetime : SLP_LIFETIME_MAXIMUM,
+ 0,
+ attributes.isNull() ? "" : attributes.latin1(),
+ SLP_TRUE,
+ KServiceRegistryRegReport,
+ d);
+ if (e != SLP_OK) {
+ kdDebug() << "KServiceRegistry: error in registerService:" << e <<endl;
+ return false;
+ }
+ return d->m_cbSuccess;
+}
+
+bool KServiceRegistry::registerService(const QString &serviceURL,
+ QMap<QString,QString> attributes,
+ unsigned short lifetime) {
+ if (!d->ensureOpen())
+ return false;
+// TODO: encode strings in map?
+ QString s;
+ QMap<QString,QString>::iterator it = attributes.begin();
+ while (it != attributes.end()) {
+ if (!s.isEmpty())
+ s += ",";
+ s += QString("(%1=%2)").arg(it.key()).arg(it.data());
+ it++;
+ }
+ return registerService(serviceURL, s, lifetime);
+}
+
+void KServiceRegistry::unregisterService(const QString &serviceURL) {
+ if (!d->m_opened)
+ return;
+ SLPDereg(d->m_handle, serviceURL.latin1(),
+ KServiceRegistryRegReport,
+ d);
+}
+
+QString KServiceRegistry::encodeAttributeValue(const QString &value) {
+ char *n;
+ if (SLPEscape(value.latin1(), &n, SLP_TRUE) == SLP_OK) {
+ QString r(n);
+ SLPFree(n);
+ return r;
+ }
+ return QString::null;
+}
+
+#else
+
+KServiceRegistry::KServiceRegistry(const QString &lang) :
+ d(0) {
+}
+
+KServiceRegistry::~KServiceRegistry() {
+}
+
+bool KServiceRegistry::available() {
+ return false;
+}
+
+bool KServiceRegistry::registerService(const QString &, QString, unsigned short ) {
+ return false;
+}
+
+bool KServiceRegistry::registerService(const QString &, QMap<QString,QString>, unsigned short) {
+ return false;
+}
+
+void KServiceRegistry::unregisterService(const QString &) {
+}
+
+QString KServiceRegistry::encodeAttributeValue(const QString &value) {
+ return value;
+}
+
+#endif
+
+QString KServiceRegistry::createCommaList(const QStringList &values) {
+ return values.join(",");
+}
+
+
+
diff --git a/krfb/srvloc/kserviceregistry.h b/krfb/srvloc/kserviceregistry.h
new file mode 100644
index 00000000..f017b129
--- /dev/null
+++ b/krfb/srvloc/kserviceregistry.h
@@ -0,0 +1,161 @@
+/*
+ * Interface to register SLP services.
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * TODO: put private variables and SLP-dependencies in private class
+ */
+
+#ifndef __KSERVICEREGISTRY_H
+#define __KSERVICEREGISTRY_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+class KServiceRegistryPrivate;
+
+/**
+ * KServiceRegistry allows you to announce your service using SLP (RFC 2608).
+ *
+ * Use KServiceRegistry to announce a service. The service will be valid
+ * until its lifespan ends, you unregister it or delete the KServiceRegistry,
+ * whatever comes first.
+ * A service will be described using a Service URL and an optional list of
+ * attributes. The syntax for a simple Service URL is
+ * <pre>
+ * service:%srvtype%://%addrspec%
+ * </pre>
+ * where "%srvtype%" specifies the protocol and "%addrspec5" the address.
+ * Examples of valid Service URLs are "service:http://www.kde.org",
+ * "service:lpr://printer.example.org/myqueure" and
+ * "service:http://your.server.org:8080".
+ * To provide more information about your service than just the protocol,
+ * port and address you can use abstract service types.
+ * A Service URL that uses an abstract service type has the form
+ * <pre>
+ * service:%abstract-type%:%concrete-type%
+ * </pre>
+ * where %abstract-type% describes the kind of service and %concrete-type% specifies
+ * the protocol and address. Examples are
+ * "service:printer:lpr://printer.example.com/lp0" and
+ * "service:printer:ipp://printer.example.com/".
+ * Note that you cannot invent you own types but only take those that are
+ * registered at IANA. To create your own service type you must become a naming
+ * authority. Then you can use service types of the form
+ * "%srvtype%.%naming-authority%". Assuming that "kde" is the id of a
+ * IANA-registered naming authority, a valid Service URL would be
+ * "service:weatherp.kde://weather.example.com". You can find more information
+ * about Service URLs in the IETF RFCs 2608 and 3224.
+ * Additionally each service can have one or more attributes to carry
+ * additional information about the service. Attributes are a simple pair of
+ * strings, one for the attributes name and one for the value. They can be
+ * used, for example, to describe the type of a printer or the email address
+ * of an administrator.
+ *
+ * Service templates can be used to describe an abstract type, including the
+ * syntax of the concrete type and the attributes. The use of service
+ * templates is described in RFC 2609, you can find the existing service
+ * templates at http://www.iana.org/assignments/svrloc-templates.htm .
+ *
+ * Example:
+ * <pre>
+ * KServiceRegistry ksr;
+ * KInetAddress kia = KInetAddress->getLocalAddress();
+ * ksr.registerService(QString("service:remotedesktop.kde:vnc://%1:0").arg(kia->nodeName()),
+ * "(type=shared)");
+ * delete kia;
+ * </pre>
+ *
+ * @version $Id$
+ * @author Tim Jansen, tim@tjansen.de
+ */
+class KServiceRegistry {
+ public:
+ /**
+ * Creates a new service registration instance for the given
+ * language.
+ * @param lang the language as two letter code, or QString::null for the
+ * system default
+ */
+ KServiceRegistry(const QString &lang = QString::null);
+ virtual ~KServiceRegistry();
+
+ /**
+ * Returns true if service registration is generally possible.
+ * Reasons for a failure could be that the SLP libraries are not
+ * installed or no SA daemon (slpd) is installed
+ * @return true if service registration seems to be possible
+ */
+ bool available();
+
+ /**
+ * Creates a comma-separated string of lists, as required by many functions.
+ * @param map the items of this list will be converted
+ * @return the comma-separated list
+ */
+ static QString createCommaList(const QStringList &values);
+
+ /**
+ * Encodes an QString for use as a attribute value. This will escape
+ * all characters that are not allowed. This method is only available
+ * when a SLP library is available, otherwise it will return the
+ * given value.
+ * @param value the value string to encode
+ * @return the encoded value string
+ */
+ static QString encodeAttributeValue(const QString &value);
+
+ /**
+ * Registers the given service.
+ * @param serviceURL the service URL to register
+ * @param attributes a list of the attributes to register, encoded in
+ * the format "(attr1=val1),(attr2=val2),(attr3=val3)"
+ * Use an empty string if you dont want to set attributes
+ * @param lifetime the lifetime of the service in seconds, or 0 for infinite
+ * @return true if successful, false otherwise. False usually means that no
+ * SA daemon (slpd) is running.
+ */
+ bool registerService(const QString &serviceURL,
+ QString attributes = QString::null,
+ unsigned short lifetime = 0);
+
+ /**
+ * Registers the given service.
+ * @param serviceURL the service URL to register
+ * @param attributes a map of all attributes
+ * @param lifetime the lifetime of the service in seconds, or 0 for infinite
+ * @return true if successful, false otherwise. False usually means that no
+ * SA daemon is running (slpd).
+ */
+ bool registerService(const QString &serviceURL,
+ QMap<QString,QString> attributes,
+ unsigned short lifetime = 0);
+
+ /**
+ * Unregisters the given service.
+ * @param serviceURL the service URL to unregister
+ */
+ void unregisterService(const QString &serviceURL);
+
+ private:
+ KServiceRegistryPrivate *d;
+};
+
+#endif
diff --git a/krfb/srvloc/uuid.cpp b/krfb/srvloc/uuid.cpp
new file mode 100644
index 00000000..61f78d86
--- /dev/null
+++ b/krfb/srvloc/uuid.cpp
@@ -0,0 +1,245 @@
+/*
+ * libuuid - library for generating UUIDs
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
+ * Copyright (C) 2002 Tim Jansen
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU
+ * Library General Public License.
+ * %End-Header%
+ *
+ * 2002-12-15, tim@tjansen.de:
+ * merged all *.c files,
+ * replaced all function that are not needed to generate a time uuid,
+ * added createUUID()
+ */
+
+#include "uuid.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+#ifndef _SVID_SOURCE
+#define _SVID_SOURCE
+#endif
+
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_SRANDOM
+#define srand(x) srandom(x)
+#define rand() random()
+#endif
+
+typedef unsigned char uuid_t[16];
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+
+struct uuid {
+ __u32 time_low;
+ __u16 time_mid;
+ __u16 time_hi_and_version;
+ __u16 clock_seq;
+ __u8 node[6];
+};
+
+void uuid_unpack(const uuid_t in, struct uuid *uu)
+{
+ const __u8 *ptr = in;
+ __u32 tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_low = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_mid = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->time_hi_and_version = tmp;
+
+ tmp = *ptr++;
+ tmp = (tmp << 8) | *ptr++;
+ uu->clock_seq = tmp;
+
+ memcpy(uu->node, ptr, 6);
+}
+
+static int get_random_fd(void)
+{
+ struct timeval tv;
+ static int fd = -2;
+ int i;
+
+ if (fd == -2) {
+ gettimeofday(&tv, 0);
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+ srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
+ }
+ /* Crank the random number generator a few times */
+ gettimeofday(&tv, 0);
+ for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+ rand();
+ return fd;
+}
+
+
+/*
+ * Generate a series of random bytes. Use /dev/urandom if possible,
+ * and if not, use srandom/random.
+ */
+static void get_random_bytes(void *buf, int nbytes)
+{
+ int i, fd = get_random_fd();
+ int lose_counter = 0;
+ char *cp = (char *) buf;
+
+ if (fd >= 0) {
+ while (nbytes > 0) {
+ i = read(fd, cp, nbytes);
+ if (i <= 0) {
+ if (lose_counter++ > 16)
+ break;
+ continue;
+ }
+ nbytes -= i;
+ cp += i;
+ lose_counter = 0;
+ }
+ }
+
+ /* XXX put something better here if no /dev/random! */
+ for (i = 0; i < nbytes; i++)
+ *cp++ = rand() & 0xFF;
+ return;
+}
+
+
+/* Assume that the gettimeofday() has microsecond granularity */
+#define MAX_ADJUSTMENT 10
+
+static int get_clock(__u32 *clock_high, __u32 *clock_low, __u16 *ret_clock_seq)
+{
+ static int adjustment = 0;
+ static struct timeval last = {0, 0};
+ static __u16 clock_seq;
+ struct timeval tv;
+ unsigned long long clock_reg;
+
+try_again:
+ gettimeofday(&tv, 0);
+ if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
+ get_random_bytes(&clock_seq, sizeof(clock_seq));
+ clock_seq &= 0x1FFF;
+ last = tv;
+ last.tv_sec--;
+ }
+ if ((tv.tv_sec < last.tv_sec) ||
+ ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec < last.tv_usec))) {
+ clock_seq = (clock_seq+1) & 0x1FFF;
+ adjustment = 0;
+ last = tv;
+ } else if ((tv.tv_sec == last.tv_sec) &&
+ (tv.tv_usec == last.tv_usec)) {
+ if (adjustment >= MAX_ADJUSTMENT)
+ goto try_again;
+ adjustment++;
+ } else {
+ adjustment = 0;
+ last = tv;
+ }
+
+ clock_reg = tv.tv_usec*10 + adjustment;
+ clock_reg += ((unsigned long long) tv.tv_sec)*10000000;
+ clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000;
+
+ *clock_high = clock_reg >> 32;
+ *clock_low = clock_reg;
+ *ret_clock_seq = clock_seq;
+ return 0;
+}
+
+static void uuid_pack(const struct uuid *uu, uuid_t ptr)
+{
+ __u32 tmp;
+ unsigned char *out = ptr;
+
+ tmp = uu->time_low;
+ out[3] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[2] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[1] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[0] = (unsigned char) tmp;
+
+ tmp = uu->time_mid;
+ out[5] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[4] = (unsigned char) tmp;
+
+ tmp = uu->time_hi_and_version;
+ out[7] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[6] = (unsigned char) tmp;
+
+ tmp = uu->clock_seq;
+ out[9] = (unsigned char) tmp;
+ tmp >>= 8;
+ out[8] = (unsigned char) tmp;
+
+ memcpy(out+10, uu->node, 6);
+}
+
+static void uuid_generate_time(uuid_t out)
+{
+ static unsigned char node_id[6];
+ struct uuid uu;
+ __u32 clock_mid;
+
+ get_random_bytes(node_id, 6);
+ get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
+ uu.clock_seq |= 0x8000;
+ uu.time_mid = (__u16) clock_mid;
+ uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
+ memcpy(uu.node, node_id, 6);
+ uuid_pack(&uu, out);
+}
+
+static void uuid_unparse(const uuid_t uu, char *out)
+{
+ struct uuid uuid;
+
+ uuid_unpack(uu, &uuid);
+ sprintf(out,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+ uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+ uuid.node[0], uuid.node[1], uuid.node[2],
+ uuid.node[3], uuid.node[4], uuid.node[5]);
+}
+
+QString createUUID() {
+ char s[37];
+ uuid_t uu;
+ uuid_generate_time(uu);
+ uuid_unparse(uu, s);
+ return QString(s);
+}
+
diff --git a/krfb/srvloc/uuid.h b/krfb/srvloc/uuid.h
new file mode 100644
index 00000000..c566a7db
--- /dev/null
+++ b/krfb/srvloc/uuid.h
@@ -0,0 +1,29 @@
+/*
+ * Micro UUID library, based on libuuid
+ * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UUID_H
+#define UUID_H
+
+#include <qstring.h>
+
+QString createUUID();
+
+#endif /* UUID_H */