⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uuid.c

📁 Upnp开发包文件
💻 C
字号:
  /*   ** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.   ** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &   ** Digital Equipment Corporation, Maynard, Mass.   ** Copyright (c) 1998 Microsoft.   ** To anyone who acknowledges that this file is provided "AS IS"   ** without any express or implied warranty: permission to use, copy,   ** modify, and distribute this file for any purpose is hereby   ** granted without fee, provided that the above copyright notices and   ** this notice appears in all source code copies, and that none of   ** the names of Open Software Foundation, Inc., Hewlett-Packard   ** Company, or Digital Equipment Corporation be used in advertising   ** or publicity pertaining to distribution of the software without   ** specific, written prior permission.  Neither Open Software   ** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital Equipment   ** Corporation makes any representations about the suitability of   ** this software for any purpose.   */#include <string.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <netinet/in.h>#include "sysdep.h"#include "uuid.h"/*   various forward declarations  */static int read_state( unsigned16 * clockseq,                       uuid_time_t * timestamp,                       uuid_node_t * node );static void write_state( unsigned16 clockseq,                         uuid_time_t timestamp,                         uuid_node_t node );static void format_uuid_v1( uuid_upnp * uid,                            unsigned16 clockseq,                            uuid_time_t timestamp,                            uuid_node_t node );static void format_uuid_v3( uuid_upnp * uid,                            unsigned char hash[16] );static void get_current_time( uuid_time_t * timestamp );static unsigned16 true_random( void );/*-----------------------------------------------------------------------------*//*   uuid_create -- generator a UUID  */intuuid_create( uuid_upnp * uid ){    uuid_time_t timestamp,      last_time;    unsigned16 clockseq;    uuid_node_t node;    uuid_node_t last_node;    int f;    /*       acquire system wide lock so we're alone      */    UUIDLock(  );    /*       get current time      */    get_current_time( &timestamp );    /*       get node ID      */    get_ieee_node_identifier( &node );    /*       get saved state from NV storage      */    f = read_state( &clockseq, &last_time, &last_node );    /*       if no NV state, or if clock went backwards, or node ID changed       (e.g., net card swap) change clockseq      */    if( !f || memcmp( &node, &last_node, sizeof( uuid_node_t ) ) )        clockseq = true_random(  );    else if( timestamp < last_time )        clockseq++;    /*       stuff fields into the UUID      */    format_uuid_v1( uid, clockseq, timestamp, node );    /*       save the state for next time      */    write_state( clockseq, timestamp, node );    UUIDUnlock(  );    return ( 1 );};/*-----------------------------------------------------------------------------*/voiduuid_unpack( uuid_upnp * u,             char *out ){    sprintf( out,             "%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",             ( unsigned int )u->time_low, u->time_mid,             u->time_hi_and_version, u->clock_seq_hi_and_reserved,             u->clock_seq_low, u->node[0], u->node[1], u->node[2],             u->node[3], u->node[4], u->node[5] );    *( out + 36 ) = '\0';};/*-----------------------------------------------------------------------------*//*   format_uuid_v1 -- make a UUID from the timestamp, clockseq,   and node ID  */voidformat_uuid_v1( uuid_upnp * uid,                unsigned16 clock_seq,                uuid_time_t timestamp,                uuid_node_t node ){    /*       Construct a version 1 uuid with the information we've gathered       * plus a few constants.      */    uid->time_low = ( unsigned long )( timestamp & 0xFFFFFFFF );    uid->time_mid = ( unsigned short )( ( timestamp >> 32 ) & 0xFFFF );    uid->time_hi_and_version = ( unsigned short )( ( timestamp >> 48 ) &                                                   0x0FFF );    uid->time_hi_and_version |= ( 1 << 12 );    uid->clock_seq_low = clock_seq & 0xFF;    uid->clock_seq_hi_and_reserved = ( clock_seq & 0x3F00 ) >> 8;    uid->clock_seq_hi_and_reserved |= 0x80;    memcpy( &uid->node, &node, sizeof uid->node );};/*-----------------------------------------------------------------------------*//*   data type for UUID generator persistent state  */typedef struct {    uuid_time_t ts;             /* saved timestamp */    uuid_node_t node;           /* saved node ID */    unsigned16 cs;              /* saved clock sequence */} uuid_state;static uuid_state st;static int stateInited = 0;/*-----------------------------------------------------------------------------*//*   read_state -- read UUID generator state from non-volatile store  */intread_state( unsigned16 * clockseq,            uuid_time_t * timestamp,            uuid_node_t * node ){    if( !stateInited ) {        return 0;    };    *clockseq = st.cs;    *timestamp = st.ts;    *node = st.node;    return 1;};/*-----------------------------------------------------------------------------*//*   write_state -- save UUID generator state back to non-volatile   storage  */voidwrite_state( unsigned16 clockseq,             uuid_time_t timestamp,             uuid_node_t node ){    static uuid_time_t next_save;    if( !stateInited ) {        next_save = timestamp;        stateInited = 1;    };    /*       always save state to volatile shared state      */    st.cs = clockseq;    st.ts = timestamp;    st.node = node;    if( timestamp >= next_save ) {        /*           schedule next save for 10 seconds from now          */        next_save = timestamp + ( 10 * 10 * 1000 * 1000 );    };};/*-----------------------------------------------------------------------------*//*   get-current_time -- get time as 60 bit 100ns ticks since whenever.   Compensate for the fact that real clock resolution is   less than 100ns.  */voidget_current_time( uuid_time_t * timestamp ){    uuid_time_t time_now;    static uuid_time_t time_last;    static unsigned16 uuids_this_tick;    static int inited = 0;    if( !inited ) {        get_system_time( &time_now );        uuids_this_tick = UUIDS_PER_TICK;        inited = 1;    };    while( 1 ) {        get_system_time( &time_now );        /*           if clock reading changed since last UUID generated...          */        if( time_last != time_now ) {            /*               reset count of uuids gen'd with this clock reading              */            uuids_this_tick = 0;            break;        };        if( uuids_this_tick < UUIDS_PER_TICK ) {            uuids_this_tick++;            break;        };        /*           going too fast for our clock; spin          */    };    /*       add the count of uuids to low order bits of the clock reading      */    *timestamp = time_now + uuids_this_tick;    time_last = *timestamp;};/*-----------------------------------------------------------------------------*//*   true_random -- generate a crypto-quality random number.   This sample doesn't do that.  */static unsigned16true_random( void ){    static int inited = 0;    uuid_time_t time_now;    if( !inited ) {        get_system_time( &time_now );        time_now = time_now / UUIDS_PER_TICK;        srand( ( unsigned int )( ( ( time_now >> 32 ) ^ time_now ) &                                 0xffffffff ) );        inited = 1;    };    return ( rand(  ) );}/*-----------------------------------------------------------------------------*//*   uuid_create_from_name -- create a UUID using a "name" from a "name space"  */voiduuid_create_from_name( uuid_upnp * uid, /* resulting UUID */                       uuid_upnp nsid,  /* UUID to serve as context, so identical                                           names from different name spaces generate                                           different UUIDs */                       void *name,  /* the name from which to generate a UUID */                       int namelen  /* the length of the name */     ){    MD5_CTX c;    unsigned char hash[16];    uuid_upnp net_nsid;         /* context UUID in network byte order */    /*       put name space ID in network byte order so it hashes the same       no matter what endian machine we're on      */    net_nsid = nsid;    htonl( net_nsid.time_low );    htons( net_nsid.time_mid );    htons( net_nsid.time_hi_and_version );    MD5Init( &c );    MD5Update( &c, &net_nsid, sizeof( uuid_upnp ) );    MD5Update( &c, name, namelen );    MD5Final( hash, &c );    /*       the hash is in network byte order at this point      */    format_uuid_v3( uid, hash );};/*-----------------------------------------------------------------------------*//*   format_uuid_v3 -- make a UUID from a (pseudo)random 128 bit number */voidformat_uuid_v3( uuid_upnp * uid,                unsigned char hash[16] ){    /*       Construct a version 3 uuid with the (pseudo-)random number       * plus a few constants.      */    memcpy( uid, hash, sizeof( uuid_upnp ) );    /*       convert UUID to local byte order      */    ntohl( uid->time_low );    ntohs( uid->time_mid );    ntohs( uid->time_hi_and_version );    /*       put in the variant and version bits      */    uid->time_hi_and_version &= 0x0FFF;    uid->time_hi_and_version |= ( 3 << 12 );    uid->clock_seq_hi_and_reserved &= 0x3F;    uid->clock_seq_hi_and_reserved |= 0x80;};/*-----------------------------------------------------------------------------*//*   uuid_compare --  Compare two UUID's "lexically" and return   -1   u1 is lexically before u2   0   u1 is equal to u2   1   u1 is lexically after u2   Note:   lexical ordering is not temporal ordering! */intuuid_compare( uuid_upnp * u1,              uuid_upnp * u2 ){    int i;#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;    CHECK( u1->time_low, u2->time_low );    CHECK( u1->time_mid, u2->time_mid );    CHECK( u1->time_hi_and_version, u2->time_hi_and_version );    CHECK( u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved );    CHECK( u1->clock_seq_low, u2->clock_seq_low )        for( i = 0; i < 6; i++ ) {        if( u1->node[i] < u2->node[i] )            return -1;        if( u1->node[i] > u2->node[i] )            return 1;    }    return 0;};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -