/**
******************************************************************************
* @file    netbios.c
* @author  WIZnet Software Team 
* @version V1.0
* @date    2015-xx-xx
* @brief   nebios 名字解析服务器功能    通过Ping	NETBIOS_W7500_NAME 可获得其IP地址
* @attention  
******************************************************************************
*/
#include "netbios.h"
#include "ip_config.h"
#include "socket.h"
#include "httpUtil.h"
#include "utility.h"
#include <string.h>
#include <stdio.h>

 /**
*@brief		  NetBIOS解码
*@param		  *name_enc			解码前的NetBios名字
*@param		  *name_dec			解码后的NetBios名字
*@param		  name_dec_len
*@return	  无
*/
static int
netbios_name_decoding( char *name_enc, char *name_dec, int name_dec_len)
{
  char *pname;
  char  cname;
  char  cnbname;
  int   index = 0;

  /* Start decoding netbios name. */
  pname  = name_enc;
  for (;;) {
    /* Every two characters of the first level-encoded name
     * turn into one character in the decoded name. */
    cname = *pname;
    if (cname == '\0')
      break;    /* no more characters */
    if (cname == '.')
      break;    /* scope ID follows */
    if (cname < 'A' || cname > 'Z') {
      /* Not legal. */
      return -1;
    }
    cname -= 'A';
    cnbname = cname << 4;
    pname++;

    cname = *pname;
    if (cname == '\0' || cname == '.') {
      /* No more characters in the name - but we're in
       * the middle of a pair.  Not legal. */
      return -1;
    }
    if (cname < 'A' || cname > 'Z') {
      /* Not legal. */
      return -1;
    }
    cname -= 'A';
    cnbname |= cname;
    pname++;

    /* Do we have room to store the character? */
    if (index < NETBIOS_NAME_LEN) {
      /* Yes - store the character. */
      name_dec[index++] = (cnbname!=' '?cnbname:'\0');
    }
  }

  return 0;
}
char netbios_rx_buf[NETBIOS_MSG_MAX_LEN];
char netbios_tx_buf[NETBIOS_MSG_MAX_LEN];

void do_netbios(void)
{
  unsigned char state;
  unsigned int len;
  state = getSn_SR(SOCK_NETBIOS);
  switch(state)
  {
  case SOCK_UDP:
    if((len=getSn_RX_RSR(SOCK_NETBIOS))>0)
    {
      unsigned char rem_ip_addr[4];
      uint16_t rem_udp_port;
      char netbios_name[NETBIOS_NAME_LEN+1];
      NETBIOS_HDR* netbios_hdr;
      NETBIOS_NAME_HDR* netbios_name_hdr;
      len=recvfrom(SOCK_NETBIOS,(unsigned char*)&netbios_rx_buf,len,rem_ip_addr,&rem_udp_port);
      //printf("netbios rx len=%d\r\n",len);
      printf("rem_ip_addr=%d.%d.%d.%d:%d\r\n",rem_ip_addr[0],rem_ip_addr[1],rem_ip_addr[2],rem_ip_addr[3],rem_udp_port);
      netbios_hdr = (NETBIOS_HDR*)netbios_rx_buf;
      netbios_name_hdr = (NETBIOS_NAME_HDR*)(netbios_hdr+1);
      /* if the packet is a NetBIOS name query question */
      if (((netbios_hdr->flags & swaps(NETB_HFLAG_OPCODE)) == swaps(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
          ((netbios_hdr->flags & swaps(NETB_HFLAG_RESPONSE)) == 0) &&
           (netbios_hdr->questions == swaps(1))) 
      {
        printf("netbios name query question\r\n");
        /* decode the NetBIOS name */
        netbios_name_decoding( (char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
        printf("name is %s\r\n",netbios_name);
        /* if the packet is for us */
        if (strcmp(netbios_name, NETBIOS_W7500_NAME) == 0) 
        {
          uint8_t ip_addr[4];
          NETBIOS_RESP *resp = (NETBIOS_RESP*)netbios_tx_buf;
          /* prepare NetBIOS header response */
          resp->resp_hdr.trans_id      = netbios_hdr->trans_id;
          resp->resp_hdr.flags         = swaps(NETB_HFLAG_RESPONSE |
                                               NETB_HFLAG_OPCODE_NAME_QUERY |
                                               NETB_HFLAG_AUTHORATIVE |
                                               NETB_HFLAG_RECURS_DESIRED);
          resp->resp_hdr.questions     = 0;
          resp->resp_hdr.answerRRs     = swaps(1);
          resp->resp_hdr.authorityRRs  = 0;
          resp->resp_hdr.additionalRRs = 0;
          /* prepare NetBIOS header datas */
          memcpy( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
          resp->resp_name.nametype     = netbios_name_hdr->nametype;
          resp->resp_name.type         = netbios_name_hdr->type;
          resp->resp_name.cls          = netbios_name_hdr->cls;
          resp->resp_name.ttl          = swapl(NETBIOS_NAME_TTL);
          resp->resp_name.datalen      = swaps(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr));
          resp->resp_name.flags        = swaps(NETB_NFLAG_NODETYPE_BNODE);
          getSIPR(ip_addr);
          memcpy(resp->resp_name.addr,ip_addr,4);
          //ip_addr_copy(resp->resp_name.addr, netif_default->ip_addr);
          
          /* send the NetBIOS response */
          sendto(SOCK_NETBIOS, (unsigned char*)resp, sizeof(NETBIOS_RESP), rem_ip_addr, rem_udp_port);
          printf("send response\r\n");
        }
      }     
    }
    break;
  case SOCK_CLOSED:																		//socket关闭状态
    close(SOCK_NETBIOS);
    socket(SOCK_NETBIOS,Sn_MR_UDP,NETBIOS_PORT,0);		//初始化socket信息
    break;
  default:
    break;
  }
}


