text: /**************************************************************************/
  /*                                                                        */
  /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
  /*                                                                        */
  /*       This software is licensed under the Microsoft Software License   */
  /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
  /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
  /*       and in the root directory of this software.                      */
  /*                                                                        */
  /**************************************************************************/
  
  
  /**************************************************************************/
  /**************************************************************************/
  /**                                                                       */
  /** NetX Component                                                        */
  /**                                                                       */
  /**   Transmission Control Protocol (TCP) for STM32L475E-IOT01A1          */
  /**                                                                       */
  /**************************************************************************/
  /**************************************************************************/
  
  #define NX_SOURCE_CODE
  
  
  /* Include necessary system files.  */
  
  #include "nx_api.h"
  #include "nx_ip.h"
  #include "nx_tcp.h"
  
  /**************************************************************************/
  /*                                                                        */
  /*  FUNCTION                                               RELEASE        */
  /*                                                                        */
  /*    _nx_tcp_socket_create                               PORTABLE C      */
  /*                                                           6.0          */
  /*  AUTHOR                                                                */
  /*                                                                        */
  /*    Yuxin Zhou, Microsoft Corporation                                   */
  /*                                                                        */
  /*  DESCRIPTION                                                           */
  /*                                                                        */
  /*    This function creates a TCP socket for the specified IP instance.   */
  /*    Both client and server sockets are created by this service.         */
  /*                                                                        */
  /*  INPUT                                                                 */
  /*                                                                        */
  /*    ip_ptr                                IP instance pointer           */
  /*    socket_ptr                            Pointer to new TCP socket     */
  /*    name                                  Name of new TCP socket        */
  /*    type_of_service                       Type of service for this TCP  */
  /*                                            socket                      */
  /*    fragment                              Flag to enable IP fragmenting */
  /*    time_to_live                          Time to live value for socket */
  /*    window_size                           Size of socket's receive      */
  /*                                            window                      */
  /*    tcp_urgent_data_callback              Routine to call when urgent   */
  /*                                            data is received            */
  /*    tcp_disconnect_callback               Routine to call when a        */
  /*                                            disconnect occurs           */
  /*                                                                        */
  /*  OUTPUT                                                                */
  /*                                                                        */
  /*    status                                Completion status             */
  /*                                                                        */
  /*  CALLS                                                                 */
  /*                                                                        */
  /*    tx_mutex_get                          Obtain protection             */
  /*    tx_mutex_put                          Release protection            */
  /*                                                                        */
  /*  CALLED BY                                                             */
  /*                                                                        */
  /*    Application Code                                                    */
  /*                                                                        */
  /*  RELEASE HISTORY                                                       */
  /*                                                                        */
  /*    DATE              NAME                      DESCRIPTION             */
  /*                                                                        */
  /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
  /*                                                                        */
  /**************************************************************************/
  UINT  _nx_tcp_socket_create(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, CHAR *name,
                              ULONG type_of_service, ULONG fragment, UINT time_to_live, ULONG window_size,
                              VOID (*tcp_urgent_data_callback)(NX_TCP_SOCKET *socket_ptr),
                              VOID (*tcp_disconnect_callback)(NX_TCP_SOCKET *socket_ptr))
  {
  TX_INTERRUPT_SAVE_AREA
  
  NX_TCP_SOCKET *tail_ptr;
  
  
      /* Initialize the TCP control block to zero.  */
      memset((void *)socket_ptr, 0, sizeof(NX_TCP_SOCKET));
  
      /* Fill in the basic information in the new TCP socket structure.  */
  
      /* Remember the associated IP structure.  */
      socket_ptr -> nx_tcp_socket_ip_ptr =  ip_ptr;
  
      /* By default, indicate the socket is a client socket.  */
      socket_ptr -> nx_tcp_socket_client_type =  NX_TRUE;
  
      /* Save the TCP socket's name.  */
      socket_ptr -> nx_tcp_socket_name =  name;
  
      /* Setup the counter for duplicated ACK packet.  */
      socket_ptr -> nx_tcp_socket_duplicated_ack_received = 0;
  
      /* Setup this socket's maximum segment size (mss).  */
      socket_ptr -> nx_tcp_socket_mss = 0;
  
      /* Setup the default receiver's maximum segment size.  */
      socket_ptr -> nx_tcp_socket_connect_mss =  NX_TCP_MSS_SIZE;
  
      /* Save the type of service input parameter.  */
      socket_ptr -> nx_tcp_socket_type_of_service =  type_of_service;
  
      /* Save the fragment input parameter.  */
      socket_ptr -> nx_tcp_socket_fragment_enable =  fragment & NX_DONT_FRAGMENT;
  
      /* Save the time-to-live input parameter.  */
      socket_ptr -> nx_tcp_socket_time_to_live =  time_to_live;
  
      /* Clear the socket bind in progress flag.  */
      socket_ptr -> nx_tcp_socket_bind_in_progress =  NX_FALSE;
  
      /* Setup the delayed ACK timeout periodic rate.  */
      socket_ptr -> nx_tcp_socket_delayed_ack_timeout =  _nx_tcp_ack_timer_rate;
  
      /* Setup the default transmit timeout.  */
      socket_ptr -> nx_tcp_socket_timeout_rate =         _nx_tcp_transmit_timer_rate;
      socket_ptr -> nx_tcp_socket_timeout_max_retries =  NX_TCP_MAXIMUM_RETRIES;
      socket_ptr -> nx_tcp_socket_timeout_shift =        NX_TCP_RETRY_SHIFT;
  
      /* Setup the default maximum transmit queue depth.  */
      socket_ptr -> nx_tcp_socket_transmit_queue_maximum_default =  NX_TCP_MAXIMUM_TX_QUEUE;
      socket_ptr -> nx_tcp_socket_transmit_queue_maximum =          NX_TCP_MAXIMUM_TX_QUEUE;
  
  #ifdef NX_ENABLE_LOW_WATERMARK
      /* Setup the default maximum receive queue depth.  */
      socket_ptr -> nx_tcp_socket_receive_queue_maximum = NX_TCP_MAXIMUM_RX_QUEUE;
  #endif /* NX_ENABLE_LOW_WATERMARK */
  
  #ifdef NX_ENABLE_TCP_WINDOW_SCALING
  
      /* Window scaling feature is enabled.  Record this user-specified window size. */
      socket_ptr -> nx_tcp_socket_rx_window_maximum = window_size;
  #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
  
      /* Setup the sliding window information.  */
      socket_ptr -> nx_tcp_socket_rx_window_default =   window_size;
      socket_ptr -> nx_tcp_socket_rx_window_current =   window_size;
      socket_ptr -> nx_tcp_socket_tx_outstanding_bytes = 0;
      socket_ptr -> nx_tcp_socket_tx_window_advertised = 0;
      socket_ptr -> nx_tcp_socket_tx_window_congestion = 0;
  
  
      /* Initialize the ack_n_packet counter. */
      socket_ptr -> nx_tcp_socket_ack_n_packet_counter = 1;
  
      /* Save the application callback routines.  */
      socket_ptr -> nx_tcp_urgent_data_callback = tcp_urgent_data_callback;
      socket_ptr -> nx_tcp_disconnect_callback =  tcp_disconnect_callback;
  
      /* Clear the receive notify function pointer.  */
      socket_ptr -> nx_tcp_receive_callback =  NX_NULL;
  
  #ifdef NX_ENABLE_TCP_KEEPALIVE
      /* If the Keep alive feature is enabled in NetX, enable it
         on all TCP sockets. */
      socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_TRUE;
  
  #endif
  
      /* If trace is enabled, insert this event into the trace buffer.  */
      NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_TCP_STATE_CHANGE, ip_ptr, socket_ptr, socket_ptr -> nx_tcp_socket_state, NX_TCP_CLOSED, NX_TRACE_INTERNAL_EVENTS, 0, 0);
  
      /* Setup the initial TCP socket state.  */
      socket_ptr -> nx_tcp_socket_state =  NX_TCP_CLOSED;
  
      /* If trace is enabled, register this object.  */
      NX_TRACE_OBJECT_REGISTER(NX_TRACE_OBJECT_TYPE_TCP_SOCKET, socket_ptr, name, type_of_service, window_size);
  
      /* If trace is enabled, insert this event into the trace buffer.  */
      NX_TRACE_IN_LINE_INSERT(NX_TRACE_TCP_SOCKET_CREATE, ip_ptr, socket_ptr, type_of_service, window_size, NX_TRACE_TCP_EVENTS, 0, 0);
  
      /* Get protection while we insert the TCP socket into the created list.  */
      tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
  
      /* Disable interrupts while we link the new TCP socket to the IP structure.  */
      TX_DISABLE
  
      /* Load the TCP ID field in the TCP control block.  */
      socket_ptr -> nx_tcp_socket_id =  NX_TCP_ID;
  
      /* Place the new TCP control block on the list of created TCP sockets for this IP.  First,
         check for an empty list.  */
      if (ip_ptr -> nx_ip_tcp_created_sockets_ptr)
      {
  
          /* Pickup tail pointer.  */
          tail_ptr =  (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous;
  
          /* Place the new TCP socket control block in the list.  */
          (ip_ptr -> nx_ip_tcp_created_sockets_ptr) -> nx_tcp_socket_created_previous =  socket_ptr;
          tail_ptr ->  nx_tcp_socket_created_next =  socket_ptr;
  
          /* Setup this TCP socket's created links.  */
          socket_ptr -> nx_tcp_socket_created_previous =  tail_ptr;
          socket_ptr -> nx_tcp_socket_created_next =      ip_ptr -> nx_ip_tcp_created_sockets_ptr;
      }
      else
      {
  
          /* The created TCP socket list is empty.  Add TCP socket control block to empty list.  */
          ip_ptr -> nx_ip_tcp_created_sockets_ptr =       socket_ptr;
          socket_ptr -> nx_tcp_socket_created_previous =  socket_ptr;
          socket_ptr -> nx_tcp_socket_created_next =      socket_ptr;
      }
  
      /* Increment the created TCP socket counter.  */
      ip_ptr -> nx_ip_tcp_created_sockets_count++;
  
      /* Restore previous interrupt posture.  */
      TX_RESTORE
  
      /* Release protection.  */
      tx_mutex_put(&(ip_ptr -> nx_ip_protection));
  
      /* Return successful completion.  */
      return(NX_SUCCESS);
  }
  
  