This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

configure CC3100 listen to multiple connection on a same port

Other Parts Discussed in Thread: CC3100, CC3200SDK, CC3200

Hi Everyone,

How to set up the CC3100 to listen to multiple tcp/ip on a same port?

I did following

1. set the CC3100 to AP mode

2. call sl_Scocket: SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);

3. Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize);

4. Status = sl_Listen(SockID, 0); // _i16 sl_Listen(_i16 sd, _i16 backlog);

I changed the backlog parameter while calling sl_Listen to 5, 8. However, I always got 2 connections.

Here is backlog definition: "The backlog parameter defines the maximum length the queue of pending connections may grow to".

Thanks in advance!

  • Dieutan,

    Can you send a snippet of your code (where you create a server and listen for clients) for review? I tried connecting upto 6 clients on my setup and see no issue.

    -Praneet 

  • Hi Praneet,

    I saw you are using CC3200. Which example did you run. I could not find it in CC3200SDK_1.0.0.

    I used example from nwp_filters - CC3100 1.0.0 SDK , static _i32 BsdTcpServer(_u16 Port) funtion. The code is below:

    LocalAddr.sin_family = SL_AF_INET;
    LocalAddr.sin_port = sl_Htons((_u16)Port);
    LocalAddr.sin_addr.s_addr = 0;

    SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
    if( SockID < 0 )
    {
    CLI_Write(" [TCP Server] Create socket Error \n\r");
    ASSERT_ON_ERROR(SockID);
    }

    AddrSize = sizeof(SlSockAddrIn_t);
    Status = sl_Bind(SockID, (SlSockAddr_t *)&LocalAddr, AddrSize);
    if( Status < 0 )
    {
    sl_Close(SockID);
    CLI_Write(" [TCP Server] Socket address assignment Error \n\r");
    ASSERT_ON_ERROR(Status);
    }

    Status = sl_Listen(SockID, 0);
    if( Status < 0 )
    {
    sl_Close(SockID);
    CLI_Write(" [TCP Server] Listen Error \n\r");
    ASSERT_ON_ERROR(Status);
    }

    newSockID = sl_Accept(SockID, ( struct SlSockAddr_t *)&Addr,
    (SlSocklen_t*)&AddrSize);
    if( newSockID < 0 )
    {
    sl_Close(SockID);
    CLI_Write(" [TCP Server] Accept connection Error \n\r");
    ASSERT_ON_ERROR(newSockID);
    }

    timeVal.tv_sec = 1;
    timeVal.tv_usec = 0;
    if( newSockID >= 0 )
    {
    Status = sl_SetSockOpt(newSockID, SL_SOL_SOCKET, SL_SO_RCVTIMEO,
    &timeVal, sizeof(timeVal));
    if( Status < 0 )
    {
    sl_Close(SockID);
    sl_Close(newSockID);
    CLI_Write(" [TCP Server] set socket option Error \n\r");
    ASSERT_ON_ERROR(Status);
    }
    }

    while (LoopCount < NO_OF_PACKETS)
    {
    recvSize = BUF_SIZE;

    do
    {
    Status = sl_Recv(newSockID, &uBuf.BsdBuf[BUF_SIZE - recvSize], recvSize, 0);
    if( Status <= 0 )
    {
    sl_Close(newSockID);
    sl_Close(SockID);
    CLI_Write(" [TCP Server] Data recv Error \n\r");
    ASSERT_ON_ERROR(TCP_RECV_ERROR);
    }
    recvSize -= Status;

    }while(recvSize > 0);

    LoopCount++;
    }

  • Hi Everyone,

    I have another question on how to handle disconnection on 1 connection from client in multiple connections situation.

    For example I have 4 active connections with client Socket ID: 1, 2, 3, and 4. Client with socket ID 2 disconnected; which event comes to host to let the host know the client connection with socket ID 2 was disconnected.

    Thanks in advance! 

  • Firstly, I don't see you accepting multiple client connections - Your snippet accepts only one connection and gets into a loop to receive data from that client. And when you modify the code to accept multiple connections, I suggest you set the 'backlog' param of 'sl_Listen' to 7.

    The device doesn't send any async-events when a client gets disconnected. However, a blocking call on that socket-ID will return '0' if one end of the socket is broken.

    -Praneet

     

  • Hi Praneet,

    Could you send me your CC3200 example you showed above?

    Could you confirm: when a disconnection is  initiated at client side , host server connection won't be notified?

    I have another question: How does host MCU server know if a client sends a packet to the server? In other words, the packet is initiated from client  and transmit to Host MCU server. For example after I make a http connection from a web browser (I am using my own http server, the CC3100 webserver is disabled); web browser sends a get request. How does CC3100 notify to host MCU that there is a packet for a specific socket?

    I don't want to use sl_recv because of it is wasting resource and most of the time the call will return SL_EAGAIN. I don't want to use polling method; I would like to use interrupter driven.

    Thanks,

    Dennis

     

  • Hi Dennis,

    • Socket level interrupt
      • The current socket level interrupt is located in the function SimpleLinkSockEventHandler. The API can be found here by navigating to Moduels -> UserEvents -> sl_SockEvtHdlr
      • As of right now, the only two supported interrupt at this level are SL_SOCKET_TX_FAILED_EVENT and SL_SOCKET_ASYNC_EVENT. Receiving interrupt is not supported. You'll have to proceed with the way with looping through all sockets and check with sl_Recv().
    • SPI Host communication low level bytes
      • Sorry but this information cannot be disclosed. The most we can provide are the synchronization bytes and higher level API with the use of Simplelink library. These low level bytes are abstracted away and not meant to be read by developers outside of TI.
  • Hi Victor,

    Thanks for the information. It is not easy to work with un-supported events and without handshake protocol - low level bytes.

    Hi Everyone,

    I made some changes in my example code to accept multiple tcp/ip connections.

    My question are:

    1. After one specific socket ID client disconnected, how can I open and accept socket ID for next time the socket ID client connect back? From my test, I can open up to 7 connections from clients, however after disconnect one of them, I cannot make another connection, in this case, there are only 6 connections left.

    2. The eight connection is not reject right away. Client has to wait for time out. How to fix this issue?

    Here is my code:

    _i16 g_clientSockID[8] = {0};

    Status = sl_Listen(SockID, 7);

    if (0 > Status)

    {
    sl_Close(SockID);
    ASSERT_ON_ERROR(Status);
    }

    while (LoopCount < NO_OF_PACKETS)
    {
    // Service 8 tcp/ip connections
    for (i = 0; i < 8; i++) {

    recvSize = BUF_SIZE;
    if ((0 == g_clientSockID[i]) || (SL_EAGAIN == g_clientSockID[i])) {
    g_clientSockID[i] = sl_Accept(SockID, ( struct SlSockAddr_t *)&Addr,
    (SlSocklen_t*)&AddrSize);
    }

    if(SL_EAGAIN == g_clientSockID[i]) {
    //CLI_Write(" [TCP Server] SL_EAGAIN\n\r");
    ;
    }
    else if(SL_ENSOCK == g_clientSockID[i]) {
    //CLI_Write(" [TCP Server] SL_ENSOCK\n\r");
    ;
    }
    else if (0 > g_clientSockID[i]) {
    sl_Close(SockID);
    CLI_Write(" [TCP Server] Accept connection Error \n\r");
    ASSERT_ON_ERROR(g_clientSockID[i]);
    }

    else {
    // tcp Connected, read data
    Status = sl_Recv(g_clientSockID[i], &(uBuf.BsdBuf[BUF_SIZE - recvSize]), recvSize, 0);
    if(SL_EAGAIN == Status) {
    //CLI_Write(" [TCP status] SL_EAGAIN\n\r");
    ;
    }
    else if(0 > Status)
    {
    sl_Close(g_clientSockID[i]);
    sl_Close(SockID);
    ASSERT_ON_ERROR(TCP_RECV_ERROR);
    }
    else if(0 < Status) {
    CLI_Write("[TCP Server] data received \n\r");
    LoopCount++;
    }
    else {
    /* Already disconnected */
    g_clientSockID[i] = 0;
    }
    }
    }
    }

    Thanks!

  • Victor, earlier you wrote:

    • SPI Host communication low level bytes
      • Sorry but this information cannot be disclosed. The most we can provide are the synchronization bytes and higher level API with the use of Simplelink library. These low level bytes are abstracted away and not meant to be read by developers outside of TI.

    Does this mean that a "behind-the-API" message structure Technical Reference Manual will not be forthcoming?  For a rough example, something like:

    All message byte values are in HEX:

    Connect TCP port 80 to openweathermap.org
    -----------------------------------------
    06 94          SL_OPCODE_SOCKET_CONNECT
    0C 00          message length
    00 00          padding
    10             socket number
    20             family and flags
    00 50          port 80, high byte first.
    CC CC          padding
    90 4C 66 A6    IPv4 address

  • Michael,

    The message example you provided is the standard TCP packet, and TI follows the guideline thoroughly. However, the SPI communication between host and CC3100 cannot be disclosed at this time. This may be subject to change in the future.

  • It is also ( minus the SYNC word) what is byte-for-byte sent by my host to the CC3100 booster pack over SPI interface. The same sequence would go over UART, should that interface be used instead (again, modulo the long SYNC word in that case). I suspect I may be misinterpreting your original comment.

  • Hi Michael,

    The data going through either UART or SPI should be identical. However, it's the data that we cannot disclose. You are certainly welcome to perform reverse engineering to get the message. The most we can provide right now is the SYNC word in order to make sure the communication channel is established.

  • Hi Everyone,

    I would like to set up my host application with 3 tcp/ip servers. one connection for telnet port #23, one connection for websocket port #8080, and 4 connections for web server port #80.

    After call socket, bind for each server I call sl_Listen for each server as following:

    Status = sl_Listen(tenet_SockID, 1);

    Status = sl_Listen(ws_SockID, 1);

    Status = sl_Listen(http_SockID, 4);

    I used clients to connect to three 3 servers with different scenarios:

    A. After 1 telnet, 1 websocket, 1 http connection established, I could not make any more http connect. question in this case: where are other 3 listening connections? (maximum of 3 connections?)

    B. Established 1 telnet, and another telnet connection = total of 2 telnet connections. Question: while I set backlog == 1.  sl_Listen(tenet_SockID, 1); Why the CC3100 accepted 2 telnet connections. (As same as when I try 2 websocket connections).

    C. Establish 3 http connections. Tried fourth http connection -> failed. Question: why does  CC3100 only allow 3 connections in this case?

    In 3 scenarios above, I could make only 3 connections. Where were other 5 sockets? Did they subtracted because I already used for listening on 3 sockets? I think they should not. CC3100 should provides 8 clients sockets besides sockets which servers listening.

    Thanks in advance!

  • Dennis,

    CC3x00 supports a maximum of 8 opened sockets. Two points to note here:

    - A socket is taken when 'sl_Listen' is called on a server-socket

    - A socket is taken when 'sl_Accept' is called on a server-socket, pending for a client connection

    Meaning, when you open a server-socket and do an sl_Listen and sl_Accept on it, you have consumed 2 sockets, even if no clients are connected. The connected client will take the pending socket that was created at 'sl_Accept'

    Responses to your Qs below:

    A>> Your three sever have taken 6 sockets initially (assuming you called 'sl_Listen' and sl_Accept' on them) - Now, when three clients are connected, you still have two sockets left. Do you call 'sl_Accept' again on 'tenet_SockID' and 'ws_SockID' after a client is connected? If yes, you are left w/ no free sockets for accepting cleints on 'http_SockID'.

    B>> The second parameter of 'sl_Listen' is 'backlog' and not the 'maximum client connections'. Please refer the API defination for more details. Let me know if you need additional information on this.

    C>> Two unused servers on 'tenet_SockID' and 'ws_SockID' have taken 4 sockets already. You then have a server on 'http_SockID' with three clients, which take another 4 sockets. Done..! You are left with no more free sockets.

    -/Praneet

  • Praneet,

    Thanks for the information.

    Normally server sockets do not count; but they are counted in this case. As I understand,  if host cpu opens 3 server sockets, there are only 5 client sockets left. I have been using other wifi module and they don't count server sockets.

    Questions:

    1. If backlog is not maximum clients connection. How can I set up one server socket accept only one client connection, other server socket accept 3 client sockets?

    2. After the maximum client connections are made. How do I set up the CC3100 reject the client attempt connection right away? Client does not have to wait for connection timeout? IN other word, if there is no connection available, CC3100 has to reject the connection immediately.

    Regards,

    Dennis

  • Dennis,

    A1&2>> I don't think there is a way to set max client connections w/ BSD sockets as well. This shall fall in your application'sdomain - Keep a track of connected clients and don't accept further connections if your thresholds are reached.

    -/Praneet

  • Praneet,

    If the host don't accept a second socket connection, does CC3100 accept or reject the connection?  I saw the CC3100 accepted second connection and the host did not know about it.

    Dennis

  • Hi Dennis,

    The host has to call an accept, for it to know about the connection request. Can you please confirm that this second connection was not intended for the internal HTTP server? This could be the reason why you see a SYN,ACK and yet the host is not notified.

    Regards,
    Raghavendra

  • Hi Raghavendra,

    Here is one scenario, The host MCU expect 1 connect only, so it accept the first connection if a client initiate a connection. If another client initiates a new connection to same port, CC3100 accepts the connection; host MCU won't accept the connection because it is set up to accept only one connection. 

    1. The second client expects host MCU start transfer data but there is no data in this case.

    2. If the host listen to other ports upto maximum number of sockets, in this scenario, it lost a socket to the above port.

    My host setup to listen 1 telnet, 1 websocket, and 3 http sockets.

    These are my questions:

    1. How to set up CC3100 listen to specific number of sockets. For example if I need to listen only one socket: sl_Listen(SockID, 1);
    2. From sl_Listen(SockID, backlog) function, backlog is not specified how many socket is accepting, if MCU don't accept a connection, how CC3100 reject a connection? I saw the CC3100 allowed a client connect but MCU did not know about it.
    3. If there is no socket available, CC3100 reject or timeout upon new connection from client? I saw the CC3100 timeout, my client socket can't wait for timeout.
    4. Is there any document on multiple tcp/ip connection?
    5. How TI test the multiple tcp/ip connection function? any example code? I do few tests and they hang.

    Thanks,

    Dennis

  • Hi Dennis,

    Please find my responses to your queries:

    1. If you need to listen to only one socket then please call accept only once over that port. Limiting the number of connections should be handled at the application.

    2. On the same port, it should allow up to 7 client connections, with one socket taken by the listening socket. For the case where you saw a "client connect but MCU did not know about it", can you please share the exact code snippet that you are using? Also, are you able to reproduce this all the time?

    3. If no sockets are available, then the next accept call should fail with error code SL_ENSOCK.

    4&5. Is your example code different from the one that you have posted already? If yes, then can you please share your example code/code snippet that hangs? So that we can try it here?

    Regards,
    Raghavendra

  • Hi Raghavendra,

    1. My host accepts 1 connection, How CC3100 handle the second connection? Does CC3100 still accept the second connection?

    2. Can you send me your test code for multiple connections?

    3. I saw a client wait for time out.

    4. I need to know how TI handle the multiple connections.

    5. Yes, My code changed. 

    0160.cc3100_code_example.c
    _i32 wifi_service_socket(_i16 *serverSockID, _i16 *clientSockID,
                             WIFI_SOCKET_STATUS_E *sockStatus)
    {
        SlSockAddrIn_t  Addr;
        SlSockAddrIn_t  LocalAddr;
    
        _u16 idx = 0;
        _u16 AddrSize = 0;
    
        _i16 i = 0;
        _i32 Status = 0;
        _i16 recvSize = 0;
    
        *sockStatus = WIFI_SOCKET_INACTIVE;
    
        recvSize = BUF_SIZE;
        if (NETWORK_NO_SOCKET == *clientSockID) {
            *clientSockID = sl_Accept(*serverSockID, ( struct SlSockAddr_t *)&Addr,
                                      (SlSocklen_t*)&AddrSize);
    
            if (0 < *clientSockID) {
                *sockStatus = WIFI_SOCKET_CONNECT;
    
                return SUCCESS;
            }
        }
    
        if ((SL_EAGAIN == *clientSockID) ||
            (SL_ENSOCK == *clientSockID) ||
            (SL_POOL_IS_EMPTY == *clientSockID) ||
            (SL_INEXE == *clientSockID)) {
            CLI_Write(" [TCP Server] SL_EAGAIN\n\r");
            *clientSockID = NETWORK_NO_SOCKET;
        }
        else if (0 > *clientSockID) {
            sl_Close(*clientSockID);
            *serverSockID = NETWORK_NO_SOCKET;
    
            send_uart_string_hex(SERIALIN, (char *)clientSockID, 1);
            CLI_Write(" [TCP Server] Accept connection Error \n\r");
            ASSERT_ON_ERROR(*clientSockID);
        }
        else {
    
            /* Connection had been made */
            Status = sl_Recv(*clientSockID, &(uBuf.BsdBuf[BUF_SIZE - recvSize]), recvSize, 0);
            if (0 < Status) {
    
                /* There is data */
                *sockStatus = WIFI_SOCKET_DATA;
                g_recvSize  = Status;
    
            }
            else if ((Status != SL_EAGAIN) && (Status != SL_POOL_IS_EMPTY)) {
                /* connection closed */
                CLI_Write("status == 0\n\r");
    
                /* Already disconnected */
                Status = sl_Close(*clientSockID);
                *clientSockID = NETWORK_NO_SOCKET;
    
                *sockStatus = WIFI_SOCKET_DISCONNECT;
            }
            else {
                /* Timeout ??? */
                *sockStatus = WIFI_SOCKET_TIMEOUT;
            }
        }
    
        return SUCCESS;
    }
    
    void telnet_server_service_request(void)
    {
        signed short retVal = 0;
    
        WIFI_SOCKET_STATUS_E sockStatus = 0;
    
        __eds__ unsigned char *temp_data_out_ptr = NULL;
        TELNET_SERVER_CB *telnet_cb_ptr, *top_telnet_ptr;
    
    
        top_telnet_ptr = &telnet_server_cb[TELNET_PORT_CT];
        for (telnet_cb_ptr = &telnet_server_cb[0];
            telnet_cb_ptr < top_telnet_ptr; telnet_cb_ptr++) {
    
            wifi_service_socket(&g_telnet_SockID,
                                &telnet_cb_ptr->tcp_socket_index,
                                &sockStatus);
    
            switch (sockStatus) {
                case WIFI_SOCKET_CONNECT:
                    /* Connected */
                    send_uart_string(SERIALIN, "TN Conn\r\n", 9);
                    telnet_cb_ptr->telnet_session_state = TELNET_CONNECTED;
    
                    ImsNetConnected = TRUE;
    
                    break;
                case WIFI_SOCKET_DISCONNECT:
                    /* Disconnected */
                    reset_single_telnet_cb(telnet_cb_ptr);
    
                    // if no telnet connect ???
                    ImsNetConnected = FALSE;
                    break;
                case WIFI_SOCKET_DATA:
    
                    if (TELNET_CONNECTED == telnet_cb_ptr->telnet_session_state) {
                        /* Has data */
                        wifi_read_data_eds(&telnet_cb_ptr->cmd_in_ptr,
                                           telnet_cb_ptr->cmd_top,
                                           telnet_cb_ptr->cmd_base,
                                           &telnet_cb_ptr->cmd_ct);
                    }
                    else {
                        telnet_cb_ptr->telnet_session_state = TELNET_DISCONN_REQUESTED;
                    }
    
                    break;
                case WIFI_SOCKET_TIMEOUT:
                    /* Timeout */
                    break;
                case WIFI_SOCKET_INACTIVE:
                    break;
    
                default:
                    break;
            }
    
            switch (telnet_cb_ptr->telnet_session_state) {
                case TELNET_CONNECTED:
                    if (0 < telnet_cb_ptr->cmd_ct) {
    
                        telnet_process_cmd(telnet_cb_ptr);
                    }
    
                    if (telnet_cb_ptr->data_ct) {
    
                        retVal = wifi_write_data_eds(telnet_cb_ptr->data_out_ptr,
                                                     telnet_cb_ptr->data_top,
                                                     telnet_cb_ptr->data_base,
                                                     telnet_cb_ptr->data_ct,
                                                     telnet_cb_ptr->tcp_socket_index);
    
                        if (0 < retVal) {
                            telnet_cb_ptr->data_ct -= retVal;
    
                            temp_data_out_ptr = telnet_cb_ptr->data_out_ptr + retVal;
                            if (temp_data_out_ptr >= telnet_cb_ptr->data_top) {
                                telnet_cb_ptr->data_out_ptr = telnet_cb_ptr->data_base +
                                                              (retVal -
                                                               (telnet_cb_ptr->data_top - telnet_cb_ptr->data_out_ptr));
                            }
                            else {
                                telnet_cb_ptr->data_out_ptr = temp_data_out_ptr;
                            }
                        }
                        else {
                            //????
                            telnet_cb_ptr->data_ct = 0;
                        }
                    }
                    break;
    
                case TELNET_DISCONN_REQUESTED:
                    if (0 == telnet_cb_ptr->data_ct) {
                        retVal = sl_Close(telnet_cb_ptr->tcp_socket_index);
                        if (0 == retVal) {
                            telnet_cb_ptr->telnet_session_state = TELNET_DISCONN_SENT;
                            telnet_cb_ptr->telnetTmrTick = TEN_S_PER_TEN_MS;
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }
    
    _i32 wifi_write_data_eds(__eds__ _u8 *src_ptr, __eds__ _u8 *top_ptr,
                             __eds__ _u8 *base_ptr, _u16 dataLength,
                             _i16 clientSockID)
    {
        _i32 retVal = -1;
        _i16 i = 0;
        _u8 *dstDataPtr = NULL;
    
        dstDataPtr = &uBuf.BsdBuf[0];
    
        for (i = 0; i < BUF_SIZE && i < dataLength; i++, dstDataPtr++) {
    
            *dstDataPtr = *src_ptr;
    
            src_ptr++;
            if (src_ptr == top_ptr) {
                src_ptr = base_ptr;
            }
        }
    
        retVal = sl_Send(clientSockID, &(uBuf.BsdBuf[0]), i, 0);
    
        return retVal;
    }
    
    

    Regards,

    Dennis

  • Hi Raghavendra,

    Maintenance team broke a link to uploaded file.

    Here the code again:

    _i32 wifi_service_socket(_i16 *serverSockID, _i16 *clientSockID,
                             WIFI_SOCKET_STATUS_E *sockStatus)
    {
        SlSockAddrIn_t  Addr;
        SlSockAddrIn_t  LocalAddr;
    
        _u16 idx = 0;
        _u16 AddrSize = 0;
    
        _i16 i = 0;
        _i32 Status = 0;
        _i16 recvSize = 0;
    
        *sockStatus = WIFI_SOCKET_INACTIVE;
    
        recvSize = BUF_SIZE;
        if (NETWORK_NO_SOCKET == *clientSockID) {
            *clientSockID = sl_Accept(*serverSockID, ( struct SlSockAddr_t *)&Addr,
                                      (SlSocklen_t*)&AddrSize);
    
            if (0 < *clientSockID) {
                *sockStatus = WIFI_SOCKET_CONNECT;
    
                return SUCCESS;
            }
        }
    
        if ((SL_EAGAIN == *clientSockID) ||
            (SL_ENSOCK == *clientSockID) ||
            (SL_POOL_IS_EMPTY == *clientSockID) ||
            (SL_INEXE == *clientSockID)) {
            CLI_Write(" [TCP Server] SL_EAGAIN\n\r");
            *clientSockID = NETWORK_NO_SOCKET;
        }
        else if (0 > *clientSockID) {
            sl_Close(*clientSockID);
            *serverSockID = NETWORK_NO_SOCKET;
    
            send_uart_string_hex(SERIALIN, (char *)clientSockID, 1);
            CLI_Write(" [TCP Server] Accept connection Error \n\r");
            ASSERT_ON_ERROR(*clientSockID);
        }
        else {
    
            /* Connection had been made */
            Status = sl_Recv(*clientSockID, &(uBuf.BsdBuf[BUF_SIZE - recvSize]), recvSize, 0);
            if (0 < Status) {
    
                /* There is data */
                *sockStatus = WIFI_SOCKET_DATA;
                g_recvSize  = Status;
    
            }
            else if ((Status != SL_EAGAIN) && (Status != SL_POOL_IS_EMPTY)) {
                /* connection closed */
                CLI_Write("status == 0\n\r");
    
                /* Already disconnected */
                Status = sl_Close(*clientSockID);
                *clientSockID = NETWORK_NO_SOCKET;
    
                *sockStatus = WIFI_SOCKET_DISCONNECT;
            }
            else {
                /* Timeout ??? */
                *sockStatus = WIFI_SOCKET_TIMEOUT;
            }
        }
    
        return SUCCESS;
    }
    
    void telnet_server_service_request(void)
    {
        signed short retVal = 0;
    
        WIFI_SOCKET_STATUS_E sockStatus = 0;
    
        __eds__ unsigned char *temp_data_out_ptr = NULL;
        TELNET_SERVER_CB *telnet_cb_ptr, *top_telnet_ptr;
    
    
        top_telnet_ptr = &telnet_server_cb[TELNET_PORT_CT];
        for (telnet_cb_ptr = &telnet_server_cb[0];
            telnet_cb_ptr < top_telnet_ptr; telnet_cb_ptr++) {
    
            wifi_service_socket(&g_telnet_SockID,
                                &telnet_cb_ptr->tcp_socket_index,
                                &sockStatus);
    
            switch (sockStatus) {
                case WIFI_SOCKET_CONNECT:
                    /* Connected */
                    send_uart_string(SERIALIN, "TN Conn\r\n", 9);
                    telnet_cb_ptr->telnet_session_state = TELNET_CONNECTED;
    
                    ImsNetConnected = TRUE;
    
                    break;
                case WIFI_SOCKET_DISCONNECT:
                    /* Disconnected */
                    reset_single_telnet_cb(telnet_cb_ptr);
    
                    // if no telnet connect ???
                    ImsNetConnected = FALSE;
                    break;
                case WIFI_SOCKET_DATA:
    
                    if (TELNET_CONNECTED == telnet_cb_ptr->telnet_session_state) {
                        /* Has data */
                        wifi_read_data_eds(&telnet_cb_ptr->cmd_in_ptr,
                                           telnet_cb_ptr->cmd_top,
                                           telnet_cb_ptr->cmd_base,
                                           &telnet_cb_ptr->cmd_ct);
                    }
                    else {
                        telnet_cb_ptr->telnet_session_state = TELNET_DISCONN_REQUESTED;
                    }
    
                    break;
                case WIFI_SOCKET_TIMEOUT:
                    /* Timeout */
                    break;
                case WIFI_SOCKET_INACTIVE:
                    break;
    
                default:
                    break;
            }
    
            switch (telnet_cb_ptr->telnet_session_state) {
                case TELNET_CONNECTED:
                    if (0 < telnet_cb_ptr->cmd_ct) {
    
                        telnet_process_cmd(telnet_cb_ptr);
                    }
    
                    if (telnet_cb_ptr->data_ct) {
    
                        retVal = wifi_write_data_eds(telnet_cb_ptr->data_out_ptr,
                                                     telnet_cb_ptr->data_top,
                                                     telnet_cb_ptr->data_base,
                                                     telnet_cb_ptr->data_ct,
                                                     telnet_cb_ptr->tcp_socket_index);
    
                        if (0 < retVal) {
                            telnet_cb_ptr->data_ct -= retVal;
    
                            temp_data_out_ptr = telnet_cb_ptr->data_out_ptr + retVal;
                            if (temp_data_out_ptr >= telnet_cb_ptr->data_top) {
                                telnet_cb_ptr->data_out_ptr = telnet_cb_ptr->data_base +
                                                              (retVal -
                                                               (telnet_cb_ptr->data_top - telnet_cb_ptr->data_out_ptr));
                            }
                            else {
                                telnet_cb_ptr->data_out_ptr = temp_data_out_ptr;
                            }
                        }
                        else {
                            //????
                            telnet_cb_ptr->data_ct = 0;
                        }
                    }
                    break;
    
                case TELNET_DISCONN_REQUESTED:
                    if (0 == telnet_cb_ptr->data_ct) {
                        retVal = sl_Close(telnet_cb_ptr->tcp_socket_index);
                        if (0 == retVal) {
                            telnet_cb_ptr->telnet_session_state = TELNET_DISCONN_SENT;
                            telnet_cb_ptr->telnetTmrTick = TEN_S_PER_TEN_MS;
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }
    
    _i32 wifi_write_data_eds(__eds__ _u8 *src_ptr, __eds__ _u8 *top_ptr,
                             __eds__ _u8 *base_ptr, _u16 dataLength,
                             _i16 clientSockID)
    {
        _i32 retVal = -1;
        _i16 i = 0;
        _u8 *dstDataPtr = NULL;
    
        dstDataPtr = &uBuf.BsdBuf[0];
    
        for (i = 0; i < BUF_SIZE && i < dataLength; i++, dstDataPtr++) {
    
            *dstDataPtr = *src_ptr;
    
            src_ptr++;
            if (src_ptr == top_ptr) {
                src_ptr = base_ptr;
            }
        }
    
        retVal = sl_Send(clientSockID, &(uBuf.BsdBuf[0]), i, 0);
    
        return retVal;
    }