#include "cSocket.h" #include "misc.h" #include "sTag.h" #include "sGui.h" #include "sFile.h" #include "donkey.h" #include "protocol.h" #include "cygwin.h" #include "sServer.h" #include "sSource.h" #include "cServer_udp.h" #include "opcodes.h" int cServer_udp::req_file_ping (in_addr ip, uint16_t port, uint8_t *file_hash) {{{ // (0x90) peer_ip.s_addr = ip.s_addr; peer_port =port; if (logSend('>', this, OP_REASKFILEPING, true)) printf("%32s\n", hash_bin2hex(file_hash)); size_t len, LEN = len = 18; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EMULEPROT); ADD_U1 (&buf, &len, OP_REASKFILEPING); ADD_HASH (&buf, &len, file_hash); ASSERT(len == 0); Write(BUF, LEN); return 1; }}} bool cServer_udp::UDP_next_ping ( ) {{{ // (0x96) uint32_t quest; if (!nextPing (&peer_ip, &peer_port, &quest)) return false; peer_port += 4; if (logSend('>', this, OP_GLOBSERVSTATREQ, false)); size_t len, LEN = len = 6; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_GLOBSERVSTATREQ); ADD_U4 (&buf, &len, quest); ASSERT(len == 0); ASSERT(fd < 10000); ASSERT (16 != (mask&16)); Write(BUF, LEN); return true; }}} bool cServer_udp::UDP_search4gui (const sGui *gui ) {{{ // (0x98) struct in_addr ip; if (!nextServer (&ip, &peer_port)) return false; peer_ip = ip; peer_port += 4; ASSERT(peer_port != 0); printf("Extending search to %s %u\n", inet_ntoa(ip), peer_port); ASSERT (gui!=NULL); if (logSend('>', this, OP_GLOBSEARCHREQ, false)); size_t len, LEN = len = 2 + gui->searchLen(); unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_GLOBSEARCHREQ); memcpy ( buf, gui->searchTree(), len); Write(BUF, LEN); return true; }}} bool cServer_udp::UDP_req_sources (in_addr ip,uint16_t port, const uint8_t *Hash) {{{ // (0x9A) ASSERT(Hash != NULL); if (0 == (ip.s_addr & 0xFF000000)) return false; if (0 == (ip.s_addr & 0x000000FF)) return false; class sFile *file = forHash(Hash); if (file == NULL) return false; ASSERT(file->status != ALL_DONE && !file->Pause()); peer_port = port + 4; peer_ip = ip; if (port == 0) return false; if (!IP_is_OK (ip)) return false; if (logSend('>', this, OP_GLOBGETSOURCES, true)) printf("%32s\n", hash_bin2hex(Hash)); actionServer (ip, port); size_t len, LEN = len = 18; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_GLOBGETSOURCES); ADD_HASH (&buf, &len, Hash); ASSERT(len == 0); Write(BUF, LEN); return true; }}} bool cServer_udp::UDP_req_callback (uint32_t idx) {{{ // (0x9C) if (logSend('>', this, OP_GLOBCALLBACKREQ, true)) printf("%u\n", idx); size_t len, LEN = len = 12; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER ); ADD_U1 (&buf, &len, OP_GLOBCALLBACKREQ ); ADD_U4 (&buf, &len, cSocket::getLocalExternalIP().s_addr); // should check peer_ip here ADD_U2 (&buf, &len, pref.ports.client ); ADD_U4 (&buf, &len, idx ); ASSERT (len == 0); Write(BUF, LEN); return true; }}} bool cServer_udp::UDP_next_info (in_addr ip, uint16_t port ) {{{ // (0xA2) peer_ip = ip; peer_port = port + 4; if (logSend('>', this, OP_SERVER_DESC_REQ, false)); size_t len, LEN = len = 2; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_SERVER_DESC_REQ); ASSERT(len == 0); Write(BUF, LEN); return true; }}} bool cServer_udp::req_server_list (struct in_addr ip, uint16_t port ) {{{ // (0xA4) peer_port = port + 4; peer_ip = ip; if (logSend('>', this, OP_SERVER_LIST_REQ, false)); size_t len, LEN = len = 2; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_SERVER_LIST_REQ); ASSERT(len == 0); Write(BUF, LEN); return true; }}} bool cServer_udp::res_ping (unsigned query, unsigned user, unsigned files) {{{ if (logSend('>', this, OP_GLOBSERVSTATRES, true)) printf("%5u - %5u\n", user, files); size_t len, LEN = len = 14; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1(&buf, &len, OP_EDONKEYHEADER); ADD_U1(&buf, &len, OP_GLOBSERVSTATRES); ADD_U4(&buf, &len, query); ADD_U4(&buf, &len, user); ADD_U4(&buf, &len, files); ASSERT(len == 0); Write(BUF, LEN); return true; }}} // Client-Server UDP handling (0x97) ... (0x9B) int cServer_udp::RES_rang (unsigned char *data, size_t len) {{{ // (0x91) struct eSources *info = Source_ip(peer_ip); if (info == NULL) return 0; setSources_version (peer_ip, info->version | 0x01000000); unsigned rank = GET_U2(&data, &len); if (rank > 0) setSource_timeout(peer_ip, currentTime + 5 * 60); else { setSource_timeout(peer_ip, currentTime - 10); setSources_version (peer_ip, info->version & 0xFEFFFFFF); } if (logSend('<', this, 0x91, true)) printf("%u\n", rank); return 1; }}} int cServer_udp::RES_not_found (unsigned char * , size_t ) {{{ // (0x92) struct eSources *info = Source_ip(peer_ip); if (logSend('<', this, 0x92, false)); if (info == NULL) return 0; setSources_version (peer_ip, info->version | 0x01000000); setSource_timeout(peer_ip, currentTime - 10); if (info == NULL) return 0; FILE_LIST { if (File_info_get(info->hash,akt->hash,akt->size, NULL)) { File_info_del (info->hash,akt->hash); return 1; } } return 1; }}} int cServer_udp::RES_queue_full (unsigned char * , size_t ) {{{ // (0x93) if (logSend('<', this, 0x93, false)); struct eSources *info = Source_ip(peer_ip); if (info == NULL) return 0; setSources_version (peer_ip, info->version | 0x01000000); setSource_timeout(peer_ip, currentTime + 5 * 60); return 1; }}} int cServer_udp::REQ_ping (unsigned char *data, size_t len) {{{ // (0x96) if (logSend('<', this, 0x96, false)); int cnt = sServer::count; uint32_t query = GET_U4(&data, &len); res_ping (query,cnt, cnt*7); return 1; }}} int cServer_udp::RES_ping (unsigned char *data, size_t len) {{{ // (0x97) if (logSend('<', this, 0x97, false)); if (len != 12) return 0; GET_U4(&data, &len); uint32_t user = GET_U4(&data, &len); uint32_t files = GET_U4(&data, &len); saveServer(peer_ip, peer_port - 4, files, user, false); if (!pongServer(peer_ip)) return 1; struct eServers *s = Server_ip (peer_ip); if (s == NULL) return 1; if (s->name[0] == 0 && s->desc[0] == 0) { UDP_next_info (s->ip, s->port); req_server_list (s->ip, s->port); } return 1; }}} int cServer_udp::RES_sources (unsigned char *data, size_t len) {{{ // (0x9B) if (logSend('<', this, 0x9B, false)); if (len <= 17) return 0; tHash hash; GET_HASH(&data, &len, hash); unsigned cnt = GET_U1(&data, &len); log (1,"Response for (%3u) Sources for %32s from (%s:%i)\n", cnt, hash_bin2hex(hash),inet_ntoa(peer_ip), peer_port); while (cnt-- && len>=6) { struct in_addr c_ip; uint16_t c_port; c_ip.s_addr = GET_U4(&data, &len); c_port = GET_U2(&data, &len); if (htonl(c_ip.s_addr) < LOW_ID || c_port == 0) { UDP_req_callback (c_ip.s_addr); } else { insertFiles (hash, c_ip, 0, NULL); addSource (c_ip, c_port, 0x00000000,true); } } return 1; }}} int cServer_udp::REQ_callback (unsigned char *DATA, size_t len) {{{ // (0x9C) if (logSend('<', this, 0x9C, false)); if (len != 10) return 0; unsigned char *data = DATA; in_addr ip; ip.s_addr = GET_U4 (&data, &len); uint16_t port = GET_U2 (&data, &len); uint32_t idx = GET_U4 (&data, &len); SERVER_LIST { if (akt->my_id != idx) continue; akt->CMD_callback (ip, port); return 1; } return 0; }}} int cServer_udp::RES_search (unsigned char *DATA, size_t LEN) {{{ unsigned char *data = DATA; size_t len = LEN; printf("UDP Search Results\n"); log (1,"New extended results received from %s\n", inet_ntoa(peer_ip)); size_t glen, GLEN = glen = len + 6; unsigned char *gbuf, *GBUF = gbuf = reinterpret_cast(alloca(GLEN)); ADD_U1 (&gbuf, &glen, OP_EDONKEYHEADER); ADD_U4 (&gbuf, &glen, GLEN - 5); ADD_U1 (&gbuf, &glen, CO_ED_SEARCH_RESULT); ASSERT(glen == len); memcpy (gbuf, data, len); GUI_LIST akt->Write(GBUF, GLEN); data = DATA; len = LEN; if (LEN > 0) { tHash hash; GET_HASH(&data, &len, hash); GET_U4 (&data, &len); GET_U2 (&data, &len); class sTag *tag = parse_tag (data, &len); if (tag == NULL) return 0; printf("Found file with %i info len %s\n", len, tag->name); insertFiles (hash, peer_ip, len, data); LEN -= len; data += len; len = LEN; delete tag; // The Rest is List of IP:Port where the file can be found *cool* TODO ad it to the file list } return 1; }}} int cServer_udp::RES_server_lst (unsigned char *DATA, size_t LEN) {{{ // (0xA1) if (logSend('<', this, 0xA1, false)); unsigned char *data = DATA; size_t len = LEN; unsigned cnt = GET_U1 (&data, &len); if (cnt == 0) return 0; do { in_addr ip; ip.s_addr = GET_U4 (&data, &len); uint16_t port = GET_U2 (&data, &len); if (port == 4665) port = 4661; // very posible that this is the udp port if (htonl(ip.s_addr) > 0x00FFFFFF) saveServer (ip, port, 0, 0, false); } while (--cnt > 0); return 1; }}} int cServer_udp::RES_info (unsigned char *DATA, size_t LEN) {{{ // (0xA3) if (logSend('<', this, 0xA3, false)); if (!pongServer(peer_ip)) return 1; unsigned char *data = DATA; size_t len = LEN; char *name = GET_S2_ (&data, &len); char *desc = GET_S2_ (&data, &len); log (1,"UDP Info "); if (name != NULL) { setServer_name (peer_ip, 0, name); log (1,"NAME: %32s ", name); Free2 (name); } if (desc != NULL) { setServer_desc (peer_ip, 0, desc); log (1,"DESC: %32s ", desc); Free2 (desc); } log (1,"\n"); return 1; }}} int cServer_udp::REQ_file_ping (unsigned char *data, size_t in_len) {{{ // (0x90) TODO if (logSend('<', this, 0x9A, false)); if (in_len != 16) return 0; tHash hash; GET_HASH(&data, &in_len, hash); sFile *file = forHash(hash); if (file == NULL) { size_t len, LEN = len = 2; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_FILENOTFOUND); ASSERT(len == 0); Write (BUF, LEN); return 1; } else { size_t len, LEN = len = 4; unsigned char *buf, *BUF = buf = reinterpret_cast(alloca(LEN)); ADD_U1 (&buf, &len, OP_EDONKEYHEADER); ADD_U1 (&buf, &len, OP_REASKACK); ADD_U2 (&buf, &len , 50); ASSERT(len == 0); Write(BUF, LEN); } return 1; }}} int cServer_udp::doRead_high(void) {{{ unsigned char *data = reinterpret_cast(read_buf); size_t len = read_len; if (len <= 0) return 0; dl_left -= len; // i know it maybe miss bites unsigned proto = GET_U1((&data), &len); unsigned code = GET_U1((&data), &len); if (proto != OP_EDONKEYHEADER && proto!=0xC5) { printf ("UDP proto: 0x%02X <= %15s:%5u\n", proto, inet_ntoa(peer_ip), peer_port); dump(read_buf, read_len); Read(read_buf, read_len); return 0; } // printf("cServer_udp::doWork(0x%02X) = %u\n", code, len); switch (code) { case 0x90 : REQ_file_ping (data, len); break; case 0x91 : RES_rang (data, len); break; case 0x92 : RES_not_found (data, len); break; case 0x93 : RES_queue_full (data, len); break; case 0x96 : REQ_ping (data, len); break; case 0x97 : RES_ping (data, len); break; // case 0x98 : printf("UDP 0x97\n"); // REQ_search TODO case 0x99 : RES_search (data, len); break; case 0x9A : break; // REQ_source TODO // OP_GLOBGETSOURCE case 0x9B : RES_sources (data, len); break; case 0x9C : REQ_callback (data, len); break; case 0x9E : break; // No such client (wrong Client ID) case 0xA0 : break; // TODO case 0xA1 : RES_server_lst (data, len); break; case 0xA2 : break; // TODO case 0xA3 : RES_info (data, len); break; default : printf ("UDP [%15s] <= 0x%02X : %02X\n", inet_ntoa(peer_ip), code, proto); dump (data, len); printf("\n"); if (code != 0xA0) break; // ASSERT(0); break; } Read(read_buf, read_len); return 0; }}}