text: /*******************************************
  Signaling LibWebSocket based API calls include file
  *******************************************/
  #ifndef __KINESIS_VIDEO_WEBRTC_LWS_API_CALLS__
  #define __KINESIS_VIDEO_WEBRTC_LWS_API_CALLS__
  
  #pragma once
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  // Timeout values
  #define SIGNALING_SERVICE_API_CALL_CONNECTION_TIMEOUT (2 * HUNDREDS_OF_NANOS_IN_A_SECOND)
  #define SIGNALING_SERVICE_API_CALL_COMPLETION_TIMEOUT (5 * HUNDREDS_OF_NANOS_IN_A_SECOND)
  #define SIGNALING_SERVICE_API_CALL_TIMEOUT_IN_SECONDS                                                                                                \
      ((SIGNALING_SERVICE_API_CALL_CONNECTION_TIMEOUT + SIGNALING_SERVICE_API_CALL_COMPLETION_TIMEOUT) / HUNDREDS_OF_NANOS_IN_A_SECOND)
  #define SIGNALING_SERVICE_TCP_KEEPALIVE_IN_SECONDS                3
  #define SIGNALING_SERVICE_TCP_KEEPALIVE_PROBE_COUNT               3
  #define SIGNALING_SERVICE_TCP_KEEPALIVE_PROBE_INTERVAL_IN_SECONDS 1
  #define SIGNALING_SERVICE_WSS_PING_PONG_INTERVAL_IN_SECONDS       10
  
  // Protocol indexes
  #define PROTOCOL_INDEX_HTTPS 0
  #define PROTOCOL_INDEX_WSS   1
  
  // API postfix definitions
  #define CREATE_SIGNALING_CHANNEL_API_POSTFIX       "/createSignalingChannel"
  #define DESCRIBE_SIGNALING_CHANNEL_API_POSTFIX     "/describeSignalingChannel"
  #define GET_SIGNALING_CHANNEL_ENDPOINT_API_POSTFIX "/getSignalingChannelEndpoint"
  #define DELETE_SIGNALING_CHANNEL_API_POSTFIX       "/deleteSignalingChannel"
  #define GET_ICE_CONFIG_API_POSTFIX                 "/v1/get-ice-server-config"
  
  // Signaling protocol name
  #define SIGNALING_CHANNEL_PROTOCOL "\"WSS\", \"HTTPS\""
  
  // Parameterized string for Describe Channel API
  #define DESCRIBE_CHANNEL_PARAM_JSON_TEMPLATE "{\n\t\"ChannelName\": \"%s\"\n}"
  
  // Parameterized string for Delete Channel API
  #define DELETE_CHANNEL_PARAM_JSON_TEMPLATE                                                                                                           \
      "{\n\t\"ChannelARN\": \"%s\","                                                                                                                   \
      "\n\t\"CurrentVersion\": \"%s\"\n}"
  
  // Parameterized string for Create Channel API
  #define CREATE_CHANNEL_PARAM_JSON_TEMPLATE                                                                                                           \
      "{\n\t\"ChannelName\": \"%s\","                                                                                                                  \
      "\n\t\"ChannelType\": \"%s\","                                                                                                                   \
      "\n\t\"SingleMasterConfiguration\": {"                                                                                                           \
      "\n\t\t\"MessageTtlSeconds\": %" PRIu64 "\n\t}"                                                                                                  \
      "%s\n}"
  
  // Parameterized string for each tag pair as a JSON object
  #define TAG_PARAM_JSON_OBJ_TEMPLATE "\n\t\t{\"Key\": \"%s\", \"Value\": \"%s\"},"
  
  // Parameterized string for TagStream API - we should have at least one tag
  #define TAGS_PARAM_JSON_TEMPLATE ",\n\t\"Tags\": [%s\n\t]"
  
  // Parameterized string for Get Channel Endpoint API
  #define GET_CHANNEL_ENDPOINT_PARAM_JSON_TEMPLATE                                                                                                     \
      "{\n\t\"ChannelARN\": \"%s\","                                                                                                                   \
      "\n\t\"SingleMasterChannelEndpointConfiguration\": {"                                                                                            \
      "\n\t\t\"Protocols\": [%s],"                                                                                                                     \
      "\n\t\t\"Role\": \"%s\""                                                                                                                         \
      "\n\t}\n}"
  
  // Parameterized string for Get Ice Server Config API
  #define GET_ICE_CONFIG_PARAM_JSON_TEMPLATE                                                                                                           \
      "{\n\t\"ChannelARN\": \"%s\","                                                                                                                   \
      "\n\t\"ClientId\": \"%s\","                                                                                                                      \
      "\n\t\"Service\": \"TURN\""                                                                                                                      \
      "\n}"
  
  // Parameter names for Signaling connect URL
  #define SIGNALING_ROLE_PARAM_NAME         "X-Amz-Role"
  #define SIGNALING_CHANNEL_NAME_PARAM_NAME "X-Amz-ChannelName"
  #define SIGNALING_CHANNEL_ARN_PARAM_NAME  "X-Amz-ChannelARN"
  #define SIGNALING_CLIENT_ID_PARAM_NAME    "X-Amz-ClientId"
  
  // Parameterized string for WSS connect
  #define SIGNALING_ENDPOINT_MASTER_URL_WSS_TEMPLATE "%s?%s=%s"
  #define SIGNALING_ENDPOINT_VIEWER_URL_WSS_TEMPLATE "%s?%s=%s&%s=%s"
  
  #define SIGNALING_SDP_TYPE_OFFER       "SDP_OFFER"
  #define SIGNALING_SDP_TYPE_ANSWER      "SDP_ANSWER"
  #define SIGNALING_ICE_CANDIDATE        "ICE_CANDIDATE"
  #define SIGNALING_GO_AWAY              "GO_AWAY"
  #define SIGNALING_RECONNECT_ICE_SERVER "RECONNECT_ICE_SERVER"
  #define SIGNALING_STATUS_RESPONSE      "STATUS_RESPONSE"
  
  // Max length of the signaling message type string length
  #define MAX_SIGNALING_MESSAGE_TYPE_LEN ARRAY_SIZE(SIGNALING_RECONNECT_ICE_SERVER)
  
  // Max value length for the status code
  #define MAX_SIGNALING_STATUS_MESSAGE_LEN 16
  
  // Send message JSON template
  #define SIGNALING_SEND_MESSAGE_TEMPLATE                                                                                                              \
      "{\n"                                                                                                                                            \
      "\t\"action\": \"%s\",\n"                                                                                                                        \
      "\t\"RecipientClientId\": \"%.*s\",\n"                                                                                                           \
      "\t\"MessagePayload\": \"%s\"\n"                                                                                                                 \
      "}"
  
  // Send message JSON template with correlation id
  #define SIGNALING_SEND_MESSAGE_TEMPLATE_WITH_CORRELATION_ID                                                                                          \
      "{\n"                                                                                                                                            \
      "\t\"action\": \"%s\",\n"                                                                                                                        \
      "\t\"RecipientClientId\": \"%.*s\",\n"                                                                                                           \
      "\t\"MessagePayload\": \"%s\",\n"                                                                                                                \
      "\t\"CorrelationId\": \"%.*s\"\n"                                                                                                                \
      "}"
  
  // Scratch buffer size
  #define LWS_SCRATCH_BUFFER_SIZE (MAX_JSON_PARAMETER_STRING_LEN + LWS_PRE)
  
  // Send and receive buffer size
  #define LWS_MESSAGE_BUFFER_SIZE (SIZEOF(CHAR) * (MAX_SIGNALING_MESSAGE_LEN + LWS_PRE))
  
  #define AWS_SIG_V4_HEADER_HOST (PCHAR) "host"
  
  #define BOOLEAN_LITERAL_TRUE  "true"
  #define BOOLEAN_LITERAL_FALSE "false"
  
  // Specifies whether to block on the correlation id
  #define BLOCK_ON_CORRELATION_ID FALSE
  
  // Service loop iteration wait time when there is an already servicing thread
  #define LWS_SERVICE_LOOP_ITERATION_WAIT (50 * HUNDREDS_OF_NANOS_IN_A_MILLISECOND)
  
  // Check for the stale credentials
  #define CHECK_SIGNALING_CREDENTIALS_EXPIRATION(p)                                                                                                    \
      do {                                                                                                                                             \
          if (GETTIME() >= (p)->pAwsCredentials->expiration) {                                                                                         \
              ATOMIC_STORE(&(p)->result, (SIZE_T) SERVICE_CALL_NOT_AUTHORIZED);                                                                        \
              CHK(FALSE, retStatus);                                                                                                                   \
          }                                                                                                                                            \
      } while (FALSE)
  
  /**
   * Index of the signaling protocol handling WSS
   * IMPORTANT!!! This should match the correct index in the
   * signaling client protocol array
   */
  #define WSS_SIGNALING_PROTOCOL_INDEX 1
  
  typedef struct __LwsCallInfo LwsCallInfo;
  struct __LwsCallInfo {
      // Size of the data in the buffer
      volatile SIZE_T sendBufferSize;
  
      // Offset from which to send data
      volatile SIZE_T sendOffset;
  
      // Service exit indicator;
      volatile ATOMIC_BOOL cancelService;
  
      // Protocol index
      UINT32 protocolIndex;
  
      // Call info object
      CallInfo callInfo;
  
      // Back reference to the signaling client
      PSignalingClient pSignalingClient;
  
      // Scratch buffer for http processing
      CHAR buffer[LWS_SCRATCH_BUFFER_SIZE];
  
      // Scratch buffer for sending
      BYTE sendBuffer[LWS_MESSAGE_BUFFER_SIZE];
  
      // Scratch buffer for receiving
      BYTE receiveBuffer[LWS_MESSAGE_BUFFER_SIZE];
  
      // Size of the data in the receive buffer
      UINT32 receiveBufferSize;
  };
  
  typedef struct {
      // The first member is the public signaling message structure
      ReceivedSignalingMessage receivedSignalingMessage;
  
      // The messaging client object
      PSignalingClient pSignalingClient;
  } SignalingMessageWrapper, *PSignalingMessageWrapper;
  
  // Signal handler routine
  VOID lwsSignalHandler(INT32);
  
  // Performs a blocking call
  STATUS lwsCompleteSync(PLwsCallInfo);
  
  // LWS listener handler
  PVOID lwsListenerHandler(PVOID);
  
  // Retry thread
  PVOID reconnectHandler(PVOID);
  
  // LWS callback routine
  INT32 lwsHttpCallbackRoutine(struct lws*, enum lws_callback_reasons, PVOID, PVOID, size_t);
  INT32 lwsWssCallbackRoutine(struct lws*, enum lws_callback_reasons, PVOID, PVOID, size_t);
  
  STATUS describeChannelLws(PSignalingClient, UINT64);
  STATUS createChannelLws(PSignalingClient, UINT64);
  STATUS getChannelEndpointLws(PSignalingClient, UINT64);
  STATUS getIceConfigLws(PSignalingClient, UINT64);
  STATUS connectSignalingChannelLws(PSignalingClient, UINT64);
  STATUS deleteChannelLws(PSignalingClient, UINT64);
  
  STATUS createLwsCallInfo(PSignalingClient, PRequestInfo, UINT32, PLwsCallInfo*);
  STATUS freeLwsCallInfo(PLwsCallInfo*);
  
  PVOID receiveLwsMessageWrapper(PVOID);
  
  STATUS sendLwsMessage(PSignalingClient, PCHAR, PCHAR, PCHAR, UINT32, PCHAR, UINT32);
  STATUS writeLwsData(PSignalingClient, BOOL);
  STATUS terminateLwsListenerLoop(PSignalingClient);
  STATUS receiveLwsMessage(PSignalingClient, PCHAR, UINT32);
  STATUS getMessageTypeFromString(PCHAR, UINT32, SIGNALING_MESSAGE_TYPE*);
  STATUS wakeLwsServiceEventLoop(PSignalingClient);
  STATUS terminateConnectionWithStatus(PSignalingClient, SERVICE_CALL_RESULT);
  
  #ifdef __cplusplus
  }
  #endif
  #endif /* __KINESIS_VIDEO_WEBRTC_LWS_API_CALLS__ */
  