// This code configures the device into Access Point and also does the following:
// 1. Sets country code
// 2. Set Security settings
// 3. set static IP address
// 4. gets the list of connected stations


#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/net/wifi/slnetifwifi.h>

#include <ti/display/Display.h>

#include <ti/drivers/SPI.h>

// TI-Driver includes
#include "ti_drivers_config.h"
#include "pthread.h"
#include<string.h>

#define APPLICATION_NAME                      ("UDP Echo")
#define APPLICATION_VERSION                   ("1.0.0.0")
#define DEVICE_ERROR                          ("Device error, please refer \"DEVICE ERRORS CODES\" section in errors.h")
#define WLAN_ERROR                            ("WLAN error, please refer \"WLAN ERRORS CODES\" section in errors.h")
#define SL_STOP_TIMEOUT                       (200)

#define UDPPORT                               (1000)
#define SPAWN_TASK_PRIORITY                   (9)
#define TASK_STACK_SIZE                       (2048)
#define SLNET_IF_WIFI_PRIO                    (5)
#define SLNET_IF_WIFI_NAME                    "CC32xx"

/*#define SSID_NAME                             "DemoAP"                          // AP SSID
#define SECURITY_TYPE                         SL_WLAN_SEC_TYPE_WPA_WPA2         // Security type could be SL_WLAN_SEC_TYPE_OPEN
#define SECURITY_KEY                          "12345678"                        // Password of the secured AP*/

unsigned char SsId[] = "H_C_Trivedi";                                           // AP SSID
_u8 country_code[] = "US";                                                      // country code for regulatory domain
_u8 secutiry_type = SL_WLAN_SEC_TYPE_WPA_WPA2;                                  // update security parameters
_u8 security_password[] = "123456789";                                          // update security password
_u8 ApPower = 15;                                                               // set Tx power level
_u8 *device_name = "Trivedi";                                                   // set new name of the device
_u8 status = 0;

long counter1 = 0;
long counter2 = 0;

pthread_t udpThread = (pthread_t)NULL;
pthread_t spawn_thread = (pthread_t)NULL;
int32_t             mode;
Display_Handle display;

extern void echoFxn(uint32_t arg0, uint32_t arg1);
extern int32_t ti_net_SlNet_initConfig();

void get_device_config_parameters(void)
{
    printf("\n\n \r Getting device configuration parameters through get_device_config_parameters function!!");

    _u8 macAddressVal[SL_MAC_ADDR_LEN];
    _u16 macAddressLen = SL_MAC_ADDR_LEN;
    _u16 ConfigOpt1 = 0;
    sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET,&ConfigOpt1,&macAddressLen,(_u8 *)macAddressVal);
    printf("\n AP MAC address is: %02x:%02x:%02x:%02x:%02x:%02x", macAddressVal[0], macAddressVal[1], macAddressVal[2], macAddressVal[3], macAddressVal[4], macAddressVal[5]);

    _u16 len = sizeof(SlNetCfgIpV4Args_t);
    _u16 ConfigOpt2 = 0;  //return value could be one of the following: SL_NETCFG_ADDR_DHCP / SL_NETCFG_ADDR_DHCP_LLA / SL_NETCFG_ADDR_STATIC
    SlNetCfgIpV4Args_t ipV4 = {0};
    sl_NetCfgGet(SL_NETCFG_IPV4_AP_ADDR_MODE,&ConfigOpt2,&len,(_u8 *)&ipV4);
    printf("DHCP is %s \n\r IP %d.%d.%d.%d \n\r MASK %d.%d.%d.%d \n\r GW %d.%d.%d.%d \n\r DNS %d.%d.%d.%d \n",
        (ConfigOpt2 == SL_NETCFG_ADDR_DHCP) ? "ON" : "OFF",
        SL_IPV4_BYTE(ipV4.Ip,3),SL_IPV4_BYTE(ipV4.Ip,2),SL_IPV4_BYTE(ipV4.Ip,1),SL_IPV4_BYTE(ipV4.Ip,0),
        SL_IPV4_BYTE(ipV4.IpMask,3),SL_IPV4_BYTE(ipV4.IpMask,2),SL_IPV4_BYTE(ipV4.IpMask,1),SL_IPV4_BYTE(ipV4.IpMask,0),
        SL_IPV4_BYTE(ipV4.IpGateway,3),SL_IPV4_BYTE(ipV4.IpGateway,2),SL_IPV4_BYTE(ipV4.IpGateway,1),SL_IPV4_BYTE(ipV4.IpGateway,0),
        SL_IPV4_BYTE(ipV4.IpDnsServer,3),SL_IPV4_BYTE(ipV4.IpDnsServer,2),SL_IPV4_BYTE(ipV4.IpDnsServer,1),SL_IPV4_BYTE(ipV4.IpDnsServer,0));

    printf("\n");
    printf("\n");
}

