/*******************************************************************************
* RXduinoライブラリ & 特電HAL
* 
* このソフトウェアは特殊電子回路株式会社によって開発されたものであり、当社製品の
* サポートとして提供されます。このライブラリは当社製品および当社がライセンスした
* 製品に対して使用することができます。
* このソフトウェアはあるがままの状態で提供され、内容および動作についての保障はあ
* りません。弊社はファイルの内容および実行結果についていかなる責任も負いません。
* お客様は、お客様の製品開発のために当ソフトウェアのソースコードを自由に参照し、
* 引用していただくことができます。
* このファイルを単体で第三者へ開示・再配布・貸与・譲渡することはできません。
* コンパイル・リンク後のオブジェクトファイル(ELF ファイルまたはMOT,SRECファイル)
* であって、デバッグ情報が削除されている場合は第三者に再配布することができます。
* (C) Copyright 2011-2012 TokushuDenshiKairo Inc. 特殊電子回路株式会社
* http://rx.tokudenkairo.co.jp/
*******************************************************************************/

#ifndef H_TKDNIP
#define H_TKDNIP

// 特電HAL
#include "tkdn_hal.h"

#ifndef BOOL
 #define BOOL  int
#endif

#ifdef __cplusplus
	extern "C" {
#endif

// リンクの状態
typedef enum {
	LINK_DOWN         = 0,
	LINK_UP           = 1,
	LINK_DOWN_CHANGED = 2,
	LINK_UP_CHANGED   = 3
} LINK_STATE;


// DNSの応答のタイプ
typedef enum {
	DNS_NONAUTH,
	DNS_AUTH,
	DNS_APPENDIX,
	DNS_UNDEF
} DNS_REPLY_TYPE;

// DNSのレコードのタイプ
typedef enum {
	DNS_A     = 1,
	DNS_NS    = 2,
	DNS_CNAME = 5,
	DNS_PTR   = 12,
	DNS_MX    = 15,
	DNS_AAAA  = 28,
	DNS_ANY   = 255,
} DNS_TYPE;

// DNSのアドレスのタイプ
typedef enum {
	DNS_UNKN  = 0,
	DNS_IN    = 1,
} DNS_CLASS;

// DNSの結果が格納される構造体
typedef struct dns_record_t
{
	DNS_REPLY_TYPE rtype;
	DNS_TYPE       type;
	DNS_CLASS      aclass;
	int            ttl;
	char           *name;
	unsigned char  *data;
} dns_record_t;

// DNSの結果が格納される構造体の配列を格納するための構造体
// tketh_nslookup_exの戻り値で使われる、
typedef struct dns_records_t
{
	int             num_of_records;
	dns_record_t  **record;
} dns_records_t;

// UDPを受信したときに呼び出されるユーザ関数
// この関数がTRUEを返すとユーザで処理したものと解釈され、システムでは処理されない
// この関数がFALSEを返すとシステムでは処理される。
// ポート番号とデータ長のエンディアンは修正されている
typedef BOOL (*UDP_HANDLE_FUNC)(
	unsigned char dest_ip[4],
	unsigned char src_ip[4],
	short dest_port,
	short src_port,
	unsigned char *data, // UDPパケットのデータ部
	short datalen        // UDPパケットのデータの長さ(ヘッダは含まない)
);

// TCPクライアントを管理するための構造体
typedef struct tcp_str tcp_t;
typedef struct tcp_server_str tcp_server_t;

// TCPの接続状態
typedef enum {TCP_CLOSED,
		      TCP_LISTEN,    // L
		      TCP_SYNRCVD,   // R
		      TCP_ESTAB,     // E
		      TCP_FIN_WAIT1, // F
		      TCP_FIN_WAIT2, // F
		      TCP_CLOSING,   // C
		      TCP_TIME_WAIT, // T
		      TCP_SYN_SENT,  // S
		      TCP_CLOSEWAIT, // W
		      TCP_LAST_ACK   // A
} TCP_STATE;

// クライアントの接続状態を示す構造体
typedef struct client_stat_t
{
	unsigned char  ipaddr[4];
	unsigned short local_port;
	unsigned short foreign_port;
	BOOL           server;
	TCP_STATE      state;
} client_stat_t;

// クライアントの接続状態を示す構造体のリスト
typedef struct clients_stat_t
{
	int             num_of_clients;
	client_stat_t  *clients;
} clients_stat_t;

typedef void (*FUNCTYPE_TCPEVENT)(tcp_t *client);

////////////////////////////////////////////////////////////////////////
//                         ユーザ公開関数
////////////////////////////////////////////////////////////////////////

//------------------------------------------------------------------------
// 基本的な操作
//------------------------------------------------------------------------

// 自分のMACアドレスを設定し、ライブラリを開始する
void tketh_open(unsigned char *macaddr);

// イーサネットのリンクアップをチェックする。
// リンクが切断→接続に変わったらオートネゴーシエーションを実行する
LINK_STATE tketh_check_link();

// 内部でいろいろな処理を進める。この関数をメインループ中で呼び出すこと。
void tketh_process();

// デバッグレベル 0:なし 1:パケットの概要 2:パケットダンプ
void tketh_debug(int level);

// 自分の名前を設定する
void tketh_set_hostname(const char *hostname);

// 自分の名前を調べる
char *tketh_get_hostname(void);

// MACアドレスを変更する
void tketh_change_macaddr(const unsigned char macaddr[6]);

// 自分のMACアドレスを調べる
void tketh_get_macaddr(unsigned char macaddr[6]);

//------------------------------------------------------------------------
// IPアドレス等の設定や取得
//------------------------------------------------------------------------

// DHCPを実行して、IPアドレス、GW、DNSサーバを設定する
BOOL tketh_dhcpc(void);

// 自分のIPアドレスを設定する
void tketh_set_myipaddr(unsigned char ipaddr[4],unsigned char mask[4]);

// 自分のIPアドレスを調べる
void tketh_get_myipaddr(unsigned char ipaddr[4],unsigned char mask[4]);

// デフォルトゲートウェイを設定する
void tketh_set_gateway(unsigned char ipaddr[4]);

// 設定されているデフォルトゲートウェイを取得する
void tketh_get_gateway(unsigned char ipaddr[4]);

// DNSサーバを設定する
void tketh_set_nameserver(unsigned char ipaddr[4]);

// 設定されているDNSサーバを取得する
void tketh_get_nameserver(unsigned char ipaddr[4]);

// ARPのテーブルを表示する
void tketh_arp_table_show();

//------------------------------------------------------------------------
// 低レベルなパケットの送受信
//------------------------------------------------------------------------

// UDPを送信する
BOOL tketh_send_udp(unsigned char ipaddr[4],short dest_port,unsigned char *buf,int len);

// UDPを受信したときに処理する関数を登録する
void tketh_regist_udp_handler(UDP_HANDLE_FUNC func);

//------------------------------------------------------------------------
// PING関係のプロトコル
//------------------------------------------------------------------------

// PINGを送信する
BOOL tketh_send_ping(unsigned char ipaddr[4],unsigned char *buf,int len);

// PINGが実行中かどうか調べる
BOOL tketh_is_ping_running();

// PINGが実行をキャンセルする
void tketh_cancel_ping();

// 最後にPINGを送った時刻をus単位で返す
unsigned long tketh_ping_starttime();

//------------------------------------------------------------------------
// 名前解決
//------------------------------------------------------------------------

// DNSサーバにアクセスして名前解決を行う
BOOL tketh_nslookup(char *hostname,unsigned char ipaddr[4]);

// DNSサーバにアクセスして名前解決を行う
dns_records_t *tketh_nslookup_ex(char *hostname);

// DNS結果構造体を開放する
void tketh_free_dns_records(dns_records_t *dnsrec);

// DNSサーバにアクセスしてIPアドレスから名前を調べる(未作成)
BOOL tketh_ip_to_hostname(unsigned char ipaddr[4],char *hostname,int hostname_maxlen);

//------------------------------------------------------------------------
// TCPクライアント
//------------------------------------------------------------------------

// コネクションの確立
tcp_t *tketh_tcp_connect(unsigned char ipaddr[4],short dest_port);

// コネクションが接続中かどうかを調べる
BOOL tketh_tcp_is_connected(tcp_t *info);

// コネクションの終了
void tketh_tcp_fin(tcp_t *info);

// コネクションの状態を文字列で返す
char *tketh_tcp_state(tcp_t *info);

// データ送信
void tketh_tcp_senddata(tcp_t *info,unsigned char *data,int len);

// 受信したデータの量を調べる
int tketh_tcp_recvcount(tcp_t *info);

// バッファからデータ受信
int tketh_tcp_recvdata(tcp_t *info,unsigned char *data,int len);

//------------------------------------------------------------------------
// TCPサーバ ※現在はセッションを１つしか張れない
//------------------------------------------------------------------------

// サーバのポート番号をセット
tcp_t *tketh_tcp_open_server(unsigned short port,FUNCTYPE_TCPEVENT func);

// 受信の開始
BOOL tketh_tcp_listen(tcp_t *info);

// 接続先のIPアドレスを調べる
unsigned char *tketh_tcp_target_addr(tcp_t *info);

// サーバの終了
void tketh_tcp_server_terminate(tcp_t *info);

//------------------------------------------------------------------------
// コネクション管理
//------------------------------------------------------------------------

clients_stat_t *tketh_get_client_stats();

#ifdef __cplusplus
	}
#endif

#endif
