#ifndef kademlia_h
#define kademlia_h
#include <time.h>
#include "cSocket.h"
#include "sFile.h"
#include "cZone.h"
#include "cSearchManager.h"
// Hash_Len defined in BYTE not in BIT 16=>128 Bit
#define	KAD_HASH_LEN	16

#define len4	unsigned int
#define	len2	unsigned short
#define len1	unsigned char

unsigned XOR_distance (const len1 *a, const len1 *b);

extern class cSearchManager	manager;
extern class cZone              overnet;

class cKademlia: public cSocket {
	private:
		FILE	*boot_file;
		time_t	 next_ip_query;
	public:
		int	 result_countdown;
		time_t	 last_query;
		unsigned best_publize;
		int	 status;
		unsigned file_size;
		unsigned result_limit;
		time_t	 search_started;
		len1	 seek_hash[KAD_HASH_LEN];
		len1	 last_publish[KAD_HASH_LEN];
	private:
		bool	 boot_done;
	public:
		
			 cKademlia (len2 port);
			~cKademlia ();
		bool	 Search	(const len1 *hash);
		void	 load_Boot		(const char *boot);
virtual		int 	 doRead_high (void);
virtual		void	 Work (void);
		bool	 send_Raw(struct in_addr ip, uint16_t port, const unsigned char *data, size_t len);

	private:
		bool	 logSend   (char dir, unsigned cmd, size_t len, bool extra = false);
		void     parsePeer_lst       	(unsigned char **buf , unsigned *len, unsigned cnt);
		void	 Init_Search		(void);
		// send Handling {{{	
		bool	 send_Connect 		(void			); // (0x0A) request boot list
		bool	 send_Connect_reply	(void			); // (0x0B) return list of other clients
		bool	 send_Publicize		(void			); // (0x0C) publize my client
		bool	 send_Publicize_ack	(void			); // (0x0D) ack the publize of my client
		bool	 send_Search		(uint8_t for_type, uint8_t *for_hash	); // (0x0E) search after an HASH (user/file)
		bool	 send_Search_next	(unsigned cnt, const uint8_t *p_hash);	// (0x0F) List of peers to try next time
//		bool	 send_Search_info  	(void			); // (0x10) req Result
		bool	 send_Search_result     (uint8_t *p_hash, unsigned min, unsigned max); // (0x11) return info
		bool	 send_search_end	(uint8_t *p_hash	); // (0x12) end the Query resonse (no more infos follow)
public:		bool	 send_Publish		(const uint8_t *k,size_t l, const char*n); // (0x13) Publish an meta description
private:	bool	 send_Publish_ack	(const uint8_t *p_hash	); // (0x14) acknowlegde the send_Publish
		bool	 send_Identify_reply	(void			); // (0x15)
		bool	 send_Identify_ack	(void			); // (0x16)
		bool	 send_FireCon		(void			); // (0x18)
		bool	 send_FireCon_ack	(void			); // (0x19)
		bool	 send_FireCon_nack	(void			); // (0x1A)
		bool	 send_IP_query		(void			); // (0x1B) Ask after BOOT what the other see as my ip
		bool	 send_IP_answer		(void			); // (0x1C) Answer for send_IP_query
		bool	 send_IP_end		(void			); // (0x1D) returned after send_IP_answer
		bool	 send_Identify		(void			); // (0x1E) 
		// }}}
	// recv Handling {{{
		bool	 recv_Connect 		(unsigned char *buf, size_t len); // (0x0A) request boot list
		bool	 recv_Connect_reply	(unsigned char *buf, size_t len); // (0x0B) return list of other clients
		bool	 recv_Publicize		(unsigned char *buf, size_t len); // (0x0C) publize my client
		bool	 recv_Publicize_ack	(unsigned char *buf, size_t len); // (0x0D) ack the publize of my client
		bool	 recv_Search		(unsigned char *buf, size_t len); // (0x0E) search after an HASH (user/file)
		unsigned recv_Search_next	(unsigned char *buf, size_t len); // (0x0F) List of peers to try next time
		bool	 recv_Search_info  	(unsigned char *buf, size_t len); // (0x10) for what ?
		bool	 recv_Search_result	(unsigned char *buf, size_t len); // (0x11) Query successful return the stored data
		bool	 recv_search_end	(unsigned char *buf, size_t len); // (0x12) end the Query resonse (no more infos follow)
		bool	 recv_Publish		(unsigned char *buf, size_t len); // (0x13) Publish an meta description
		bool	 recv_Publish_ack	(unsigned char *buf, size_t len); // (0x14) acknowlegde the send_Publish
		bool	 recv_Identify_reply	(unsigned char *buf, size_t len); // (0x15)
		bool	 recv_Identify_ack	(unsigned char *buf, size_t len); // (0x16) recive TCP_Port
		bool	 recv_FireCon		(unsigned char *buf, size_t len); // (0x18) i handle the firewalled server
		bool	 recv_FireCon_ack	(unsigned char *buf, size_t len); // (0x19)
		bool	 recv_FireCon_nack	(unsigned char *buf, size_t len); // (0x1A)
		bool	 recv_IP_query		(unsigned char *buf, size_t len); // (0x1B) Ask after BOOT what the other see as my ip
		bool	 recv_IP_answer		(unsigned char *buf, size_t len); // (0x1C) Answer for send_IP_query
		bool	 recv_IP_end		(unsigned char *buf, size_t len); // (0x1D) returned after send_IP_answer
		bool	 recv_Identify		(unsigned char *buf, size_t len); // (0x1E)
	// }}}
	};