/*
 *  ======== printError ========
 */
void printError(char *errString, int code)
{
    Display_printf(display, 0, 0, "Error! code = %d, Description = %s\n", code,
                   errString);
    while(1);
}

/*!
    \brief          SimpleLinkNetAppEventHandler

    This handler gets called whenever a Netapp event is reported by the host driver / NWP. Here user can implement he's own logic for any of these events. This handler is used by 'network_terminal' application to show case the following scenarios:
    1. Handling IPv4 / IPv6 IP address acquisition.
    2. Handling IPv4 / IPv6 IP address Dropping.

    \param          pNetAppEvent     -   pointer to Netapp event data.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 5.7
 */

void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
{
    int32_t             status = 0;
    pthread_attr_t      pAttrs;
    struct sched_param  priParam;

    if(pNetAppEvent == NULL)
    {
        return;
    }

    switch(pNetAppEvent->Id)
    {
    case SL_NETAPP_EVENT_IPV4_ACQUIRED:
    case SL_NETAPP_EVENT_IPV6_ACQUIRED:

        /* Initialize SlNetSock layer with CC3x20 interface                      */
        status = ti_net_SlNet_initConfig();
        if(0 != status)
        {
            Display_printf(display, 0, 0, "Failed to initialize SlNetSock\n\r");
        }

        if(mode != ROLE_AP)
        {
            Display_printf(display, 0, 0,"[NETAPP EVENT] IP Acquired: IP=%d.%d.%d.%d , "
                           "Gateway=%d.%d.%d.%d\n\r",
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,3),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,2),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,1),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Ip,0),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,3),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,2),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,1),
                           SL_IPV4_BYTE(pNetAppEvent->Data.IpAcquiredV4.Gateway,0));

            pthread_attr_init(&pAttrs);
            priParam.sched_priority = 1;
            status = pthread_attr_setschedparam(&pAttrs, &priParam);
            status |= pthread_attr_setstacksize(&pAttrs, TASK_STACK_SIZE);
            status = pthread_create(&udpThread, &pAttrs, (void *(*)(void *))echoFxn, (void*)UDPPORT);
            if(status)
            {
                printError("Task create failed", status);
            }
        }
        break;
    default:
        break;
    }
}
/*!
    \brief          SimpleLinkFatalErrorEventHandler

    This handler gets called whenever a socket event is reported by the NWP / Host driver. After this routine is called, the user's application must restart the device in order to recover.

    \param          slFatalErrorEvent    -   pointer to fatal error event.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 17.9.
 */

void SimpleLinkFatalErrorEventHandler(SlDeviceFatal_t *slFatalErrorEvent)
{
    /* Unused in this application */
}
/*!
    \brief          SimpleLinkNetAppRequestMemFreeEventHandler

    This handler gets called whenever the NWP is done handling with the buffer used in a NetApp request. This allows the use of dynamic memory with these requests.

    \param          pNetAppRequest     -   Pointer to NetApp request structure.
    \param          pNetAppResponse    -   Pointer to NetApp request Response.
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 17.9.
    \return         void
 */

