emNet DNS Client (Sample)

From SEGGER Knowledge Base
Jump to navigation Jump to search
IP_DNS_Client_Sample.c
Requires modifications No
Download IP_DNS_Client_Sample.c

This Sample demonstrates how to use emNet to resolve a hostname to an IP address. By default multiple SEGGER hostnames are used.

Code

/*********************************************************************
*                   (c) SEGGER Microcontroller GmbH                  *
*                        The Embedded Experts                        *
*                           www.segger.com                           *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

Purpose : Sample program for embOS & emNet
          Demonstrates use of the IP stack to resolve a hostname to an
          IP addr. IP_ResolveHost() is used instead of gethostbyname()
          as gethostbyname() is not thread safe and is therefore not
          recommended to be used.

          The DNS client will resolve a hostname to its IP addr. using
          the DNS server of an interface. The following is a sample of
          the output to the terminal window:

          <...>
          30:033 DNSClient - DNS resolve demonstration
          31:033 DNSClient - IP addr. 116.203.153.115 resolved from host name "segger.com".
          32:033 DNSClient - IP addr. 194.45.36.135 resolved from host name "blog.segger.com".
          33:033 DNSClient - IP addr. 5.104.108.9 resolved from host name "wiki.segger.com".
          34:033 DNSClient - IP addr. 89.163.210.194 resolved from host name "forum.segger.com".
          35:033 DNSClient - IP addr. 213.202.222.194 resolved from host name "studio.segger.com".
          36:033 DNSClient - IP addr. 194.45.36.135 resolved from host name "support.segger.com".
          <...>
*/

#include "RTOS.h"
#include "BSP.h"
#include "IP.h"

/*********************************************************************
*
*       Configuration
*
**********************************************************************
*/

#define USE_RX_TASK  0  // 0: Packets are read in ISR, 1: Packets are read in a task of its own.

//
// DNS client sample.
//
#define TIMEOUT    10000  // Timeout for DNS request [ms].

//
// Task priorities.
//
enum {
   TASK_PRIO_IP_DNSC = 150
  ,TASK_PRIO_IP_TASK             // Priority should be higher than all IP application tasks.
#if USE_RX_TASK
  ,TASK_PRIO_IP_RX_TASK          // Must be the highest priority of all IP related tasks.
#endif
};

//
// Task stack sizes that might not fit for some interfaces (multiples of sizeof(int)).
//
#ifndef   APP_TASK_STACK_OVERHEAD
  #define APP_TASK_STACK_OVERHEAD     0
#endif

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
//
// List of host names to resolve
//
static const char* _Hosts[] = { "segger.com", "blog.segger.com", "wiki.segger.com", "forum.segger.com", "studio.segger.com", "support.segger.com" };

static IP_HOOK_ON_STATE_CHANGE _StateChangeHook;
static int                     _IFaceId;

//
// Task stacks and Task-Control-Blocks.
//
static OS_STACKPTR int _IPStack[TASK_STACK_SIZE_IP_TASK/sizeof(int)];             // Stack of the IP_Task.
static OS_TASK         _IPTCB;                                                    // Task-Control-Block of the IP_Task.

#if USE_RX_TASK
static OS_STACKPTR int _IPRxStack[TASK_STACK_SIZE_IP_RX_TASK/sizeof(int)];        // Stack of the IP_RxTask.
static OS_TASK         _IPRxTCB;                                                  // Task-Control-Block of the IP_RxTask.
#endif

static OS_STACKPTR int _DNScStack[(1152 + APP_TASK_STACK_OVERHEAD)/sizeof(int)];  // Stack of the DNS client.
static OS_TASK         _DNScTCB;                                                  // Task-Control-Block of the DNS client.

/*********************************************************************
*
*       Prototypes
*
**********************************************************************
*/
#ifdef __cplusplus
extern "C" {     /* Make sure we have C-declarations in C++ programs */
#endif
void MainTask(void);
#ifdef __cplusplus
}
#endif

/*********************************************************************
*
*       Local functions
*
**********************************************************************
*/

