Add new CAPI for registering SRP service with TXT records 46/279746/2
authorArkadiusz Bokowy <a.bokowy@partner.samsung.com>
Fri, 12 Aug 2022 12:29:05 +0000 (14:29 +0200)
committerArkadiusz Bokowy <a.bokowy@partner.samsung.com>
Thu, 1 Sep 2022 06:40:39 +0000 (08:40 +0200)
Change-Id: I8e9e861ac0b8e4579ebd0fbdeccc9404b578d025

include/thread-private.h
include/thread-type.h
include/thread.h
src/thread-srp.c
src/thread-util.c

index 8017556..0329763 100755 (executable)
@@ -383,6 +383,17 @@ void _thread_route_free(gpointer data);
  */
 void _thread_onmesh_prefix_free(gpointer data);
 
+/**
+ * @brief Encode TXT entries as a null-terminated hex-string.
+ * @since_tizen 7.0
+ *
+ * @exception
+ * @pre
+ * @post
+ */
+int _thread_encode_txt_entries(const thread_dns_txt_entry_s *txt_entries,
+                               uint8_t num_txt_entries, char *buffer, size_t buffer_size);
+
 #ifdef __cplusplus
 }
 #endif
index 5dd11f4..6aa15ed 100755 (executable)
@@ -198,6 +198,19 @@ typedef void (*thread_joiner_result_cb)(int result, void *user_data);
  */
 typedef void *thread_network_h;
 
