#include "cygwin.h"
#include "protocol.h"
#include "sSource.h"
#include "donkey.h"
#include "sPacket.h"
#include "misc.h"
#include "sFile.h"
#include "sTag.h"

const unsigned char OP_GLOBSERVSTATREQ = 0x96;
const unsigned char OP_GLOBSERVSTATRES = 0x97;
const unsigned char OP_SERVER_LIST_REQ = 0xA4;

class sTag *parseTag  (class sPacket *packet) {{{
	unsigned char *data   = packet->DATA();
	unsigned len = packet->Unused();
	sTag *ret = parse_tag(data, &len);
	packet->GET_BLIND(len);
	return ret;
	}}}
const char *commandName (unsigned short cmd) {{{
	switch(cmd) {
	case 0x01 : return "Hello";
// {{{ Server		    
	case 0x05 : return "SERVER (unwanted)";
	case 0x14 : return "REQ_SERVERLIST";
	case 0x15 : return "RES_OFFERFILES";
	case 0x16 : return "REQ_SEARCH";
	case 0x19 : return "Req_Source";
	case 0x1A : return "REQ_USERNAME";
	case 0x1C : return "REQ_CALLBACK";
	case 0x1D : return "queryChats (deprecated)";
	case 0x32 : return "RES_SERVER_LIST";
	case 0x33 : return "RES_SEARCH";
	case 0x34 : return "RES_ONLINESTAT";
	case 0x35 : return "CONNECT_REQUEST";
	case 0x36 : return "RES_IP";
	case 0x38 : return "RES_SERVERMSG";
// }}}
// {{{ Client
	case 0x40 : return "CHANGEID";
	case 0x41 : return "SERVER_VERSION";
	case 0x42 : return "Res_Source";
	case 0x43 : return "RES_SOURCES";
	case 0x44 : return "REQ_QUEUE";
	case 0x46 : return "PART_DATA";
	case 0x47 : return "REQ_FOR_PART";
	case 0x48 : return "no_such_file";
	case 0x49 : return "END_OF_DOWNLOAD";
	case 0x4A : return "REQ_SHAREDFILES";
	case 0x4B : return "RES_SHAREDFILES";
	case 0x4C : return "answerHello";
	case 0x4D : return "CHANGE_SERVER";
	case 0x4E : return "RES_CLIENTMESSAGE";
	case 0x4F : return "REQ_PART_STAT";
	case 0x50 : return "RES_PART_STAT";
	case 0x51 : return "REQ_PART_HASHES";
	case 0x52 : return "RES_PART_HASHES";
	case 0x54 : return "reqSlot";
	case 0x55 : return "resSlot_avail";
	case 0x56 : return "RES_CANCEL_TRANSFER";
	case 0x57 : return "RES_SLOT_CLOSE";
	case 0x58 : return "fileName_req";
	case 0x59 : return "fileName_res";
	case 0x5C : return "SLOT_idx";
// }}}		    
	case 0x60 : return "queueRank_res";
	case 0x64 : return "Login";
	case 0x66 : return "Txt_Command";
	case 0x90 : return "Req_Slot_Index";
	case 0x91 : return "Res_Slot_Index";
	case 0x92 : return "Res_Slot_Notfound";
	case 0x96 : return "Req_Server_Status";
	case 0x97 : return "Res_Server_Status";
	case 0x98 : return "Req_Seearch";
	case 0x99 : return "Res_Search";
	case 0x9A : return "Req_Source";
	case 0x9B : return "Res_Sources";
	case 0x9C : return "Req_Callback";
	case 0xA0 : return "Req_ServerList";
	case 0xA1 : return "Res_ServerList";
	case 0xA2 : return "Req_ServerDesc";
	case 0xA3 : return "Res_ServerDesc";
// {{{ GUI		    
	case 0xAA : return "CO_SERVER_LIST";
	case 0xAB : return "CO_FRIEND_LIST";
	case 0xAC : return "CO_SHARED_DIRS";
	case 0xAD : return "CO_SHARED_FILES";
	case 0xAE : return "GUI_gap_detail_res";
	case 0xAF : return "CO_CLIENT_STATS";
	case 0xB4 : return "CO_STATUS_MSG";
	case 0xB5 : return "CO_ERROR_MSG";
	case 0xB6 : return "CO_CONNECTED_TO";
	case 0xB7 : return "CO_DISCONNECTED";
	case 0xB8 : return "CO_SET_SERVER_STATS";
	case 0xB9 : return "CO_EXTENDING_SEARCH";
	case 0xBA : return "CO_SEARCH_RESULT";
	case 0xBB : return "CO_NEW_SEARCH_RESULTS";
	case 0xBC : return "CO_dl_add";
	case 0xBD : return "CO_dl_del";
	case 0xBE : return "CO_UL_add";
	case 0xBF : return "CO_UL_del";
	case 0xC0 : return "CO_NEW_UPLOAD_SLOT";
	case 0xC5 : return "CO_dl_status";
	case 0xC6 : return "CO_ul_stats";
	case 0xC7 : return "GUI_res_options";
	case 0xC8 : return "C_G_CONNECT";
	case 0xC9 : return "C_G_DISCONNECT";
	case 0xCA : return "C_G_SEARCH";
	case 0xCB : return "C_G_EXT_SEARCH";
	case 0xD0 : return "GUI_pause_Download";
	case 0xD1 : return "GUI_resumeDownload";
	case 0xD2 : return "GUI_cancelDownload";
	case 0xD3 : return "GUI_set_dlPrio";
	case 0xD5 : return "GUI_get_serverlist";
	case 0xD7 : return "GUI_get_share_dirs";
	case 0xD9 : return "GUI_start_dl_status";
	case 0xDA : return "GUI_stop_dl_status";
	case 0xDB : return "GUI_start_ul_status";
	case 0xDC : return "GUI_stop_ul_status";
	case 0xDD : return "GUI_delete_server";
	case 0xDE : return "GUI_addServer";
	case 0xE0 : return "GUI_get_share_files";
	case 0xE1 : return "GUI_req_options";
	case 0xE3 : return "GUI_gap_detail_req";
	case 0xE4 : return "C_G_CLIENT_STATS";
// }}}		    
	case 0xC501: return "eMule reqHelo";
	case 0xC502: return "eMule resHelo";
	case 0xC540: return "eMule resPartData";
	case 0xC560: return "SLOT_idx";
	case 0xC561: return "eMule comment";
	case 0xC581: return "emule reqSources";
	case 0xC582: return "emule resSources";
	case 0xD482: return "emule resSources";
	default   : break;
		}
static	char CMD[3];
	sprintf (CMD, "%02x", cmd);
	return CMD;
	}}}