void SimpleLinkNetAppRequestMemFreeEventHandler(uint8_t *buffer)
{
    /* Unused in this application */
}

/*!
    \brief          SimpleLinkNetAppRequestEventHandler

    This handler gets called whenever a NetApp event is reported by the NWP / Host driver. User can write he's logic to handle the event here.

    \param          pNetAppRequest     -   Pointer to NetApp request structure.
    \param          pNetAppResponse    -   Pointer to NetApp request Response.
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 17.9.
    \return         void
 */

void SimpleLinkNetAppRequestEventHandler(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
{
    /* Unused in this application */
}

/*!
    \brief          SimpleLinkHttpServerEventHandler

    This handler gets called whenever a HTTP event is reported by the NWP internal HTTP server.

    \param          pHttpEvent       -   pointer to http event data.
    \param          pHttpEvent       -   pointer to http response.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) chapter 9.
 */

void SimpleLinkHttpServerEventHandler(SlNetAppHttpServerEvent_t *pHttpEvent,
                                      SlNetAppHttpServerResponse_t *pHttpResponse)
{
    /* Unused in this application */
}

/*!
    \brief          SimpleLinkWlanEventHandler

    This handler gets called whenever a WLAN event is reported by the host driver / NWP. Here user can implement he's own logic for any of these events. This handler is used by 'network_terminal' application to show case the following scenarios:
    1. Handling connection / Disconnection.
    2. Handling Addition of station / removal.
    3. RX filter match handler.
    4. P2P connection establishment.

    \param          pWlanEvent       -   pointer to Wlan event data.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) sections 4.3.4, 4.4.5 and 4.5.5.
    \sa             cmdWlanConnectCallback, cmdEnableFilterCallback, cmdWlanDisconnectCallback, cmdP2PModecallback.
 */

void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
{
    if(pWlanEvent == NULL)
    {
        return;
    }

    switch(pWlanEvent->Id)
    {
    case SL_WLAN_EVENT_STA_ADDED:
        printf("\n\n A station with following parameters has got connected to the AP: %s", SsId);
        printf("\n\n %02x:%02x:%02x:%02x:%02x:%02x \n\n",
               pWlanEvent->Data.STAAdded.Mac[0],
               pWlanEvent->Data.STAAdded.Mac[1],
               pWlanEvent->Data.STAAdded.Mac[2],
               pWlanEvent->Data.STAAdded.Mac[3],
               pWlanEvent->Data.STAAdded.Mac[4],
               pWlanEvent->Data.STAAdded.Mac[5]);

        // code to get the number of connected stations...

        _u8 num_ap_connected_sta;
        _u16 len = sizeof(num_ap_connected_sta);
        status = sl_NetCfgGet(SL_NETCFG_AP_STATIONS_NUM_CONNECTED, NULL, &len, &num_ap_connected_sta);
        printf("Revised number of connected stations = %d\n", num_ap_connected_sta);

        // code to get the list of stations...

        SlNetCfgStaInfo_t ApStaList[4];
        _u8 sta_info_len = sizeof(ApStaList);
        _u8 start_sta_index = 0;
        _u8 actual_num_sta, ii;
        sl_NetCfgGet(SL_NETCFG_AP_STATIONS_INFO_LIST, &start_sta_index, &sta_info_len, (_u8 *)ApStaList);
        actual_num_sta = sta_info_len / sizeof(SlNetCfgStaInfo_t);
        printf("\n \n Actual num_stations = %d", actual_num_sta);
        printf("\n \n upon sta_info_len = %d", sta_info_len);
        for (ii=0; ii<actual_num_sta; ii++)
        {
            SlNetCfgStaInfo_t *staInfo = &ApStaList[ii];
            printf("    Ap Station %d is connected\n", ii);
            printf("    NAME: %s\n", staInfo->Name);
            printf("    MAC:  %02x:%02x:%02x:%02x:%02x:%02x\n", staInfo->MacAddr[0], staInfo->MacAddr[1], staInfo->MacAddr[2], staInfo->MacAddr[3], staInfo->MacAddr[4], staInfo->MacAddr[5]);
            printf("    IP:   %d.%d.%d.%d\n", SL_IPV4_BYTE(staInfo->Ip,3), SL_IPV4_BYTE(staInfo->Ip,2), SL_IPV4_BYTE(staInfo->Ip,1), SL_IPV4_BYTE(staInfo->Ip,0));
            // Display_printf(display, 0, 0,"\n\r NAME: %s\n\r", staInfo->Name);
            // Display_printf(display, 0, 0,"\n\r IP:   %d.%d.%d.%d\n", SL_IPV4_BYTE(staInfo->Ip,3), SL_IPV4_BYTE(staInfo->Ip,2), SL_IPV4_BYTE(staInfo->Ip,1), SL_IPV4_BYTE(staInfo->Ip,0));
            SlNetCfgIpV4Args_t *staInfo2 = &ApStaList[ii];
            printf("    Gateway: %d.%d.%d.%d\n\n", SL_IPV4_BYTE(staInfo2->IpGateway,3),SL_IPV4_BYTE(staInfo2->IpGateway,2),SL_IPV4_BYTE(staInfo2->IpGateway,1),SL_IPV4_BYTE(staInfo2->IpGateway,0));
        }

        break;
    case SL_WLAN_EVENT_STA_REMOVED:
        printf("\n\n A station with following parameters have been removed from the AP: %s", SsId);
        printf("\n\n %02x:%02x:%02x:%02x:%02x:%02x \n\n",
               pWlanEvent->Data.STARemoved.Mac[0],
               pWlanEvent->Data.STARemoved.Mac[1],
               pWlanEvent->Data.STARemoved.Mac[2],
               pWlanEvent->Data.STARemoved.Mac[3],
               pWlanEvent->Data.STARemoved.Mac[4],
               pWlanEvent->Data.STARemoved.Mac[5]);
        break;
    default:
        break;
    }
}
/*!
    \brief          SimpleLinkGeneralEventHandler

    This handler gets called whenever a general error is reported by the NWP / Host driver. Since these errors are not fatal, application can handle them.

    \param          pDevEvent    -   pointer to device error event.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 17.9.
 */

void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
{
    /* Unused in this application */
}

/*!
    \brief          SimpleLinkSockEventHandler

    This handler gets called whenever a socket event is reported by the NWP / Host driver.

    \param          SlSockEvent_t    -   pointer to socket event data.
    \return         void
    \note           For more information, please refer to: user.h in the porting folder of the host driver and the  CC31xx/CC32xx NWP programmer's guide (SWRU455) section 7.6.
 */

void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
{
    /* Unused in this application */
}

void mainThread(void *pvParameters)
{
    pthread_attr_t      pAttrs_spawn;
    struct sched_param  priParam;
    unsigned char flag1 = 0;

    SPI_init();
    Display_init();
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while(1);
    }

    /* Start the SimpleLink Host */
    pthread_attr_init(&pAttrs_spawn);
    priParam.sched_priority = SPAWN_TASK_PRIORITY;
    status = pthread_attr_setschedparam(&pAttrs_spawn, &priParam);
    status |= pthread_attr_setstacksize(&pAttrs_spawn, TASK_STACK_SIZE);

    status = pthread_create(&spawn_thread, &pAttrs_spawn, sl_Task, NULL);
    if(status)
    {
        printError("Task create failed", status);
    }

    /* Turn NWP on - initialize the device*/
    mode = sl_Start(0, 0, 0);
    Display_printf(display, 0, 0,"\n\rMode: %d", mode);
    if (mode < 0)
    {
        Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, DEVICE_ERROR);
    }
    switch(mode)
    {
    case 0:
        printf("\n \r Role = Station");
        break;
    case 1:
        printf("\n \r Role = Reserved!");
        break;
    case 2:
        printf("\n \r Role = Access Point");
        break;
    case 3:
        printf("\n \r Role = ROLE_P2P");
        break;
    case 4:
        printf("\n \r Role = ROLE_TAG");
        break;
    default:
        printf("\n \r Some Error Occured! No such role!!");
        break;
    }
    unsigned int temp1 = 0;
    if(mode != ROLE_AP)
    {
        /* Set NWP role as STA */
        mode = sl_WlanSetMode(ROLE_AP);
        if (mode < 0)
        {
            Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, WLAN_ERROR);
        }

        /* For changes to take affect, we restart the NWP */
        status = sl_Stop(SL_STOP_TIMEOUT);
        if (status < 0)
        {
            Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, status, DEVICE_ERROR);
        }

        mode = sl_Start(0, 0, 0);
        if (mode < 0)
        {
            Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, DEVICE_ERROR);
        }
    }

    if(mode == ROLE_AP)
    {

        printf("\n Configuring AP parameters now... \n");

        // as per response from TI post, there is no need to restart the device after every change. Hence, keeping only a single restart at the end of this if statement.
        // set device name

        status = sl_NetAppSet (SL_NETAPP_DEVICE_ID,SL_NETAPP_DEVICE_URN, strlen(device_name), (_u8 *) device_name);
        if( status )
        {
            Display_printf(display, 0, 0, "Device Name could not be updated");
        }
        else
        {
            printf("\n Device Name Updated \n");
        }

        // set SSID for the AP

        status = sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SSID, strlen(SsId), SsId);
        if(status)
        {
            Display_printf(display, 0, 0, "SSID Name could not be updated");
        }
        else
        {
            printf("\n SSID Name Updated \n");
        }

        // set country code for AP

        status = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, SL_WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country_code);
        if(status)
        {
            Display_printf(display, 0, 0, "Country Code could not be updated");
        }
        else
        {
            printf("\n Device Country Code updated \n");
        }

        // set security settings

        status = sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_SECURITY_TYPE, 1, (_u8 *) &secutiry_type);

        if(status)
        {
            Display_printf(display, 0, 0, "Security Type could not be updated");
        }
        else
        {
            printf("\n Device Security Settings updated \n");
        }

        // set password for updated security type

        status = sl_WlanSet(SL_WLAN_CFG_AP_ID, SL_WLAN_AP_OPT_PASSWORD, strlen(security_password), (_u8*) security_password);

        if(status)
        {
            Display_printf(display, 0, 0, "Security Type could not be updated");
        }
        else
        {
            printf("\n Device Security Password updated \n");
        }

        // set Tx power levels => 0 dB backoff for now

        status = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, SL_WLAN_GENERAL_PARAM_OPT_AP_TX_POWER,1,(_u8*)& ApPower);

        if(status)
        {
            Display_printf(display, 0, 0, "Access Point Power could not be updated");
        }
        else
        {
            printf("\n Device power updated \n");
        }

        /* For changes to take affect, we restart the NWP */
        status = sl_Stop(SL_STOP_TIMEOUT);
        if (status < 0)
        {
            Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, status, DEVICE_ERROR);
        }

        mode = sl_Start(0, 0, 0);
        if (mode < 0)
        {
            Display_printf(display, 0, 0,"\n\r[line:%d, error code:%d] %s\n\r", __LINE__, mode, DEVICE_ERROR);
        }
        else
        {
            printf("\n Device restarted after various configurations!! \n");
        }
    }

    printf("\n Configuring Network Parameters now... \n");

    SlNetCfgIpV4Args_t ipV4;
    ipV4.Ip = (_u32)SL_IPV4_VAL(10,1,1,201);                                // IP address
    ipV4.IpMask = (_u32)SL_IPV4_VAL(255,255,255,0);                         // Subnet mask
    ipV4.IpGateway = (_u32)SL_IPV4_VAL(10,1,1,1);                           // Default gateway address
    ipV4.IpDnsServer = (_u32)SL_IPV4_VAL(8,8,8,8);                          // _u32 DNS server address
    status = sl_NetCfgSet(SL_NETCFG_IPV4_AP_ADDR_MODE,SL_NETCFG_ADDR_STATIC,sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4);
    if(status)
    {
        Display_printf(display, 0, 0, "IP address could not be updated");
    }
    else
    {
        printf("\n IP address updated \n");
    }

    get_device_config_parameters();

    // while(1);

    /*
        SlSockAddrIn_t  Addr;
        _i16 AddrSize = sizeof(SlSockAddrIn_t);
        _i16 SockID;
        _i16 Status;
        _i8 Buf[SEND_BUF_LEN];
        Addr.sin_family = SL_AF_INET;
        Addr.sin_port = sl_Htons(5001);
        Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200));
        SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
        Status = sl_Connect(SockID, (SlSockAddr_t *)&Addr, AddrSize);
        Status = sl_Send(SockID, Buf, 1460, 0 );                                */

    _i16 Sd;
    SlSockAddrIn_t Addr;
    _i8 SendBuf[] = "Hello from AP !!!";
    _i8 RecvBuf[1460] ={0};
    Sd = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);                   // IPv4 socket (UDP, TCP, etc), UDP Packets, Null
    if( Sd < 0 )
    {
        printf("Socket opening failed!!");
    }

    Addr.sin_family = SL_AF_INET;
    Addr.sin_port = sl_Htons(5001);
    Addr.sin_addr.s_addr = SL_INADDR_ANY;                                       // bind to any address
    // Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(192,168,1,31));              // bind to this specific address only.
    status = sl_Bind(Sd, ( SlSockAddr_t *)&Addr, sizeof(SlSockAddrIn_t));
    if(status)
    {
        printf("\n\n\n Socket Binding failed");
    }
    else
    {
        printf("\n socket binding completed \n");
    }

    Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(10,1,1,200));              // connect with this specific address only.

    status = sl_Connect(Sd, ( SlSockAddr_t *)&Addr, sizeof(SlSockAddrIn_t));    // address specified in this statement is the same from which the data is to be received and to which the data is to be sent.

    if(status)
    {
        printf("\n\n\n Socket Connection failed");
    }




    while(1)
    {

        char msg1[]=" AP Message # ";
        char msg2[6], msg3[6];
        ltoa(counter1, msg2, 10);
        ltoa(counter2, msg3, 10);
        strcat(msg1, msg2);
        strcat(msg1, " & ");
        strcat(msg1, msg3);

        status = sl_Send(Sd, msg1, strlen(msg1), 0);
        if( strlen(msg1) != status )
        {
            printf("\n\n\n All packets could not be sent");
        }

        /*
                Addr.sin_family = SL_AF_INET;
                Addr.sin_port = sl_Htons(5001);
                Addr.sin_addr.s_addr = sl_Htonl(SL_IPV4_VAL(192,168,1,31));
                Status = sl_SendTo(Sd, SendBuf, strlen(SendBuf), 0, (SlSockAddr_t*)&Addr,sizeof(SlSockAddr_t));
                if( strlen(SendBuf) != Status )
                {
                // error
                }

         */

        status = sl_Recv(Sd, RecvBuf, 1460, 0);
        if (status < 0)
        {
            printf("\n\n\nPacket reception failed!!");
        }
        else
        {
            // printf("\n\n\n number of packets received = %d", status);
            // printf(" \n received messages is: %s", RecvBuf);
            // printf(" \n ");
            // printf(" \n ");
        }
        counter1++;
        if(counter1 == 50000)
        {
            printf(" \n received messages is: %s", RecvBuf);
            printf(" \n ");
            counter2++;
            counter1 = 0;
        }

        /*

                AddrSize = sizeof(SlSockAddrIn_t);
                status = sl_RecvFrom(Sd, RecvBuf, 1460, 0, ( SlSockAddr_t *)&Addr, &AddrSize);
                if( 0 > Status )
                {
                // error
                }

         */
    }


    status = sl_Close(Sd);
    if( status )
    {
        printf("Error Occured!!");
    }
    else
    {
        printf("\n Socket Closed \n");
    }
}
