1
0
mirror of https://invent.kde.org/network/krfb synced 2024-07-05 09:28:35 +00:00

Register one SLP URL per interface (instead of guessing one LAN

interface address). Added service id attribute containing a UUID
to identify a host with several interfaces. KInetAddress update.

svn path=/trunk/kdenetwork/krfb/; revision=194009
This commit is contained in:
Tim Jansen 2002-12-15 04:08:40 +00:00
parent 12a0b19492
commit b6c4365d2d
11 changed files with 473 additions and 195 deletions

View File

@ -20,6 +20,7 @@
#include "kinetd.moc"
#include "kinetaddr.h"
#include "kuser.h"
#include "uuid.h"
#include <qregexp.h>
#include <kservicetype.h>
#include <kdebug.h>
@ -40,6 +41,7 @@ PortListener::PortListener(KService::Ptr s,
m_config(config),
m_srvreg(srvreg)
{
m_uuid = createUUID();
loadConfig(s);
if (m_valid && m_enabled)
@ -206,16 +208,21 @@ int PortListener::port() {
return m_port;
}
QString PortListener::processServiceTemplate(const QString &a) {
KInetAddress *kia = KInetAddress::getLocalAddress();
QString hostName = kia->nodeName();
delete kia;
KUser u;
QString x = a; // replace does not work in const QString. Why??
return x.replace(QRegExp("%h"), KServiceRegistry::encodeAttributeValue(hostName))
.replace(QRegExp("%p"), QString::number(m_port))
.replace(QRegExp("%u"), KServiceRegistry::encodeAttributeValue(u.loginName()))
.replace(QRegExp("%f"), KServiceRegistry::encodeAttributeValue(u.fullName()));
QStringList PortListener::processServiceTemplate(const QString &a) {
QStringList l;
QValueVector<KInetAddress> v = KInetAddress::getAllAddresses();
QValueVector<KInetAddress>::Iterator it = v.begin();
while (it != v.end()) {
QString hostName = (*(it++)).nodeName();
KUser u;
QString x = a; // replace does not work in const QString. Why??
l.append(x.replace(QRegExp("%h"), KServiceRegistry::encodeAttributeValue(hostName))
.replace(QRegExp("%p"), QString::number(m_port))
.replace(QRegExp("%u"), KServiceRegistry::encodeAttributeValue(u.loginName()))
.replace(QRegExp("%i"), KServiceRegistry::encodeAttributeValue(m_uuid))
.replace(QRegExp("%f"), KServiceRegistry::encodeAttributeValue(u.fullName())));
}
return l;
}
bool PortListener::setPort(int port, int autoPortRange) {
@ -292,17 +299,25 @@ void PortListener::setServiceRegistrationEnabledInternal(bool e) {
return;
if (m_enabled && e) {
m_registeredServiceURL = processServiceTemplate(m_serviceURL);
m_serviceRegistered = m_srvreg->registerService(
m_registeredServiceURL,
processServiceTemplate(m_serviceAttributes),
m_serviceLifetime);
if (!m_serviceRegistered)
kdDebug(7021) << "Failure registering SLP service (no slpd running?)"<< endl;
m_registeredServiceURLs = processServiceTemplate(m_serviceURL);
QStringList attributes = processServiceTemplate(m_serviceAttributes);
QStringList::Iterator it = m_registeredServiceURLs.begin();
QStringList::Iterator it2 = attributes.begin();
while ((it != m_registeredServiceURLs.end()) &&
(it2 != attributes.end())) {
if (!m_srvreg->registerService(
*(it++),
*(it2++),
m_serviceLifetime))
kdDebug(7021) << "Failure registering SLP service (no slpd running?)"<< endl;
}
m_serviceRegistered = true;
// make lifetime 30s shorter, because the timeout is not precise
m_slpLifetimeEnd = QDateTime::currentDateTime().addSecs(m_serviceLifetime-30);
} else {
m_srvreg->unregisterService(m_registeredServiceURL);
QStringList::Iterator it = m_registeredServiceURLs.begin();
while (it != m_registeredServiceURLs.end())
m_srvreg->unregisterService(*(it++));
m_serviceRegistered = false;
}
}

View File

@ -35,7 +35,8 @@ class PortListener : public QObject {
private:
bool m_valid;
QString m_serviceName;
QString m_serviceURL, m_serviceAttributes, m_registeredServiceURL;
QString m_serviceURL, m_serviceAttributes;
QStringList m_registeredServiceURLs;
int m_serviceLifetime;
int m_port;
int m_portBase, m_autoPortRange;
@ -47,6 +48,7 @@ private:
bool m_serviceRegistered, m_registerService;
QDateTime m_expirationTime;
QDateTime m_slpLifetimeEnd;
QString m_uuid;
KServerSocket *m_socket;
KProcess m_process;
@ -74,7 +76,7 @@ public:
QDateTime serviceLifetimeEnd();
bool isEnabled();
int port();
QString processServiceTemplate(const QString &a);
QStringList processServiceTemplate(const QString &a);
bool setPort(int port = -1, int autoProbeRange = 1);
void refreshRegistration();

View File

@ -71,11 +71,14 @@ Type=QString
Type=bool
# if set, kinetd will register the given URL at the local SLP SA while
# the port is open. The following strings will be substituted:
# the port is open. It will register one URL for each IP address of the
# host.
# The following strings will be substituted:
# %h with the local IP address
# %p with the port number
# %u with the user's login name
# %f with the user's full name
# %i with a UUID thats identical in all URLs of this service
[PropertyDef::X-KDE-KINETD-serviceURL]
Type=QString
@ -85,6 +88,7 @@ Type=QString
# %p with the port number
# %u with the user's login name
# %f with the user's full name
# %i with a UUID thats identical in all URLs of this service
[PropertyDef::X-KDE-KINETD-serviceAttributes]
Type=QString

View File

@ -260,9 +260,8 @@ void Configuration::refreshTimeout() {
QString Configuration::hostname() const
{
KInetAddress *a = KInetAddress::getPrivateInetAddress();
QString hostName = a->nodeName();
delete a;
KInetAddress a = KInetAddress::getPublicInetAddress();
QString hostName = a.nodeName();
return hostName;
}

View File

@ -11,8 +11,8 @@ X-KDE-KINETD-autoPortRange=100
X-KDE-KINETD-enabled=false
X-KDE-KINETD-argument=--kinetd
X-KDE-KINETD-multiInstance=false
X-KDE-KINETD-serviceURL=service:remotedesktop.kde:vnc://%h:%p;(type=shared),(username=%u),(fullname=%f)
X-KDE-KINETD-serviceAttributes=(type=shared),(username=%u),(fullname=%f)
X-KDE-KINETD-serviceURL=service:remotedesktop.kde:vnc://%h:%p;(type=shared),(username=%u),(fullname=%f),(serviceid=%i)
X-KDE-KINETD-serviceAttributes=(type=shared),(username=%u),(fullname=%f),(serviceid=%i)
X-KDE-KINETD-serviceLifetime=1200
Name=KRfb Desktop Sharing

View File

@ -4,10 +4,10 @@ METASOURCES = AUTO
noinst_LTLIBRARIES = libsrvloc.la
libsrvloc_la_SOURCES = kinetaddr.cpp kinetaddr_ipfinder.cpp \
kserviceregistry.cpp kuser.cpp
kserviceregistry.cpp kuser.cpp uuid.cpp
libsrvloc_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_SLP)
libsrvloc_la_LDFLAGS = $(all_libraries) -no-undefined
noinst_HEADERS = kinetaddr.h kserviceregistry.h kuser.h
noinst_HEADERS = kinetaddr.h kserviceregistry.h kuser.h uuid.h
# set the include path for X, qt and KDE
INCLUDES= $(all_includes)

View File

@ -22,16 +22,14 @@
* Boston, MA 02111-1307, USA.
**/
#include "kinetaddress.h"
#include <config.h>
#include <limits.h>
#include <string.h>
#include <kdebug.h>
#include <klocale.h>
#include "kinetaddr.h"
#include <netdb.h>
#if defined(__osf__) && defined(AF_INET6)
@ -65,6 +63,19 @@ public:
};
/**
* Functions defined in kinetaddr_ipfinder.cpp:
*/
QMap<QString,QString> kinetaddr_getAllInterfaces(bool includeLoopback);
KInetAddress::KInetAddress() :
d(new KInetAddressPrivate)
{
}
KInetAddress::KInetAddress(const KInetAddress &other) :
d(new KInetAddressPrivate)
{
@ -114,6 +125,15 @@ KInetAddress::KInetAddress(const QString &host) :
}
KInetAddress& KInetAddress::operator =(const KInetAddress& a) {
d->sockfamily = a.d->sockfamily;
memcpy(&d->in, &a.d->in, sizeof(d->in));
#ifdef AF_INET6
memcpy(&d->in6, &a.d->in6, sizeof(d->in6));
#endif
return *this;
}
KInetAddress::~KInetAddress()
{
delete d;
@ -152,7 +172,7 @@ QString KInetAddress::nodeName() const
#endif
else {
kdWarning() << "KInetAddress::nodeName() called on uninitialized class\n";
return i18n("<empty>");
return QString::null;
}
return QString::fromLatin1(buf); // FIXME! What's the encoding?
@ -176,4 +196,41 @@ bool KInetAddress::areEqual(const KInetAddress &a1, const KInetAddress &a2)
return true;
}
KInetAddress KInetAddress::getPublicInetAddress() {
KInetAddress kia("localhost");
QMap<QString,KInetAddress> list = getAllInterfaces(false);
QMap<QString,KInetAddress>::iterator it = list.begin();
while (it != list.end()) {
QString ifc = it.key();
kia = it.data();
if (ifc.startsWith("ppp"))
return kia;
if (ifc.startsWith("ippp"))
return kia;
it++;
}
return kia;
}
QValueVector<KInetAddress> KInetAddress::getAllAddresses(bool includeLoopback) {
QValueVector<KInetAddress> list;
QMap<QString,KInetAddress> map = getAllInterfaces(includeLoopback);
QMap<QString,KInetAddress>::iterator it = map.begin();
while (it != map.end()) {
list.push_back(it.data());
it++;
}
return list;
}
QMap<QString,KInetAddress> KInetAddress::getAllInterfaces(bool includeLoopback) {
QMap<QString,KInetAddress> map;
QMap<QString,QString> l = kinetaddr_getAllInterfaces(includeLoopback);
QMap<QString,QString>::iterator it = l.begin();
while (it != l.end()) {
map[it.key()] = KInetAddress(it.data());
it++;
}
return map;
}

View File

@ -34,6 +34,8 @@
#endif
#include <qobject.h>
#include <qmap.h>
#include <qvaluevector.h>
#include <qcstring.h>
#include <qstring.h>
@ -45,19 +47,26 @@ class KInetAddressPrivate;
* An Inet (IPv4 or IPv6) address.
*
* This class represents an internet (IPv4 or IPv6) address. The difference
* between KInetAddress and KInetSocketAddress is that the socket address
* consists of the address and the port, KInetAddress peresents only the
* address itself.
* between @ref KInetAddress and @ref KInetSocketAddress is that the socket
* address consists of the address and the port, KInetAddress represents
* only the address itself.
*
* @author Tim Jansen <tim@tjansen.de>
* @short an Internet Address
* @short Represents an Internet Address
* @since 3.2
*/
class KInetAddress {
public:
/**
* Copy constructor
* Default constructor. Creates an uninitialized KInetAddress.
*/
KInetAddress(const KInetAddress&);
KInetAddress();
/**
* Copy constructor
* @param a the KInetAddress to copy
*/
KInetAddress(const KInetAddress &a);
/**
* Creates an IPv4 socket from in_addr
@ -88,30 +97,59 @@ public:
virtual ~KInetAddress();
/**
* Returns a text representation of the host address
* Assignment, makes a deep copy of @p a.
* @param a the KInetAddress to copy
* @return this KInetAddress
*/
KInetAddress& operator =(const KInetAddress& a);
/**
* Returns a text representation of the host address.
* @return a text representation of the host address, or
* QString::null if created using the default
* constructor
*/
virtual QString nodeName() const;
/**
* Checks whether this KInetAddress equals the @p other.
* @param other the other KInetAddress to compare
* @return true if both addresses equal
* @see areEqual()
*/
bool isEqual(const KInetAddress* other) const
{ return areEqual(*this, *other); }
/**
* Checks whether this KInetAddress equals the @p other.
* @param other the other KInetAddress to compare
* @return true if both addresses equal
* @see areEqual()
*/
bool operator==(const KInetAddress& other) const
{ return areEqual(*this, other); }
/**
* Checks whether the given KInetAddresses are equal.
* @param a1 the first KInetAddress to compare
* @param a2 the second KInetAddress to compare
* @return true if both addresses equal
* @see isEqual()
*/
static bool areEqual(const KInetAddress &a1, const KInetAddress &a2);
/**
* Returns the in_addr structure. The pointer is valid as long as
* the KInetAddress object lives.
* This will be NULL if this is not a v4 address.
* Returns the in_addr structure.
* @return the in_addr structure, or 0 if this is not a v4 address.
* The pointer is valid as long as the KInetAddress object lives.
* @see addressV6
*/
const struct in_addr* addressV4() const;
/**
* Returns the in6_addr structure. The pointer is valid as long as
* the KInetAddress object lives.
* This will be NULL if this is not a v6 address.
* Returns the in6_addr structure.
* @return the in_addr structure, or 0 if this is not a v6 address.
* The pointer is valid as long as the KInetAddress object lives.
* @see addressV4
*/
const struct in6_addr* addressV6() const;
@ -123,29 +161,31 @@ public:
{ return addressV6(); }
/**
* Returns an address that can be used for communication with
* other computers on the internet.
* Note that the returned address is not always a real
* internet address, because the computer couble be unable to connect
* to the internet or is behind a NAT gateway.
* In the worst case you will get the address of the local loopback
* interface.
* The user is responsible for freeing the object.
* @return a new KInetAddress object that contains the address
* 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
*/
static KInetAddress* getPrivateInetAddress();
static KInetAddress getPublicInetAddress();
/**
* Returns the address of the interface that should be used
* to announce local services.
* Note that the returned address is not always a real internet address,
* because the computer may be behind a NAT gateway, or
* it is no connected to the internet. In the worst case you
* will get the address of the local loopback interface.
* The user is responsible for freeing the object.
* @return a new KInetAddress object that contains the address
* Returns all active IP addresses that can be used to reach this
* system.
* @param includeLoopback if true, include the loopback interface's
* name
* @return the list of IP addresses
*/
static KInetAddress* getLocalAddress();
static QValueVector<KInetAddress> getAllAddresses(bool includeLoopback = false);
/**
* Returns all active interfaces as name/IP address pairs.
* @param includeLoopback if true, include the loopback interface's
* name
* @return the map of interfaces. The QString contains the name (like 'eth0'
* or 'ppp1'), KInetAddress the address
*/
static QMap<QString,KInetAddress> getAllInterfaces(bool includeLoopback = false);
private:

View File

@ -1,8 +1,8 @@
/*
* Find network adapter's IP address
* Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
* based on code from KInetSocketAddress:
* Copyright (C) 2000,2001 Thiago Macieira <thiagom@mail.com>
* This code is based on KPhone/libdissipate's SIPUtil class.
* Copyright (c) 2000 Billy Biggs <bbiggs@div8.net>
*
* $Id$
*
@ -23,18 +23,7 @@
**/
#include <config.h>
#include <kdebug.h>
#include "kinetaddr.h"
/*
* This code is based on KPhone/libdissipate's SIPUtil class.
* Copyright (c) 2000 Billy Biggs <bbiggs@div8.net>
*
* The code is far from being perfect, and gateway detection only works on
* Linux. Later there should be a way to configure the addresses using
* a KCM.
*
*/
#include <qmap.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -61,136 +50,34 @@
#endif
static const char *local_address = NULL;
static const char *inet_address = NULL;
/* max number of network interfaces*/
#define MAX_IF 8
/* Path to the route entry in proc filesystem */
#define PROCROUTE "/proc/net/route"
#ifndef SIOCGIFCOUNT
#define SIOCGIFCOUNT 0x8935
#endif
char iface[16];
#define MAX_IF 16
/* This searches the proc routing entry for the interface the default gateway
 * is on, and returns the name of that interface.
 */
char *getdefaultdev()
QMap<QString,QString> kinetaddr_getAllInterfaces(bool includeLoopback)
{
FILE *fp = fopen( PROCROUTE, "r");
char buff[4096], gate_addr[128], net_addr[128];
char mask_addr[128];
int irtt, window, mss, num, metric, refcnt, use;
unsigned int iflags;
char i;
if( !fp ) {
return NULL;
}
i=0;
// cruise through the list, and find the gateway interface
while( fgets(buff, 1023, fp) ) {
num = sscanf(buff, "%15s %127s %127s %X %d %d %d %127s %d %d %d\n",
iface, net_addr, gate_addr, &iflags, &refcnt, &use, &metric,
mask_addr, &mss, &window, &irtt);
i++;
if( i == 1) continue;
if( iflags & RTF_GATEWAY )
return iface;
}
fclose(fp);
/* didn't find a default gateway */
return NULL;
}
static void findAddresses( void )
{
int sock, err, if_count, i, j = 0;
QMap<QString,QString> map;
int sock, err, if_count, i;
struct ifconf netconf;
char buffer[32*MAX_IF];
char if_name[10][21];
char if_addr[10][21];
char *default_ifName;
netconf.ifc_len = 32 * MAX_IF;
netconf.ifc_buf = buffer;
sock=socket( PF_INET, SOCK_DGRAM, 0 );
err=ioctl( sock, SIOCGIFCONF, &netconf );
if ( err < 0 )
kdDebug() << "KInetAddress: Error in ioctl: "<<errno<<"." << endl;
close( sock );
sock = socket(PF_INET, SOCK_DGRAM, 0);
err = ioctl(sock, SIOCGIFCONF, &netconf);
if (err < 0)
return map;
close(sock);
if_count = netconf.ifc_len / 32;
for( i = 0; i < if_count; i++ ) {
if( strcmp( netconf.ifc_req[i].ifr_name, "lo" ) != 0 ) {
strncpy( if_name[j], netconf.ifc_req[i].ifr_name, 20 );
strncpy( if_addr[j], inet_ntoa(((struct sockaddr_in*)(&netconf.ifc_req[i].ifr_addr))->sin_addr), 20 );
j++;
for(i = 0; i < if_count; i++) {
if(includeLoopback ||
(strcmp( netconf.ifc_req[i].ifr_name, "lo" ) != 0)) {
map.insert(netconf.ifc_req[i].ifr_name,
inet_ntoa(((struct sockaddr_in*)(&netconf.ifc_req[i].ifr_addr))->sin_addr));
}
}
if(j == 0) {
local_address = "localhost";
inet_address = "localhost";
return;
}
if(j == 1) {
local_address = strdup( if_addr[0] );
inet_address = local_address;
return;
}
/* take default gateway interface for inet address if available */
default_ifName = getdefaultdev();
if( default_ifName) {
for( i = 0; i < j; i++ ) {
if( strcmp(if_name[i], default_ifName) == 0 ) {
inet_address = strdup(if_addr[i]);
break;
}
}
}
/* use first ppp connection for inet, first non-ppp for local */
for( i = 0; i < j; i++ ) {
if((strncmp(if_name[i], "ppp", 3) == 0) ||
(strncmp(if_name[i], "ippp", 4) == 0)) {
if (!inet_address) {
inet_address = strdup(if_addr[i]);
}
}
else if (!local_address) {
local_address = strdup(if_addr[i]);
}
}
/* if nothing did work, just take anything */
if (!inet_address)
inet_address = strdup(if_addr[0]);
if (!local_address)
local_address = strdup(if_addr[0]);
return map;
}
KInetAddress* KInetAddress::getPrivateInetAddress() {
if ( inet_address == NULL ) {
findAddresses();
}
return new KInetAddress(QString(inet_address));
}
KInetAddress* KInetAddress::getLocalAddress() {
if ( local_address == NULL ) {
findAddresses();
}
return new KInetAddress(QString(local_address));
}

245
srvloc/uuid.cpp Normal file
View File

@ -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 generating 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);
}

29
srvloc/uuid.h Normal file
View File

@ -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 */