/*********************************************************************
*
*       _OnStateChange()
*
* Function description
*   Callback that will be notified once the state of an interface
*   changes.
*
* Parameters
*   IFaceId   : Zero-based interface index.
*   AdminState: Is this interface enabled ?
*   HWState   : Is this interface physically ready ?
*/
static void _OnStateChange(unsigned IFaceId, U8 AdminState, U8 HWState) {
  //
  // Check if this is a disconnect from the peer or a link down.
  // In this case call IP_Disconnect() to get into a known state.
  //
  if (((AdminState == IP_ADMIN_STATE_DOWN) && (HWState == 1)) ||  // Typical for dial-up connection e.g. PPP when closed from peer. Link up but app. closed.
      ((AdminState == IP_ADMIN_STATE_UP)   && (HWState == 0))) {  // Typical for any Ethernet connection e.g. PPPoE. App. opened but link down.
    IP_Disconnect(IFaceId);                                       // Disconnect the interface to a clean state.
  }
}

/*********************************************************************
*
*       _DNScTask()
*
* Function description
*   DNS client task that resolves the configured host name to its
*   IP addr.
*/
static void _DNScTask(void) {
  U32  IPAddr;
  int  i;
  int  r;
  int  NumIFaces;
  char ac[16];
  U8   IFaceReady;

  //
  // Make sure that at least one interface is ready before starting the sample.
  //
  IFaceReady = 0;
  NumIFaces  = IP_INFO_GetNumInterfaces();
  do {
    for (i = 0; i < NumIFaces; i++) {
      if (IP_IFaceIsReadyEx(_IFaceId) != 0) {
        IFaceReady = 1;
        break;
      }
      OS_Delay(100);
    }
  } while (IFaceReady == 0);
  //
  // DNS client sample.
  //
  while (1) {
    IP_Logf_Application("DNS resolve demonstration");
    for (i = 0; i < (int)SEGGER_COUNTOF(_Hosts); i++) {
      OS_Delay(1000);                                   // One check per second is enough.
      r = IP_ResolveHost(_Hosts[i], &IPAddr, TIMEOUT);  // Resolve host name.
      if (r != 0) {
        IP_Logf_Application("Could not resolve host addr.");
        continue;
      }
      IP_PrintIPAddr(ac, ntohl(IPAddr), sizeof(ac));
      IP_Logf_Application("IP addr. %s resolved from host name \"%s\".", ac, _Hosts[i]);
    }
    IP_Logf_Application(" "); // newline
    OS_Delay(5000);
  }
}

/*********************************************************************
*
*       Global functions
*
**********************************************************************
*/

/*********************************************************************
*
*       MainTask()
*
* Function description
*   Main task executed by the RTOS to create further resources and
*   running the main application.
*/
void MainTask(void) {
  IP_Init();
  IP_AddLogFilter(IP_MTYPE_APPLICATION);
  _IFaceId = IP_INFO_GetNumInterfaces() - 1;                                           // Get the last registered interface ID as this is most likely the interface we want to use in this sample.
  OS_SetPriority(OS_GetTaskID(), TASK_PRIO_IP_TASK);                                   // For now, this task has highest prio except IP management tasks.
  OS_CREATETASK(&_IPTCB  , "IP_Task"  , IP_Task  , TASK_PRIO_IP_TASK   , _IPStack);    // Start the IP_Task.
#if USE_RX_TASK
  OS_CREATETASK(&_IPRxTCB, "IP_RxTask", IP_RxTask, TASK_PRIO_IP_RX_TASK, _IPRxStack);  // Start the IP_RxTask, optional.
#endif
  OS_CREATETASK(&_DNScTCB, "DNSClient", _DNScTask, TASK_PRIO_IP_DNSC   , _DNScStack);  // Start the DNS client.
  IP_AddStateChangeHook(&_StateChangeHook, _OnStateChange);                            // Register hook to be notified on disconnects.
  IP_Connect(_IFaceId);                                                                // Connect the interface if necessary.
  OS_SetPriority(OS_GetTaskID(), 255);                                                 // Now this task has highest prio for real-time application. This is only allowed when this task does not use blocking IP API after this point.
  while (IP_IFaceIsReadyEx(_IFaceId) == 0) {
    OS_Delay(50);
  }
  while (1) {
    BSP_ToggleLED(1);
    OS_Delay(200);
  }
}

/*************************** End of file ****************************/