You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2016/06/27 17:47:18 UTC
[trafficserver] branch master updated: TS-4518 Add the basic APIs
and code for UUIDs
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch master
in repository https://git-dual.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 9f774fb TS-4518 Add the basic APIs and code for UUIDs
9f774fb is described below
commit 9f774fb656b44930375746e63df1b2cdb583bd18
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Fri Jun 10 22:03:35 2016 -0600
TS-4518 Add the basic APIs and code for UUIDs
---
.../api/functions/TSUuidCreate.en.rst | 136 +++++++++++++++++++
doc/developer-guide/api/types/TSUuid.en.rst | 48 +++++++
iocore/utils/I_Machine.h | 3 +
iocore/utils/Machine.cc | 36 ++---
lib/ts/Makefile.am | 2 +
lib/ts/apidefs.h.in | 86 ++++++++++--
lib/ts/ink_uuid.cc | 97 ++++++++++++++
lib/ts/ink_uuid.h | 135 +++++++++++++++++++
proxy/InkAPI.cc | 95 ++++++++++++++
proxy/InkAPITest.cc | 146 +++++++++++++++++++++
proxy/Main.cc | 3 +
proxy/api/ts/ts.h | 17 +++
12 files changed, 776 insertions(+), 28 deletions(-)
diff --git a/doc/developer-guide/api/functions/TSUuidCreate.en.rst b/doc/developer-guide/api/functions/TSUuidCreate.en.rst
new file mode 100644
index 0000000..d0f9429
--- /dev/null
+++ b/doc/developer-guide/api/functions/TSUuidCreate.en.rst
@@ -0,0 +1,136 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+.. include:: ../../../common.defs
+
+.. default-domain:: c
+
+TSUuidCreate
+************
+
+Traffic Server UUID construction APIs.
+
+Synopsis
+========
+
+`#include <ts/ts.h>`
+
+.. function:: TSUuid TSUuidCreate(void);
+.. function:: TSReturnCode TSUuidInitialize(TSUuid uuid, TSUuidVersion v);
+.. function:: void TSUuidDestroy(TSUuid uuid);
+.. function:: TSReturnCode TSUuidCopy(TSUuid dest, const TSUuid src);
+.. function:: const char *TSUuidStringGet(const TSUuid uuid);
+.. function:: TSUuidVersion TSUuidVersionGet(const TSUuid uuid);
+.. function:: TSReturnCode TSUuidStringParse(TSUuid uuid, const char *uuid_str);
+.. function:: const TSUuid TSProcessUuidGet(void);
+
+Description
+===========
+
+These APIs are used to create, manage, and use UUIDs in a plugin, implementing
+part of RFC 4122. Currently, only the V4 variant of the specifications is
+implemented. In addition, an internal, process unique UUID is provided, which
+can be used to uniquely identifying the running Traffic Server process.
+
+:func:`TSUuidCreate` creates a new :type:`TSUuid` object, which is returned
+and can be used by the other APIs. Similarly, a read-only global process UUID
+is returned from the function :func:`TSProcessUuidGet`. You must not attempt
+to modify any data as returned by either of these functions.
+
+:func:`TSUuidInitialize` initializes a :type:`TSUuid` object, using the
+algorithm defined for the specified version. Note that only the V4 variants is
+currently supported. You can call :func:`TSUuidInitialize` repeatedly, which
+each generates a new UUID, but this will overwrite any existing UUID data in
+the object. This also implies that any strings retrieved using
+:func:`TSUuidStringGet` are also modified accordingly.
+
+:func:`TSUuidDestroy` destroys (releases) an :type:`TSUuid` object, and frees
+all memory associated with this object. This includes any strings as returned
+by e.g. :func:`TSUuidStringGet`.
+
+:func:`TSUuidCopy` copies one :type:`TSUuid` to another, making an exact
+duplicate. Note that both the source and the destination UUIDs must be created
+appropriately, and should not have been previously destroyed.
+
+:func:`TSUuidVersionGet` returns the version number for the
+:type:`TSUuid`. This will work properly for any RFC 4122 initialized UUID
+object, e.g. if you parse a string with :func:`TSUuidStringParse` this will
+return the correct variant ID.
+
+:func:`TSUuidStringGet` returns a pointer to the internal string
+representation of the :type:`TSUuid` object. It's important to know that there
+is no transfer of ownership of this string. If you need a copy of it, you are
+responsible of doing so yourself. In particular, using a string as returned by
+:func:`TSUuidStringGet` **after** you have called :func:`TSUuidDestroy` on the
+corresponding :type:`TSUuid` object is a serious error. The UUID object does
+not do any sort of reference counting on the string, and you must absolutely
+not free the memory as returned by this API.
+
+Finally, :func:`TSUuidStringParse` can be used to convert an existing
+:type:`TSUuid` string to a Traffic Server UUID object. This will only succeed
+if the :type:`TSUuid` string is a proper *RFC 4122* UUID. The :type:`TSUuid`
+argument passed to this function must be a properly :func:`TSUuidCreate`
+object, but it does not need to be previously initialized.
+
+Return Values
+=============
+
+The :type:`TSUuid` type is an opaque pointer to an internal representation of
+the UUID object. Several of the functions returns a normal Traffic Server
+return status code, :type:`TSReturnCode`. You should verify the success of
+those APIs, of course.
+
+The :func:`TSUuidStringGet` function will return ``NULL`` if the :type:`TSUuid`
+object is not properly inititialized. Likewise, :func:`TSUuidVersionGet` would
+then return ``TS_UUID_UNDEFINED``.
+
+The :func:`TSUuidDestroy` function can not fail, and does not have a return
+value, but you are of course responsible for providing a valid :type:`TSUuid`
+object.
+
+Examples
+========
+
+.. code-block:: c
+
+ #include <ts/ts.h>
+
+ TSUuid machine, uuid;
+
+ machine = TSProcessUuidGet();
+ printf("Machine UUID is %s\n", TSUuidStringGet(machine);
+
+ if (uuid = TSUuidCreate()) {
+ if (TS_SUCCESS == TSUuidInitialize(uuid, TS_UUID_V4) {
+ printf("My UUID is %s\n", TSUuidStringGet(uuid));
+ }
+ TSUuidDestroy(uuid);
+ }
+
+ const char* str = "c71e2bab-90dc-4770-9535-c9304c3de38e";
+
+ if (TS_SUCCESS == TSUuidStringParse(uuid, str)) {
+ if (TS_UUID_V4 == TSUuidVersionGet(uuid)) {
+ // Yes!
+ }
+ }
+
+See Also
+========
+
+:manpage:`TSAPI(3ts)`,
+:manpage:`TSUuid(3ts)`,
+:manpage:`TSReturnCode(3ts)`,
diff --git a/doc/developer-guide/api/types/TSUuid.en.rst b/doc/developer-guide/api/types/TSUuid.en.rst
new file mode 100644
index 0000000..abf5044
--- /dev/null
+++ b/doc/developer-guide/api/types/TSUuid.en.rst
@@ -0,0 +1,48 @@
+.. Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright
+ ownership. The ASF licenses this file to you under the Apache
+ License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of
+ the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+.. include:: ../../../common.defs
+
+TSUuid
+******
+
+Synopsis
+========
+
+`#include <ts/apidefs.h>`
+
+.. c:type:: TSUuid
+
+An opaque pointer to an internal representation of a UUID object.
+
+
+Description
+===========
+
+The UUID object is managed and created via the various UUID APIs. You can not
+access nor modify this object using anything but the provided APIs.
+
+See Also
+========
+
+:manpage:`TSUuidCreate(3ts)`,
+:manpage:`TSUuidInitialize(3ts)`,
+:manpage:`TSUuidDestroy(3ts)`,
+:manpage:`TSUuidCopy(3ts)`,
+:manpage:`TSUuidStringGet(3ts)`,
+:manpage:`TSUuidVersionGet(3ts)`,
+:manpage:`TSUuidStringParse(3ts)`,
+:manpage:`TSProcessUuidGet(3ts)`
diff --git a/iocore/utils/I_Machine.h b/iocore/utils/I_Machine.h
index 6a15b89..ef9d7e0 100644
--- a/iocore/utils/I_Machine.h
+++ b/iocore/utils/I_Machine.h
@@ -32,6 +32,7 @@
#define _I_Machine_h
#include "ts/ink_inet.h"
+#include "ts/ink_uuid.h"
/**
The Machine is a simple place holder for the hostname and the ip
@@ -63,6 +64,8 @@ struct Machine {
char ip_hex_string[TS_IP6_SIZE * 2 + 1]; ///< IP address as hex string
int ip_hex_string_len;
+ ATSUuid uuid;
+
~Machine();
/** Initialize the singleton.
diff --git a/iocore/utils/Machine.cc b/iocore/utils/Machine.cc
index 9b2695b..8deb003 100644
--- a/iocore/utils/Machine.cc
+++ b/iocore/utils/Machine.cc
@@ -60,6 +60,7 @@ Machine::Machine(char const *the_hostname, sockaddr const *addr)
ink_zero(ip);
ink_zero(ip4);
ink_zero(ip6);
+ uuid.initialize(TS_UUID_V4);
localhost[sizeof(localhost) - 1] = 0; // ensure termination.
@@ -122,25 +123,28 @@ Machine::Machine(char const *the_hostname, sockaddr const *addr)
// get the interface's flags
struct ifreq ifr;
ink_strlcpy(ifr.ifr_name, spot->ifr_name, IFNAMSIZ);
- if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
+ if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
ifflags = ifr.ifr_flags;
- else
+ } else {
ifflags = 0; // flags not available, default to just looking at IP
+ }
#endif
- if (!ats_is_ip(ifip))
+ if (!ats_is_ip(ifip)) {
spot_type = NA;
- else if (ats_is_ip_loopback(ifip) || (IFF_LOOPBACK & ifflags))
+ } else if (ats_is_ip_loopback(ifip) || (IFF_LOOPBACK & ifflags)) {
spot_type = LO;
- else if (ats_is_ip_linklocal(ifip))
+ } else if (ats_is_ip_linklocal(ifip)) {
spot_type = LL;
- else if (ats_is_ip_private(ifip))
+ } else if (ats_is_ip_private(ifip)) {
spot_type = PR;
- else if (ats_is_ip_multicast(ifip))
+ } else if (ats_is_ip_multicast(ifip)) {
spot_type = MC;
- else
+ } else {
spot_type = GL;
- if (spot_type == NA)
+ }
+ if (spot_type == NA) {
continue; // Next!
+ }
if (ats_is_ip4(ifip)) {
if (spot_type > ip4_type) {
@@ -160,24 +164,24 @@ Machine::Machine(char const *the_hostname, sockaddr const *addr)
#endif
// What about the general address? Prefer IPv4?
- if (ip4_type >= ip6_type)
+ if (ip4_type >= ip6_type) {
ats_ip_copy(&ip.sa, &ip4.sa);
- else
+ } else {
ats_ip_copy(&ip.sa, &ip6.sa);
+ }
}
#if !HAVE_IFADDRS_H
close(s);
#endif
} else { // address provided.
ats_ip_copy(&ip, addr);
- if (ats_is_ip4(addr))
+ if (ats_is_ip4(addr)) {
ats_ip_copy(&ip4, addr);
- else if (ats_is_ip6(addr))
+ } else if (ats_is_ip6(addr)) {
ats_ip_copy(&ip6, addr);
+ }
- status = getnameinfo(addr, ats_ip_size(addr), localhost, sizeof(localhost) - 1, 0, 0, // do not request service info
- 0 // no flags.
- );
+ status = getnameinfo(addr, ats_ip_size(addr), localhost, sizeof(localhost) - 1, 0, 0, 0); // no flags
if (0 != status) {
ip_text_buffer ipbuff;
diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am
index a3ddf43..9a13750 100644
--- a/lib/ts/Makefile.am
+++ b/lib/ts/Makefile.am
@@ -178,6 +178,8 @@ libtsutil_la_SOURCES = \
ink_thread.h \
ink_time.cc \
ink_time.h \
+ ink_uuid.cc \
+ ink_uuid.h \
llqueue.cc \
lockfile.cc \
signals.cc \
diff --git a/lib/ts/apidefs.h.in b/lib/ts/apidefs.h.in
index 28d0a7a..a9030cc 100644
--- a/lib/ts/apidefs.h.in
+++ b/lib/ts/apidefs.h.in
@@ -121,7 +121,12 @@ typedef struct {
TSHttpHdrParseReq() and TSHttpHdrParseResp().
*/
-typedef enum { TS_PARSE_ERROR = -1, TS_PARSE_DONE = 0, TS_PARSE_OK = 1, TS_PARSE_CONT = 2 } TSParseResult;
+typedef enum {
+ TS_PARSE_ERROR = -1,
+ TS_PARSE_DONE = 0,
+ TS_PARSE_OK = 1,
+ TS_PARSE_CONT = 2,
+} TSParseResult;
/**
This set of enums represents the possible HTTP types that
@@ -133,7 +138,11 @@ typedef enum { TS_PARSE_ERROR = -1, TS_PARSE_DONE = 0, TS_PARSE_OK = 1, TS_PARSE
to obtain the TSHttpType of an HTTP header.
*/
-typedef enum { TS_HTTP_TYPE_UNKNOWN, TS_HTTP_TYPE_REQUEST, TS_HTTP_TYPE_RESPONSE } TSHttpType;
+typedef enum {
+ TS_HTTP_TYPE_UNKNOWN,
+ TS_HTTP_TYPE_REQUEST,
+ TS_HTTP_TYPE_RESPONSE,
+} TSHttpType;
/**
This set of enums represents possible return values from
@@ -475,9 +484,17 @@ typedef enum {
TS_CACHE_LOOKUP_SKIPPED
} TSCacheLookupResult;
-typedef enum { TS_CACHE_DATA_TYPE_NONE, TS_CACHE_DATA_TYPE_HTTP, TS_CACHE_DATA_TYPE_OTHER } TSCacheDataType;
+typedef enum {
+ TS_CACHE_DATA_TYPE_NONE,
+ TS_CACHE_DATA_TYPE_HTTP,
+ TS_CACHE_DATA_TYPE_OTHER,
+} TSCacheDataType;
-typedef enum { TS_CACHE_ERROR_NO_DOC = -20400, TS_CACHE_ERROR_DOC_BUSY = -20401, TS_CACHE_ERROR_NOT_READY = -20407 } TSCacheError;
+typedef enum {
+ TS_CACHE_ERROR_NO_DOC = -20400,
+ TS_CACHE_ERROR_DOC_BUSY = -20401,
+ TS_CACHE_ERROR_NOT_READY = -20407,
+} TSCacheError;
typedef enum {
TS_CACHE_SCAN_RESULT_DONE = 0,
@@ -499,7 +516,10 @@ typedef enum {
TS_TXN_INFO_LAST_ENTRY
} TSHttpTxnInfoKey;
-typedef enum { TS_VC_CLOSE_ABORT = -1, TS_VC_CLOSE_NORMAL = 1 } TSVConnCloseFlags;
+typedef enum {
+ TS_VC_CLOSE_ABORT = -1,
+ TS_VC_CLOSE_NORMAL = 1,
+} TSVConnCloseFlags;
typedef enum {
TS_IOBUFFER_SIZE_INDEX_128 = 0,
@@ -519,9 +539,16 @@ typedef enum {
TS_IOBUFFER_SIZE_INDEX_2M = 14
} TSIOBufferSizeIndex;
-typedef enum { TS_ERROR = -1, TS_SUCCESS = 0 } TSReturnCode;
+typedef enum {
+ TS_ERROR = -1,
+ TS_SUCCESS = 0,
+} TSReturnCode;
-typedef enum { NO_CALLBACK = 0, AFTER_HEADER, AFTER_BODY } TSFetchWakeUpOptions;
+typedef enum {
+ NO_CALLBACK = 0,
+ AFTER_HEADER,
+ AFTER_BODY,
+} TSFetchWakeUpOptions;
#ifndef _HTTP_PROXY_API_ENUMS_H_
#define _HTTP_PROXY_API_ENUMS_H_
@@ -536,7 +563,10 @@ typedef enum {
/// Server session sharing values - pool
/// Must be identical to definition in HttpProxyAPIEnums.h
-typedef enum { TS_SERVER_SESSION_SHARING_POOL_GLOBAL, TS_SERVER_SESSION_SHARING_POOL_THREAD } TSServerSessionSharingPoolType;
+typedef enum {
+ TS_SERVER_SESSION_SHARING_POOL_GLOBAL,
+ TS_SERVER_SESSION_SHARING_POOL_THREAD,
+} TSServerSessionSharingPoolType;
#endif
/* librecords types */
@@ -573,7 +603,11 @@ typedef union {
} TSRecordData;
/* The values of this enum must match enum RecPersistT in I_RecDefs.h */
-typedef enum { TS_RECORDP_NULL, TS_RECORDP_PERSISTENT, TS_RECORDP_NON_PERSISTENT } TSRecordPersistType;
+typedef enum {
+ TS_RECORDP_NULL,
+ TS_RECORDP_PERSISTENT,
+ TS_RECORDP_NON_PERSISTENT,
+} TSRecordPersistType;
/* The values of this enum must match enum RecUpdateT in I_RecDefs.h */
typedef enum {
@@ -585,13 +619,27 @@ typedef enum {
} TSRecordUpdateType;
/* The values of this enum must match enum RecCheckT in I_RecDefs.h */
-typedef enum { TS_RECORDCHECK_NULL, TS_RECORDCHECK_STR, TS_RECORDCHECK_INT, TS_RECORDCHECK_IP } TSRecordCheckType;
+typedef enum {
+ TS_RECORDCHECK_NULL,
+ TS_RECORDCHECK_STR,
+ TS_RECORDCHECK_INT,
+ TS_RECORDCHECK_IP,
+} TSRecordCheckType;
/* The values of this enum must match enum RecModeT in I_RecDefs.h */
-typedef enum { TS_RECORDMODE_NULL, TS_RECORDMODE_CLIENT, TS_RECORDMODE_SERVER, TS_RECORDMODE_STAND_ALONE } TSRecordModeType;
+typedef enum {
+ TS_RECORDMODE_NULL,
+ TS_RECORDMODE_CLIENT,
+ TS_RECORDMODE_SERVER,
+ TS_RECORDMODE_STAND_ALONE,
+} TSRecordModeType;
/* The values of this enum must match enum RecAccessT in I_RecDefs.h */
-typedef enum { TS_RECORDACCESS_NULL, TS_RECORDACCESS_NO_ACCESS, TS_RECORDACCESS_READ_ONLY } TSRecordAccessType;
+typedef enum {
+ TS_RECORDACCESS_NULL,
+ TS_RECORDACCESS_NO_ACCESS,
+ TS_RECORDACCESS_READ_ONLY,
+} TSRecordAccessType;
typedef enum {
TS_CONFIG_NULL = -1,
@@ -1125,6 +1173,20 @@ extern tsapi const char *const TS_NPN_PROTOCOL_GROUP_SPDY;
*/
extern tsapi const TSMLoc TS_NULL_MLOC;
+/* --------------------------------------------------------------------------
+ Interface for the UUID APIs. https://www.ietf.org/rfc/rfc4122.txt. */
+typedef enum {
+ TS_UUID_UNDEFINED = 0,
+ TS_UUID_V1 = 1,
+ TS_UUID_V2,
+ TS_UUID_V3,
+ TS_UUID_V4, /* At this point, this is the only implemented version (or variant) */
+ TS_UUID_V5,
+} TSUuidVersion;
+
+#define TS_UUID_STRING_LEN 36
+typedef struct tsapi_uuid *TSUuid;
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/lib/ts/ink_uuid.cc b/lib/ts/ink_uuid.cc
new file mode 100644
index 0000000..88bc75c
--- /dev/null
+++ b/lib/ts/ink_uuid.cc
@@ -0,0 +1,97 @@
+/** @file
+ *
+ * Basic implementation of RFC 4122, see
+ * https://www.ietf.org/rfc/rfc4122.txt
+ *
+ * @section license License
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <openssl/rand.h>
+
+#include "ts/ink_error.h"
+#include "ts/ink_uuid.h"
+
+void
+ATSUuid::initialize(TSUuidVersion v)
+{
+ switch (v) {
+ case TS_UUID_UNDEFINED:
+ ink_abort("Don't initialize to undefined UUID variant!");
+ break;
+ case TS_UUID_V1:
+ case TS_UUID_V2:
+ case TS_UUID_V3:
+ case TS_UUID_V5:
+ ink_zero(_uuid.data); // Not properly implemented yet, so set it to the Nil UUID
+ break;
+ case TS_UUID_V4:
+ RAND_bytes(_uuid.data, sizeof(_uuid.data));
+ _uuid.clockSeqAndReserved = (uint8_t)((_uuid.clockSeqAndReserved & 0x3F) | 0x80);
+ _uuid.timeHighAndVersion = (uint16_t)((_uuid.timeHighAndVersion & 0x0FFF) | 0x4000);
+
+ break;
+ }
+
+ _version = _toString(_string) ? v : TS_UUID_UNDEFINED;
+}
+
+// Copy assignment
+ATSUuid &
+ATSUuid::operator=(const ATSUuid other)
+{
+ memcpy(_uuid.data, other._uuid.data, sizeof(_uuid.data));
+ memcpy(_string, other._string, sizeof(_string));
+ _version = other._version;
+
+ return *this;
+}
+
+bool
+ATSUuid::parseString(const char *str)
+{
+ int cnt = sscanf(str, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", &_uuid.timeLow, &_uuid.timeMid,
+ &_uuid.timeHighAndVersion, &_uuid.clockSeqAndReserved, &_uuid.clockSeqLow, &_uuid.node[0], &_uuid.node[1],
+ &_uuid.node[2], &_uuid.node[3], &_uuid.node[4], &_uuid.node[5]);
+
+ if ((11 == cnt) && _toString(_string)) {
+ switch (_uuid.timeHighAndVersion >> 12) {
+ case 1:
+ _version = TS_UUID_V1;
+ break;
+ case 2:
+ _version = TS_UUID_V2;
+ break;
+ case 3:
+ _version = TS_UUID_V3;
+ break;
+ case 4:
+ _version = TS_UUID_V4;
+ break;
+ case 5:
+ _version = TS_UUID_V5;
+ break;
+ default:
+ _version = TS_UUID_UNDEFINED;
+ break;
+ }
+ } else {
+ _version = TS_UUID_UNDEFINED;
+ }
+
+ return (TS_UUID_UNDEFINED != _version);
+}
diff --git a/lib/ts/ink_uuid.h b/lib/ts/ink_uuid.h
new file mode 100644
index 0000000..7df48d8
--- /dev/null
+++ b/lib/ts/ink_uuid.h
@@ -0,0 +1,135 @@
+/** @file
+ *
+ * Basic implementation of RFC 4122, see
+ * https://www.ietf.org/rfc/rfc4122.txt
+ *
+ * @section license License
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+
+#include "ts/apidefs.h"
+#include "ts/ink_memory.h"
+
+// This is the C++ portions of things, which will need to get wrapped in C-helper APIs.
+class ATSUuid
+{
+public:
+ // Constructors
+ ATSUuid() : _version(TS_UUID_UNDEFINED) {}
+ ATSUuid &operator=(const ATSUuid other);
+
+ // Initialize the UUID from a string
+ bool parseString(const char *str);
+
+ // Initialize a UUID using appropriate logic for the version specified. This can be done multiple times.
+ void initialize(TSUuidVersion v);
+
+ // These return the internal string representation of the UUID, do not mess with this string. There is
+ // no transfer of ownership here. You will have to make a copy to take ownership!
+ const char *
+ getString() const
+ {
+ return valid() ? _string : NULL;
+ }
+
+ const char *
+ c_str() const
+ {
+ return getString();
+ }
+
+ TSUuidVersion
+ version() const
+ {
+ return _version;
+ }
+
+ bool
+ valid() const
+ {
+ return (TS_UUID_UNDEFINED != _version);
+ }
+
+ // Getter's for the various UUID components.
+ uint32_t
+ getTimeLow() const
+ {
+ return _uuid.timeLow;
+ }
+
+ uint16_t
+ getTimeMid() const
+ {
+ return _uuid.timeMid;
+ }
+
+ uint16_t
+ getTimeHighAndVersion() const
+ {
+ return _uuid.timeHighAndVersion;
+ }
+
+ uint8_t
+ getClockSeqAndReserved() const
+ {
+ return _uuid.clockSeqAndReserved;
+ }
+
+ uint8_t
+ getClockSeqLow() const
+ {
+ return _uuid.clockSeqLow;
+ }
+
+ const uint8_t *
+ getNode() const
+ {
+ return _uuid.node;
+ }
+
+private:
+ // This is the union of the raw data (128 bits) and the fields as specified in
+ // RFC 4122. Technically we only need the raw data, but might as well unionize here.
+ union {
+ uint8_t data[16];
+
+ struct {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t timeHighAndVersion;
+ uint8_t clockSeqAndReserved;
+ uint8_t clockSeqLow;
+ uint8_t node[6];
+ };
+ } _uuid;
+
+ // This is the typically used visible portion of the UUID
+ TSUuidVersion _version;
+ char _string[TS_UUID_STRING_LEN + 1];
+
+ bool
+ _toString(char *buf)
+ {
+ int len = snprintf(buf, TS_UUID_STRING_LEN + 1, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+ _uuid.timeLow, _uuid.timeMid, _uuid.timeHighAndVersion, _uuid.clockSeqAndReserved, _uuid.clockSeqLow,
+ _uuid.node[0], _uuid.node[1], _uuid.node[2], _uuid.node[3], _uuid.node[4], _uuid.node[5]);
+
+ return (len == TS_UUID_STRING_LEN);
+ }
+};
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index 5772c12..ea1e073 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -59,6 +59,7 @@
#include "I_RecDefs.h"
#include "I_RecCore.h"
+#include "I_Machine.h"
#include "HttpProxyServerMain.h"
/****************************************************************
@@ -8941,3 +8942,97 @@ TSVConnReenable(TSVConn vconn)
}
}
}
+
+// APIs for managing and using UUIDs.
+TSUuid
+TSUuidCreate(void)
+{
+ ATSUuid *uuid = new ATSUuid();
+ return (TSUuid)uuid;
+}
+
+void
+TSUuidDestroy(TSUuid uuid)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
+ delete (ATSUuid *)uuid;
+}
+
+TSReturnCode
+TSUuidCopy(TSUuid dest, const TSUuid src)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)dest) == TS_SUCCESS);
+ sdk_assert(sdk_sanity_check_null_ptr((void *)src) == TS_SUCCESS);
+ ATSUuid *d = (ATSUuid *)dest;
+ ATSUuid *s = (ATSUuid *)src;
+
+ if (s->valid()) {
+ *d = *s;
+ return TS_SUCCESS;
+ }
+
+ return TS_ERROR;
+}
+
+TSReturnCode
+TSUuidInitialize(TSUuid uuid, TSUuidVersion v)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
+ ATSUuid *u = (ATSUuid *)uuid;
+
+ u->initialize(v);
+ return u->valid() ? TS_SUCCESS : TS_ERROR;
+}
+
+const TSUuid
+TSProcessUuidGet(void)
+{
+ Machine *machine = Machine::instance();
+ return (TSUuid)(&machine->uuid);
+}
+
+const char *
+TSUuidStringGet(const TSUuid uuid)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
+ ATSUuid *u = (ATSUuid *)(uuid);
+
+ if (u->valid()) {
+ return u->getString();
+ }
+
+ return NULL;
+}
+
+TSReturnCode
+TSUuidStringParse(TSUuid uuid, const char *str)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
+ sdk_assert(sdk_sanity_check_null_ptr((void *)str) == TS_SUCCESS);
+ ATSUuid *u = (ATSUuid *)uuid;
+
+ if (u->parseString(str)) {
+ return TS_SUCCESS;
+ }
+
+ return TS_ERROR;
+}
+
+TSUuidVersion
+TSUuidVersionGet(TSUuid uuid)
+{
+ sdk_assert(sdk_sanity_check_null_ptr((void *)uuid) == TS_SUCCESS);
+ ATSUuid *u = (ATSUuid *)uuid;
+
+ return u->version();
+}
+
+// Expose the HttpSM's sequence number (ID)
+uint64_t
+TSHttpTxnIdGet(TSHttpTxn txnp)
+{
+ sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
+ HttpSM *sm = (HttpSM *)txnp;
+
+ return (uint64_t)sm->sm_id;
+}
diff --git a/proxy/InkAPITest.cc b/proxy/InkAPITest.cc
index d156403..8cfe6b1 100644
--- a/proxy/InkAPITest.cc
+++ b/proxy/InkAPITest.cc
@@ -7775,3 +7775,149 @@ REGRESSION_TEST(SDK_API_DEBUG_NAME_LOOKUPS)(RegressionTest *test, int /* atype A
return;
}
+
+////////////////////////////////////////////////
+// SDK_API_UUID
+//
+// Unit Test for API: TSUuidCreate
+// TSUuidDestroy
+// TSUuidCopy
+// TSUuidInitialize
+// TSProcessUuidGet
+// TSUuidStringGet
+// TSUuidVersionGet
+// TSUuidStringParse
+////////////////////////////////////////////////
+#include "ts/ink_uuid.h"
+
+REGRESSION_TEST(SDK_API_UUID)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
+{
+ TSUuid machine, uuid;
+ const char *str1;
+ const char *str2;
+ static const char uuid_v1[] = "5de5f9ec-30f4-11e6-a073-002590a33e4e";
+ static const char uuid_v4[] = "0e95fe5f-295a-401d-9ae4-eb32756d73cb";
+
+ *pstatus = REGRESSION_TEST_INPROGRESS;
+
+ // Test TSProcessUuidGet(), should just return a non-NULL pointer now.
+ machine = TSProcessUuidGet();
+ if (!machine) {
+ SDK_RPRINT(test, "TSProcessUuidGet", "TestCase1", TC_FAIL, "Returned a NULL pointer");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else if (!((ATSUuid *)machine)->valid()) {
+ SDK_RPRINT(test, "TSProcessUuidGet", "TestCase2", TC_FAIL, "Returned an invalid UUID object");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSProcessUuidGet", "TestCase1", TC_PASS, "ok");
+ SDK_RPRINT(test, "TSProcessUuidGet", "TestCase2", TC_PASS, "ok");
+ }
+
+ // Test TSUuidStringGet, should return a random string (so can't check the string value itself)
+ str1 = TSUuidStringGet(machine);
+ if (!str1 || (TS_UUID_STRING_LEN != strlen(str1))) {
+ SDK_RPRINT(test, "TSUuidStringGet", "TestCase1", TC_FAIL, "Did not return a valid UUID string representation");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidStringGet", "TestCase1", TC_PASS, "ok");
+ }
+
+ // Test TSUuidCreate
+ if (!(uuid = TSUuidCreate())) {
+ SDK_RPRINT(test, "TSUuidCreate", "TestCase1", TC_FAIL, "Failed to crete a UUID object");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidCreate", "TestCase1", TC_PASS, "ok");
+ if (TS_SUCCESS != TSUuidInitialize(uuid, TS_UUID_V4)) {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase1", TC_FAIL, "Failed to Initialize a V4 UUID");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase1", TC_PASS, "ok");
+ }
+ }
+
+ // Test TSUuidVersion
+ if (TS_UUID_V4 != TSUuidVersionGet(uuid)) {
+ SDK_RPRINT(test, "TSUuidVersionGet", "TestCase1", TC_FAIL, "Failed to get the UUID version");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidVersionGet", "TestCase1", TC_PASS, "ok");
+ }
+
+ // Test TSUuidCopy
+ if (TS_SUCCESS != TSUuidCopy(uuid, machine)) {
+ SDK_RPRINT(test, "TSUuidCopy", "TestCase1", TC_FAIL, "Failed to copy the Machine UUID object");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidCopy", "TestCase1", TC_PASS, "ok");
+ str2 = TSUuidStringGet(uuid);
+ if (!str2 || (TS_UUID_STRING_LEN != strlen(str2)) || strcmp(str1, str2)) {
+ SDK_RPRINT(test, "TSUuidCopy", "TestCase2", TC_FAIL, "The copied UUID strings are not identical");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidCopy", "TestCase2", TC_PASS, "ok");
+ }
+ }
+
+ // Test TSUuidInitialize again, make sure they take effect when called multiple times
+ if (TS_SUCCESS != TSUuidInitialize(uuid, TS_UUID_V4)) {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase2", TC_FAIL, "Failed to re-initialize the UUID object");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase2", TC_PASS, "ok");
+ str2 = TSUuidStringGet(uuid);
+ if (!str2 || (TS_UUID_STRING_LEN != strlen(str2)) || !strcmp(str1, str2)) {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase3", TC_FAIL, "The re-initialized string is the same as before");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidInitialize", "TestCase3", TC_PASS, "ok");
+ }
+ }
+
+ // Test TSUuidStringParse
+ if ((TS_SUCCESS != TSUuidStringParse(uuid, uuid_v1)) || (TS_UUID_V1 != TSUuidVersionGet(uuid))) {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase1", TC_FAIL, "Failed to parse the UUID v1 string");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase1", TC_PASS, "ok");
+ str1 = TSUuidStringGet(uuid);
+ if (!str1 || (TS_UUID_STRING_LEN != strlen(str1)) || strcmp(str1, uuid_v1)) {
+ SDK_RPRINT(test, "TSUuidStringString", "TestCase2", TC_FAIL, "The parse UUID v1 string does not match the original");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase2", TC_PASS, "ok");
+ }
+ }
+ if ((TS_SUCCESS != TSUuidStringParse(uuid, uuid_v4)) || (TS_UUID_V4 != TSUuidVersionGet(uuid))) {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase3", TC_FAIL, "Failed to parse the UUID v4 string");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase3", TC_PASS, "ok");
+ str1 = TSUuidStringGet(uuid);
+ if (!str1 || (TS_UUID_STRING_LEN != strlen(str1)) || strcmp(str1, uuid_v4)) {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase4", TC_FAIL, "The parse UUID v4 string does not match the original");
+ *pstatus = REGRESSION_TEST_FAILED;
+ return;
+ } else {
+ SDK_RPRINT(test, "TSUuidStringParse", "TestCase4", TC_PASS, "ok");
+ }
+ }
+
+ TSUuidDestroy(uuid);
+
+ *pstatus = REGRESSION_TEST_PASSED;
+ return;
+}
diff --git a/proxy/Main.cc b/proxy/Main.cc
index 27fcc16..5ce9da2 100644
--- a/proxy/Main.cc
+++ b/proxy/Main.cc
@@ -1674,6 +1674,9 @@ main(int /* argc ATS_UNUSED */, const char **argv)
machine_addr.assign(HttpConfig::m_master.inbound_ip6);
Machine::init(0, &machine_addr.sa);
+ RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.uuid", (char *)Machine::instance()->uuid.getString(),
+ RECP_NON_PERSISTENT);
+
// pmgmt->start() must occur after initialization of Diags but
// before calling RecProcessInit()
diff --git a/proxy/api/ts/ts.h b/proxy/api/ts/ts.h
index 919a5ae..2a03952 100644
--- a/proxy/api/ts/ts.h
+++ b/proxy/api/ts/ts.h
@@ -2329,6 +2329,9 @@ tsapi TSReturnCode TSHttpTxnCacheLookupUrlSet(TSHttpTxn txnp, TSMBuffer bufp, TS
tsapi TSReturnCode TSHttpTxnPrivateSessionSet(TSHttpTxn txnp, int private_session);
tsapi int TSHttpTxnBackgroundFillStarted(TSHttpTxn txnp);
+/* Get the Txn's (HttpSM's) unique identifier, which is a sequence number since server start) */
+tsapi uint64_t TSHttpTxnIdGet(TSHttpTxn txnp);
+
/* Expose internal Base64 Encoding / Decoding */
tsapi TSReturnCode TSBase64Decode(const char *str, size_t str_len, unsigned char *dst, size_t dst_size, size_t *length);
tsapi TSReturnCode TSBase64Encode(const char *str, size_t str_len, char *dst, size_t dst_size, size_t *length);
@@ -2389,6 +2392,20 @@ tsapi const char *TSHttpHookNameLookup(TSHttpHookID hook);
*/
tsapi const char *TSHttpEventNameLookup(TSEvent event);
+/* APIs for dealing with UUIDs, either self made, or the system wide process UUID. See
+ https://docs.trafficserver.apache.org/en/latest/developer-guide/api/functions/TSUuidCreate.en.html
+*/
+tsapi TSUuid TSUuidCreate(void);
+tsapi TSReturnCode TSUuidInitialize(TSUuid uuid, TSUuidVersion v);
+tsapi void TSUuidDestroy(TSUuid uuid);
+tsapi TSReturnCode TSUuidCopy(TSUuid dest, const TSUuid src);
+tsapi const char *TSUuidStringGet(const TSUuid uuid);
+tsapi TSUuidVersion TSUuidVersionGet(const TSUuid uuid);
+tsapi TSReturnCode TSUuidStringParse(TSUuid uuid, const char *uuid_str);
+
+/* Get the process global UUID, resets on every startup */
+tsapi const TSUuid TSProcessUuidGet(void);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
--
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].