bool logSend(char prefix, const cSocket *sock, unsigned short cmd, bool own) {{{
//	if (sock->Type == tSource) return false; // Testing only
//	if (sock->Type == tServer) return false; // Testing only
	if (sock->Type == tGui   ) return false; // Testing only
	if (cmd == 0x00E0 || cmd == 0x00AD) return false; // Get shared files

	switch(protocol_logLevel) {
	case 9 : break; // show all
	case 8 : if(cmd==0x0049||cmd==0xC540 ||cmd==0x46 )	      return false;	// do not even log block data
		 if(cmd==0x0042||cmd==0x0019 ||cmd==0x35	    ) return false;	// server source query/list
	case 7 : if(cmd==0xC582||cmd==0xC581 ||cmd==0x47 ||cmd==0x57) return false;	// request Part data
		 if(cmd==0xD482					    ) return false;
	case 6 : if(cmd==0x50  ||cmd==0x4F   ||cmd==0x5B)	      return false;	// Part status / unknown
	case 5 : if(cmd==0xC560||cmd==0x54   ||cmd==0x55)	      return false;	// Slot Handling
	case 4 : if(cmd==0x58  ||cmd==0x59   ||cmd==0x32 ||cmd==0x5C) return false;	// File Name handling
	case 2 : if(cmd==0x48  ||cmd==0x51   ||cmd==0x52 ||cmd==0x4D) return false;
	case 1 : if(cmd==0xC501||cmd==0xC502 ||cmd==0x01 ||cmd==0x4C) return false;	// Hello Handshake
		 if(cmd==0xBB  ||cmd==0x33   ||cmd==0x16            ) return false;
	case 0 : if(cmd==0xDA  ||cmd==0xDC   ||cmd==0xE0 ||cmd==0xAE) return false;
		 if(cmd==0xC5  ||cmd==0xC6   ||cmd==0xE4 ||cmd==0xE3) return false;
		 if(cmd==0xD5  ||cmd==0x66   ||cmd==0xAC            ) return false;
		 if(cmd==0xBE  ||cmd==0xBC   ||cmd==0xB4 ||cmd==0xD9) return false;
		 if(cmd==0xDB  ||cmd==0xCB   ||cmd==0xD1 ||cmd==0xAF) return false;
		 if(cmd==0xE1  ||cmd==0x67   ||cmd==0xDD ||cmd==0xCA) return false;
		 break;
	default: if (protocol_logLevel>7) protocol_logLevel = 7;
		 break;
		}
	if ( protocol_logLevel != 9 ) {
		if ('>' == prefix) 
			if (cmd==0x14 || cmd==0x41 || cmd==0x34 || cmd==0x15) return false;
		if ('<' == prefix) 
			if (cmd==0x38 || cmd==0x41 || cmd==0x34 || cmd==0x40) return false;
		}
	if (isTerm) printf("\33[1;%im", (prefix=='<')?31:32); // printf("\33[1;32m"); printf("\33[1;31m");
	// 31 = Rot
	// 32 = Grün
	// 33 = Gelb
	ASSERT (sock != NULL);
	printf("%s ",currentTime_str);
	printf("%c 0x%04hX %8s [%15s](%p) %-20s", prefix, cmd, txtType(sock), 
			inet_ntoa (sock->peer_ip), reinterpret_cast<const void*>(sock), commandName (cmd));
	if (isTerm)  printf("\33[0;39m");
	if (!own) printf("\n"); 
	return true;
	}}}