+/**
+ * @ingroup CAPI_NETWORK_THREAD_MODULE
+ * @brief Structure which holds single DNS TXT entry.
+ * @since_tizen 7.0
+ *
+ * @note The total length of the TXT entry, which is "key + '=' + value" or
+ *       "key" for boolean key, must not exceed 255 bytes.
+ */
+typedef struct {
+       const char *key; /** The TXT record null-terminated key string */
+       const uint8_t *value; /** The TXT record value, or NULL for boolean key */
+       uint8_t value_len; /** The length of the TXT record value */
+} thread_dns_txt_entry_s;
 
 /**
  * @ingroup CAPI_NETWORK_THREAD_MODULE
index 2f93623..01ace89 100644 (file)
@@ -1473,12 +1473,36 @@ int thread_srp_client_set_host_address(thread_instance_h instance, const char *i
  * @pre thread API must be initialized with thread_initialize().
  * @see thread_srp_client_start()
  * @see thread_srp_client_set_host_address()
+ * @see thread_srp_client_register_service_full()
  */
 int thread_srp_client_register_service(thread_instance_h instance,
        const char *service_name, const char *service_type, uint64_t port);
 
 /**
  * @ingroup CAPI_NETWORK_THREAD_SRP_MODULE
+ * @brief Register Service to SRP server
+ * @since_tizen 7.0
+ *
+ * This is an extended version of thread_srp_client_register_service()
+ * which allows to set priority, weight and TXT entries.
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #THREAD_ERROR_NONE  Successful
+ * @retval #THREAD_ERROR_NOT_INITIALIZED  Not initialized
+ * @retval #THREAD_ERROR_OPERATION_FAILED  Operation failed
+ * @retval #THREAD_ERROR_NOT_SUPPORTED  Not supported
+ *
+ * @pre thread API must be initialized with thread_initialize().
+ * @see thread_srp_client_start()
+ * @see thread_srp_client_set_host_address()
+ * @see thread_srp_client_register_service()
+ */
+int thread_srp_client_register_service_full(thread_instance_h instance,
+       const char *service_name, const char *service_type, uint16_t port, uint16_t priority,
+       uint16_t weight, const thread_dns_txt_entry_s *txt_entries, uint8_t num_txt_entries);
+
+/**
+ * @ingroup CAPI_NETWORK_THREAD_SRP_MODULE
  * @brief Remove Service from SRP server
  * @since_tizen 7.0
  *
index 063649a..8667c75 100644 (file)
@@ -175,6 +175,51 @@ int thread_srp_client_register_service(thread_instance_h instance,
        return ret;
 }
 
+int thread_srp_client_register_service_full(thread_instance_h instance,
+       const char *service_name, const char *service_type, uint16_t port, uint16_t priority,
+       uint16_t weight, const thread_dns_txt_entry_s *txt_entries, uint8_t num_txt_entries)
+{
+       FUNC_ENTRY;
+       THREAD_CHECK_SUPPORTED_FEATURE(THREAD_FEATURE_COMMON);
+       THREAD_VALIDATE_INPUT_PARAMETER(service_name);
+       THREAD_VALIDATE_INPUT_PARAMETER(txt_entries);
+       THREAD_CHECK_INIT_STATUS();
+       THREAD_VALIDATE_INPUT_PARAMETER(instance);
+       int ret = THREAD_ERROR_NONE;
+
+       /* Register SRP service */
+       const char *msg = THREAD_SRP_CLIENT_REGISTER_SERVICE_CMD;
+
+       char buffer[THREAD_MAX_BUFFER_SIZE] = {0};
+       char txt[THREAD_MAX_BUFFER_SIZE] = "";
+
+       ret = _thread_encode_txt_entries(txt_entries, num_txt_entries, txt, sizeof(txt));
+       if (ret != THREAD_ERROR_NONE) {
+               THREAD_DBG("socket srp_client_register_service_full encode txt entries failed");
+               return ret;
+       }
+
+       int len = snprintf(buffer, sizeof(buffer), "%s %s %s %u %u %u %s", msg,
+                               service_name, service_type, (int)port, (int)priority, (int)weight, txt);
+       /* Make sure that the socket command was not truncated. It might
+        * happen if the TXT record is too long. */
+       if (len > sizeof(buffer) - 1) {
+               THREAD_DBG("socket srp_client_register_service_full buffer overflow");
+               return THREAD_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = _thread_socket_client_execute(_thread_get_socket_fd(),
+                                               buffer, strlen(buffer));
+       if (ret != THREAD_ERROR_NONE && ret != THREAD_ERROR_ALREADY_DONE) {
+               THREAD_DBG("socket srp_client_register_service_full execute failed");
+               return ret;
+       }
+       THREAD_DBG("socket srp_client_register_service_full execute successful");
+
+       FUNC_EXIT;
+       return ret;
+}
+
 int thread_srp_client_remove_service(thread_instance_h instance,
        const char *service_name, const char *service_type)
 {
index a5b41bd..1265ee2 100644 (file)
@@ -238,3 +238,52 @@ void  _thread_dbus_method_cb(gboolean res, const char* method,
 
        FUNC_EXIT;
 }
+
+int _thread_encode_txt_entries(const thread_dns_txt_entry_s *txt_entries,
+                               uint8_t num_txt_entries, char *buffer, size_t buffer_size)
+{
+       FUNC_ENTRY;
+       int ret = THREAD_ERROR_NONE;
+
+       for (size_t i = 0; i < num_txt_entries; i++) {
+
+               /* calculate data length for DNS TXT entry as "key=value" */
+               size_t key_len = strlen(txt_entries[i].key);
+               size_t entry_len = key_len;
+               if (txt_entries[i].value != NULL)
+                       entry_len += 1 + txt_entries[i].value_len;
+               if (entry_len > 255) {
+                       THREAD_DBG("Invalid DNS TXT entry length: %zu > 255", entry_len);
+                       return THREAD_ERROR_INVALID_PARAMETER;
+               }
+
+               /* check if buffer is big enough to hold hex-encoded
+                * entry record and string null-terminator */
+               if (buffer_size < 2 * (entry_len + 1) + 1) {
+                       THREAD_DBG("Not enough space in buffer for hex-encoded TXT entries");
+                       return THREAD_ERROR_OUT_OF_MEMORY;
+               }
+
+               sprintf(&buffer[0], "%.2x", (int)entry_len);
+               for (size_t n = 0; n < key_len; n++)
+                       sprintf(&buffer[2 + 2 * n], "%.2x", txt_entries[i].key[n]);
+
+               buffer += 2 * (1 + key_len);
+               buffer_size -= 2 * (1 + key_len);
+
+               if (txt_entries[i].value != NULL) {
+
+                       sprintf(&buffer[0], "%.2x", (int)'=');
+                       for (size_t n = 0; n < txt_entries[i].value_len; n++)
+                               sprintf(&buffer[2 + 2 * n], "%.2x", txt_entries[i].value[n]);
+
+                       buffer += 2 * (1 + txt_entries[i].value_len);
+                       buffer_size -= 2 * (1 + txt_entries[i].value_len);
+
+               }
+
+       }
+
+       FUNC_EXIT;
+       return ret;
+}