/*
Connect		0x0A <PEER (sender)>				(25 Byte)
Connect_reply	0x0B <LEN2> <PEER>[len]
Publicize	0x0C <PEER (sender)>				(25 Byte)
Publicize_ack	0x0D (null)					( 2 Byte)
Search		0x0E <CNT> <HASH>				(19 Byte)	// CNT tell the number of whised answers
Search_next	0x0F <HASH> <LEN2> <PEER>[len]			// min len should be 2
Search_info  	0x10 <HASH> <KIND> <MIN> <MAX>			(25 Bytes)
Search_result	0x11 <SEARCH_HASH> <RETURN_HASH> <CNT4> <META>[cnt]		// if search was keyword they can divergate
Search_end	0x12 <HASH> <IP?>
Publish		0x13 <HASH> <HASH> <CNT4> <META>[cnt]
Publish_ack	0x14 <HASH>
Identify_reply	0x15 <CONTACT (sender)>				// Answer to 0x1E
Identify_ack	0x16 <PORT_tcp (sender)>			// Answer to 0x15
FireCon		0x18 <HASH> <PORT_tcp>				// hash of the firewall server
FireCon_ack	0x19 <HASH>
FireCon_nack	0x1A <HASH>
IP_query	0x1B <PORT_tcp>
IP_answer	0x1C <IP>
IP_end		0x1D (null)
Identify	0x1E (null)				// request the other side to tell hash/ip/port

CONTACT ::= <HASH><IP><PORT (udp)>
PEER	::= <CONTACT><KIND>
HASH 	::= 16 Byte value (for files and tree-md4)
IP	::=  4 Byte value (IP in network order)
PORT	::=  2 Byte value port
KIND	::=  1 Byte (what is the exact meaning)
LEN2	::=  2 Byte "unsigned short"
CNT4	::=  4 Byte "unsigned int"
META	::= Meta Tag <mTYPE> <mLEN> <mKEY> <mValue> see eDonkey Protocol
mTYPE	::=  1 Byte
mLEN	::=  2 Byte
mKEY	::=  mLen Bytes
mValue	::=  * Bytes (depend on mTYPE)

Substring search:
- stransform to lower text
- use " ()[]{}<>,._-!?" as Wort seperator
- ignore file extensions
- ignore 1 and 2 Letter words
- use the md4(keyword) as hash (Thomas-Lussnig => TIP: use the largest word (most significant))

SEARCH:
- basic search (0x0F) algorythmen is used for source,substring,publish find and publish
- depend on the type once info(0x10) where send in the other case publice(0x0C)
or publish(0x13) so the nereast nodes become their information.
- the you send (0x0F) to nearer nodes till you got 20 best or timeout
- if an node can not suply better ones take them as temporary best and send detail query/publish
- until you have 20 best the better replace the notes where log(2)(distance) is more bad.

Next Client to Ask:
- where the log(2) (XOR(seek_hash,client_hash)) is smalest and not already asked

Tag:
"loc"		=> "bcp://217.233.215.74:4662"
"filename"	=> string
"size"		=> int
"ip"		=> int
"port"		=> int

*/

#endif