// ed2k link handling {{{
static bool split_suche   (void) {{{
	char *name;
	if (NULL == (name = strtok(NULL,"|"))) return false;
	Free2 (such_file);
	such_file = STRDUP (name);
	return true;
	}}}
static bool split_file    (void) {{{
	char *name;
	char *size;
	char *Hash;
	const unsigned char* hash;
	if (NULL == (name = strtok(NULL,"|"))) return false;
	if (NULL == (size = strtok(NULL,"|"))) return false;
	if (NULL == (Hash = strtok(NULL,"|"))) return false;
	if (strlen (Hash) != 32) return false;
	hash = hash_hex2bin(Hash);	
	new sFile (hash, name, atoi(size), incoming);
	return true;
	}}}
static bool split_server  (void) {{{
	struct in_addr ip;
	char *addr;
	char *port;
	if (NULL == (addr = strtok (NULL, "|"))) return false;
	if (NULL == (port = strtok (NULL, "|"))) return false;
	ip.s_addr = IP4Name(addr);
	saveServer(ip, atoi(port), 0, 0, true);
	return true;
	}}}
bool split_link    (const char *Link) {{{
	char *tst = NULL;;
	int OK = 1;
	bool ret = false;
	if (Link == NULL) OK = 0;
	char *tmp = reinterpret_cast<char*>(alloca (strlen(Link) + 1));
	if (OK) strcpy(tmp, Link);
	if (OK) tst = strtok (tmp ,"|");
	if (OK) if (tst == NULL || 0 != strcmp(tst,"ed2k://")) OK = 0;
	if (OK) tst = strtok(NULL,"|");
	if (!OK) return false;
		
	if (tst != NULL) {
		if (0 == strcmp (tst, "server")) ret = split_server ();
		if (0 == strcmp (tst, "file"  )) ret = split_file   ();
		if (0 == strcmp (tst, "suche" )) ret = split_suche  (); /* OLD ! */
		}
	return ret;
	}}}
// }}}

// vim600: fdm=marker
