Interoperari In Reteaua Gnutella

Introducere

1.1. Scurt Istoric Gnutella.

Este universal cunoscut că mp3-urile au început să ia locul CD-urilor adevărate, fiind foarte tentant să ai pe un singur CD cu .mp3-uri echivalentul a 10 CD-uri audio obișnuite. Cu diferențe de calitate sesizabile numai de către puriști, mp3-urile au invadat calculatoarele din lumea largă într-un timp incredibil de scurt.

Luând în considerarea aceste lucruri era inevitabila apariția Napster-ului [18]: un fel de ‘piață centrală’ în care fiecare partajează datele care le deține pentru a putea căuta și transfera (download-a) de la ceilalți membri din rețea, informațiile și datele pe care le dorește.

După câteva runde legale în care s-a încercat scoaterea Napster-ului din competiție, un succes parțial l-au marcat cei de la Metallica, care au adunat o listă de câteva mii de utilizatori Napster care au descărcat – via Napster – copii pirat ale unor piese ale formației. Dând curs unei decizii judecătorești în acest sens, cei de la Napster au "bannat" (interzis accesul) pe toți cei de pe lista neagră a celor de la Metallica.

Cu nu foarte mult timp în urmă, mai precis în anul 2000, o companie numită Nullsoft, autorii Winamp-ului, cel mai popular player soft de .mp3-uri, a pornit un proiect numit Gnutella [19]. După un anumit timp, la modul oficial, autorilor li s-a interzis să își continue proiectul (noilor proprietari ai firmei li s-a făcut puțintel frică de avalanșa de procese posibile), iar sursa promisă încă nu a devenit de-adevărat publică. Paradoxal, cu toate acestea, Gnutella continuă să crească și să se răspândească rapid. Simplu ca și concept, este un protocol construit peste http și care permite schimbul de fișiere între oricare doi participanți. Inovația cea mai importantă constă în anularea oricărui punct central precum și a diferenței între un server și un client. Nu mai există chiar nici un punct central, gen Napster, care să poată fi obligat relativ ușor să se plece unor cerințe ale unei autorități. Fiind un protocol, va fi extrem de greu (imposibil poate) de găsit o argumentație care să justifice interzicerea folosirii acestuia.

Numele de Gnutella a venit de la GNU [12] pentru că urmă să fie open source software, iar Nutella pentru că "Nutella" este o ciocolată incredibil de populară printre europeni. Termenul de GNU este un acronim recursiv și vine de la "GNU Nu-i Unix" (GNU’s Not Unix) și se pronunță exact cum se scrie – GNU. Proiectul GNU a fost lansat în 1984 pentru a dezvolta un sistem de operare complet, similar Unix-ului, care este software liber (free software). Variante ale sistemului de operare GNU, care folosesc kernelul Linux, sunt folosite acum pe scară largă; deși aceste sisteme sunt deseori numite "Linux", ele sunt mai corect numite sisteme GNU/Linux. Proiectului GNU a fost creat de Richard Stallman și a apărut la Massachusetts Institute of Technology. Acest proiect a fost anunțat public pe 27 Septembrie 1983 pe site-urile net.unix-wizards și net.usoft și lucrul efectiv la proiect a început în 5 Ianuarie 1984, Stallman fiind nevoit să renunțe la funcția sa de la MIT pentru a-si dedica și mai mult timp proiectului GNU.

1.2. Prezentare Generală

Scopul acestei lucrări este de a studia și analiza căutările în rețelele distribuite P2P (peer-to-peer) și de a găsi o metoda cât mai eficientă pentru procesarea și rutarea interogărilor în aceste rețelele P2P.

Paradigma rețelelor P2P a apărut ca un mod nou pentru interconectarea sistemelor individuale. Un dezavantaj al rețelelor de acest tip, care încearcă evitarea folosirii unui server pentru centralizarea indecșilor, este lipsa robusteții o data cu creșterea numărului de noduri din rețea. în aceasta lucrare sunt prezentate câteva modificări ale paradigmei rețelelor distribuite, care permit existenta unui index la nivelul unui nod și rutarea interogărilor bazata pe acest index. Aceasta modificare are ca rezultat evitarea căutărilor exponențiale în sistemele distribuite și oferă totodată și o potențiala soluție pentru scalarea interogărilor în rețelele peer-to-peer.

Alt scop declarat al acestei lucrări este implementarea unui client al rețelei P2P (peer-to-peer) Gnutella, care să permitea căutarea și transferarea de informații și date (sub formă de fișiere) din aceasta rețea.

Aplicația creata suporta conectarea la diferite noduri (host-uri) din rețeaua Gnutella, noduri care se mai numesc și ultrapeer. Sunt oferite totodată funcții de inserare de noduri la care aplicația să încerce să se conecteze, posibilitatea de a elimina unul sau mai multe noduri la care aplicația s-a conectat deja, dar și de a vizualiza proprietățile și anumite informații în legătura cu nodurile la care s-a reușit conectarea.

Dacă s-a reușit conectarea la cel puțin un nod (ultrapeer) din rețeaua Gnutella atunci se pot efectua diferite căutări în aceasta rețea. Căutarea în rețeaua Gnutella se face după numele fișierelor sau după cuvinte ce sunt conținute în numele fișierelor. Aplicația dezvoltata suporta și o căutare mai avansata în care se poate specifica tipul fișierelor dorite și în ce limite să se încadreze dimensiunea acelor fișiere. în cazul în care au fost găsite rezultate la interogarea introdusa de utilizator, acesta poate selecta dintre fișierele găsite cele pe care dorește să le transfere (download-eze).

Aplicația oferă și funcții de management al transferurilor de fișiere, funcții cum ar fi : oprirea și repornirea de download-uri de fișiere, posibilitatea de a executa fișierele care s-au transferat și fișierele parțiale, posibilitatea de a înlătura definitiv anumite download-uri din lista, dar și de a vizualiza proprietățile unui anumit download.

Cu ajutorul aplicației create s-a făcut și o analiza a căutărilor, și a timpilor de căutare, în rețeaua Gnutella punându-se în evidenta câteva dintre caracteristicile definitorii ale acestei rețele și a rețelelor P2P în general.

Studiu Bibliografic

2.1. Introducere în Rețele P2P

Rețelele peer-to-peer (P2P) [3, 4] au devenit un mediu popular pentru partajarea de cantități considerabile de date. Aceste sisteme distribuie costurile de partajare a informațiilor – spațiu ocupat pe disc pentru stocarea fișierelor și lățime de banda pentru transferarea acestora – prin ‘peer-urile’ din rețea, permițând astfel realizarea de aplicații scalabile fără a fi nevoie de servere puternice și costisitoare. Capacitatea rețelelor P2P de a construi un sistem foarte ‘bogat’ în resurse prin agregarea resurselor unui număr de noduri independente permite acestor sisteme să micșoreze capacitățile multor sisteme centralizate pentru costuri relativ reduse. Exemplele în acest sens includ masiva putere computațională a sistemelor ca SETI@Home [20] sau capacitatea de a agrega și stoca informații. Numai sistemul de partajare a fișierelor Kazaa [17] a raportat, începând cu data de 30 aprilie 2003, peste 4.5 milioane de utilizatori, care au partajat un total de 7  peta bytes de date.

Sistemele peer-to-peer (P2P)  sunt sisteme distribuite în care noduri cu roluri și capacități egale fac schimb de informații și servicii în mod direct și reciproc. în ultimii ani, rețelele P2P au apărut ca o modalitate foarte utilizata de a partaja cantități uriașe de date. De exemplu, sistemul Morpheus [23] de partajare a fișierelor multimedia a raportat peste 470.000 de utilizatori care au împărțit un total de 0.36 peta bytes de date, începând din 26 octombrie 2001. Partajarea unui volum atât de mare de informații este posibilă datorita distribuirii costurilor principale – spațiul ocupat pe disc pentru stocarea fișierelor și lățimea de banda pentru a le transfera – prin ‘peer-urile’ din rețea. Pe lângă capacitatea de a aduna și utiliza cantități mari de resurse, performantele sistemelor P2P existente includ capacități de auto-organizare, de balansarea cantități de informație,  de adaptare și toleranta la diferite tipuri de erori.

Cheia utilizării la scara larga a unui sistem P2P de partajare a datelor o reprezintă tehnicile eficiente de căutare și găsire a datelor. în sisteme unde persistenta și accesibilitatea datelor nu sunt garantate sau necesare, cum ar fi Gnutella [19], Napster [18] și Morpheus [23], tehnicile de căutare își permit să aibă anumita marja de eroare. Pe lângă aceasta, deoarece aceste sisteme sunt folosite de o gama larga de utilizatori, care pot face parte din diferite organizații, tehnicile de căutare nu își permit să controleze strict rețeaua.

În sistemele P2P de partajare a datelor utilizatorii generează interogării și primesc în schimb rezultate, cum ar fi date sau pointeri înspre date, cu ajutorul mecanismului de căutare. Datele partajate în acest sistem pot fi de orice tip. în majoritatea cazurilor utilizatori partajează fișiere, cum ar fi fișiere cu muzica, cu filme, cu imagini, cu articole de știri, cu pagini web, etc. Interogările pot lua orice formă, care este adecvata tipului de date partajate. Spre exemplu într-un sistem de partajare a fișierelor, interogările pot fi sub forma unor cuvinte-cheie și căutarea poate fi definita pe diferite porțiuni ale documentului (spre exemplu : ‘header’, title, ‘meta-data’).

Un mecanism de căutare definește comportamentul nodurilor din rețea în 3 secțiuni :

Topologie : definește modul în care sunt conectate nodurile între ele. în unele sisteme, de exemplu Gnutella, nodurile se pot conecta la ce noduri doresc. în alte sisteme nodurile sunt organizate într-o structura mai rigida, în care numărul și natura conexiunilor sunt dictate de protocol. Prin definirea unei topologii rigide a rețelei se poate mari eficiența dar se va restrânge autonomia.

Plasarea datelor : definește modul în care datele sau ‘meta datele’ sunt distribuite în rețeaua P2P.

Rutarea mesajelor: definește procesul de propagare al mesajelor în rețea. Când un nod generează o interogare, mesajul conținând interogarea este trimis la un anumit număr de noduri vecine (noduri la care respectivul nod este conectat), care la rândul lor pot să trimită mai departe mesajul, secvențial sau paralel, către vecini lor, și așa mai departe. Când și către cine sunt trimise mesajele se decide cu ajutorul protocolului de rutare. Deseori protocolul de rutare poate profita de anumite cai cunoscute în rețea și de locația anumitor date pentru a reduce numărul de mesaje trimise.

Există provocări importante care trebuie depășite înainte ca potențialul complet al sistemelor peer-to-peer să poată fi atins. De exemplu,  procesul de scalare al rețelei și autonomia nodurilor îngreunează identificarea și distribuția resurselor disponibile. în plus, datorita faptului ca unele ‘peer-uri’ pot fi malițioase (malicious), ‘peer-urile’ pot primi informații neautentice sau pot fi victime ale nodurilor care refuza să satisfacă o anumita interogare(Denial of Service, DoS).

2.1.1. Securitatea în Rețelele P2P

Sistemele de partajare a datelor, P2P, prezintă un risc ridicat de susceptibilitate la multe forme de atacuri malițioase. în aceste tipuri de sisteme, nodurile operează în mod autonom și orice nod care ‘cunoaște’ protocolul sistemului poate intra în respectivul sistem. Totuși, faptul ca un nod implementează acest protocolul nu înseamnă ca o face bine intenționat. Astfel, nodurile nu pot să presupună că alte noduri vor răspunde la interogările lor, ca le vor limita numărul de interogări pe care le generează, ca vor produce rezultate autentice sau ca vor menține conținutul interogărilor privat.

Atacurile împotriva accesibilității unui sistem sunt numite adesea atacuri de tip refuzare de servicii (denial-of-service, DoS). Aceste atacuri au capacitatea de a degrada un sistem sau de a închide (shut down) un sistem, astfel încât clienții malițioși folosesc și epuizează resursele (cicluri CPU, spațiul de pe disc, lățimea de unda etc), așa încât aceste resurse nu mai pot fi utilizate de clienții legitimi ai sistemului. Pe lângă acestea, o caracteristica a acestui tip de atacuri consta în dificultatea de a discerncuri consta în dificultatea de a discerne între nodurile malițioase și cele care sunt foarte solicitate.

2.2. Introducere în Rețeaua Gnutella

Încă de la început principiul fundamental al Internetului a fost partajarea de informații. Mulți nu au realizat acest lucru, dar la o analiza mai temeinica, Internetul a existat din totdeauna pentru simplu motiv al partajării informațiilor. Gnutella [19, 9, 22] furnizează Internetului o componenta care are ca principiu de funcționare chiar principiile care au pus baza Internetului.

La începuturi, când ‘www’-ul (World Wide Web) si-a început expansiunea se puneau pe o pagina câteva link-uri spre alte pagini ; apariția hiperlegăturilor (hyperlink) și în general a www-ului, la începutul anilor 1990 fiind un pas uriaș spre dezvoltarea Internetului din zilele noastre. Similar, apariția Napster-ului [18], a generat o dezvoltare energica a tehnologiilor care permit partajarea și schimbul de informații și de date. Aceasta idee nu a murit cu toate ca Napster-ul a fost dat în judecată, și chiar închis, ci a continuat să se dezvolte atingând cote nebănuite.

Gnutella a apărut în perioada sfârșitul anului 1999 începutul anului 2000 când compania Nullsoft (care recent a fost cumpărată de AOL) s-a decis să dezvolte un protocol nou peste HTTP (Hyper Text Transfer Protocol) care să permită partajarea de date în cadrul rețelei.

Figura 2.1 : Modelul de protocol Gnutella

Aceasta rețea remodelează ‘atmosfera’ Internet-ului, permițând utilizatorilor să schimbe informații, într-o maniera ne mai întâlnită până acum. Mai simplu spus Gnutella reintroduce interacțiunile personale dintre sisteme, diferența fata de rețeaua Napster fiind ca Gnutella nu necesita un server central care să coordoneze toata activitatea. Când se folosește un client Gnutella și respectivul sistem se conectează la rețeaua Gnutella, se partajează datele care se doresc a fi publice. Bineînțeles se poate alege ce date vor fi partajate, putându-se partaja, un fișier, un director sau chiar tot harddiskul (ceea ce nu este indicat) sau nepartajând nici un fișier.

Gnutella permite căutarea de informații pe cale anonima și permite căutarea de informații într-un mod care diferă de cel al motoarelor de căutare tradiționale, cum ar fi Yahoo! [11], deoarece spre deosebire de aceste motoare de căutare informația nu este controlată sau filtrata la furnizare.

2.2.1. Principii de Funcționare

Gnutella nu folosește pentru comunicare principiul de client – server, un utilizator putând fi în același timp și client și server. Un utilizator poate fi la un moment dat, ‘ultrapeer’, care are rolul de a ruta interogările și răspunsurile la aceste interogări ale clienților care sunt conectați la el.

Rețeaua Gnutella este compusa din sisteme, numite noduri, pe care fiecare rulează un client Gnutella. Acest client, să zicem un nod A, dispune de o lista de noduri și încearcă să se conecteze la fiecare nod din acea lista, eliminând din lista nodurile la care nu a reușit să se conecteze. Aceasta lista fiind relativ mare, șansa de a se conecta la cel puțin un nod, să zicem B, fiind destul de mare. O data ce nodul A s-a conectat la nodul B, acesta din urmă va trimite nodului A propria lista cu nodurile la care a reușit să se conecteze. Nodul A va încerca să se conecteze la aceste noduri, dar și la alte noduri, pe care le primește de la celelalte noduri la care este conectat, până când atinge o anumita limita de număr de noduri la care este conectat. Celelalte noduri care nu au fost încă încercate vor fi însă păstrate, iar cele la care s-a încercat conectarea, dar nu s-a reușit vor fi eliminate.

Când nodul A vrea să genereze o căutare, el trimite o interogare la fiecare nod la care este conectat (în varianta mai noua a protocolului interogarea este trimisa pe baza unor indecși de rutare și nu va fi trimisa la toate nodurile). Având în vedere caracterul foarte dinamic al rețelei este posibil ca unele noduri la care s-a conectat nodul A să nu mai fie disponibile momentan, în acest caz A încercând să se conecteze la alte noduri din lista sa de noduri salvata. Numărul de noduri la care un utilizator este conectat este relativ mic, între 5 și 20 de noduri. La primirea unei interogări fiecare nod din rețea trimite aceasta interogare mai departe la nodurile la care este conectat, cu excepția nodului de la care a venit.

Dacă o anumita interogare este satisfăcută nodul care deține rezultatul interogării contactează direct nodul care a emis interogarea, adresa IP a nodului care inițiază interogarea fiind inclusa în pachetul interogării. Apoi se negociază transferul de fișiere, iar după aceasta transferul efectiv poate să înceapă. Dacă s-au găsit mai multe copii ale aceluiași fișier nodul care a generat interogarea poate să downloadeze bucăți diferite ale respectivului fișier de la noduri diferite, acest lucru făcând ca rata de transfer al datelor să crească considerabil.

Când nodul A se deconectează de la rețea, el salvează lista de noduri la care s-a conectat cu succes pentru a o folosi data viitoare când se va conecta la rețea.

Având în vedere ca fiecare nod din rețea este un simplu utilizator, starea rețelei nu va fi niciodată stabila, în orice moment înregistrându-se conectări și deconectări de la rețea. în medie la un moment dat în rețea sunt prezente cel puțin 100000 de noduri. Adevăratul beneficiu al acestei descentralizări a rețelei Gnutella consta în faptul ca va fi foarte greu să fie oprita sau interzisa. Spre deosebire de Napster unde întreaga rețea se baza pe existenta unui server central, Gnutella nu poate fi oprita prin oprirea unui nod din rețea. Atât timp cât vor există cel puțin 2 utilizatori în rețea, Gnutella va continua să existe.

Modelul de funcționare al rețelelor de tip Napster este prezentat în Figura 2 [2]:

Figura 2.2 : Model de funcționare Napster

Modelul de funcționare al rețelelor de tip Gnutella este prezentat în Figura 3 [2]:

Figura 2.3 : Model de funcționare Gnutella

2.2.2. Caracteristicile și extensiile protocolului Gnutella

Prima versiunea a protocolului Gnutella, versiunea 0.4, suporta 5 tipuri de pachete folosite în comunicație :

Ping : când se descoperă un ‘host’ nou în rețea

Pong : răspuns la ping

Query : când se generează o interogare pentru a se căuta un anumit fișier

Query Hit : răspuns la interogare (query)

Push : cerere de ‘download’ (pentru nodurile care sunt după un firewall)

Aceste tipuri de pachete se concentrează în special asupra căutărilor în rețeaua Gnutella, pentru transportul de fișiere fiind folosite protocoale HTTP prestabilite.

Dezvoltarea rețelei și protocolului Gnutella este condusa de GDF (Gnutella Developer Forum). S-au dezvoltat până acum și se dezvolta în continuare multe extensii ale acestui protocol de către diferiți producători de software, extensii cum ar fi : rutarea inteligenta a interogărilor, folosirea de algoritmi de hashing pentru indexarea informațiilor cum ar fi SHA (Secure Hash Algorithm) și suportul pentru transferul simultan, pe bucăți, al unui fișier de la mai multe surse (multi-source downloading).

Fundamentare Teoretică

3.1. O Schemă Eficientă pentru Procesarea Interogărilor în Rețelele P2P

Paradigma rețelelor P2P(Peer-to-Peer) a apărut ca un mod nou pentru interconectarea sistemelor individuale. Un dezavantaj al rețelelor de acest tip, care încearcă evitarea folosirii unui server pentru centralizarea indecșilor, este lipsa robusteții o data cu creșterea numărului de noduri din rețea. în continuare sunt prezentate câteva modificări ale paradigmei rețelelor distribuite, care permit existenta unui index la nivelul unui nod și rutarea interogărilor bazata pe acest index. Aceasta modificare are ca rezultat evitarea căutărilor exponențiale în sistemele distribuite și oferă totodată și o potențiala soluție pentru scalarea interogărilor în rețelele peer-to-peer . Un model de rețea P2P, spre exemplu Gnutella, este prezentat în Figura 3.1 :

Figura 3.1 : Model de rețea P2P

3.1.1. Introducere în Procesarea Interogărilor în Rețelele Distribuite

Starea actuala în procesarea interogărilor în rețelele distribuite este ca fiecare nod din rețeaua respectiva să proceseze fiecare interogare. La prima vedere, aceasta caracteristica ar părea să fie o trăsătura definitorie a unei rețele cu adevărat distribuita. Existenta unui server central care să păstreze indecșii ar pune în pericol trăsătura de distribuitate adevărata a rețelei. Datorita faptului ca fiecare nod cunoaște doar conținutul datelor sale, singura modalitate de a afla ceva într-o rețea cu adevărat distribuita este de a interoga fiecare nod din respectiva rețea.

Într-o rețea de tip arbore(vezi Figura 3.2) fiecare nod se conectează pe arbore în “sus ” la un host părinte și pe arbore în “jos” la copiii săi. Mesajele de la un nod se trimit la părinte și la toți copiii acestuia, astfel interogarea fiind transmisa la toate nodurile din rețea.

Figura 3.2: Rețea de tip arbore

În Figura 3.3 este prezentat un proces normal de interogare. Un nod care generează o interogare transmite aceasta interogare la nodul părinte. Acesta la rândul sau trimite aceasta interogare la nodul părinte și la toți fii, cu excepția fiului de la care a primit interogarea respectiva. Acest proces continua recursiv până când toate nodurile din rețea au primit cate o copie a acelei interogări.

Figura 3.3: Diagrama de transmitere a unei interogări

Se observă ca factorul de încărcare al comunicației rețelei crește o data cu creșterea populației din rețea. Se poate observă de asemenea ca există o limita a numărului de interogări care pot fi procesate de către un nod din rețeaua distribuita. Dacă o interogare necesita un număr de Q bytes și cea mai înceată legătura are o lățime de banda B bytes/sec, acel nod poate să proceseze dor B/Q interogări pe secunda. Dacă un nod din arbore nu poate procesa o interogare el trunchiază efectiv arborele, ceea ce duce la fragmentarea rețelei.

Aceasta este o limitare fundamentala în rețelele peer-to-peer, ce nu poate fi eliminata nici prin algoritmi nici prin protocoale mai “deștepte”. Dacă fiecare mașina este responsabila pentru procesarea fiecărei interogări, paradigma rețelei este obligată să suporte această limitare, indiferent de lățimea de bandă disponibilă.

3.1.2. Paradigma Rutării

Când rețelele locale de calculatoare au devenit populare și în special, 10Base2 Ethernet (coax), lățimea de banda de 10Mbps a furnizat un mediu de comunicare foarte propice pentru sistemele de la acea vreme. Dar o data cu dezvoltarea rețelelor de calculatoare Ethernet, lățimea de banda partajata în rețea a devenit din ce în ce mai limitata. Doar un singur calculator putea emite în rețea la un moment dat, iar restul calculatoarelor din rețea trebuind să “asculte”, de obicei existând doar un singur calculator care “asculta”. Soluția la aceasta limitare de performanta, impusa de partajarea lățimii de banda, a fost segmentarea rețelei folosind router-ele.

Router-ele, în teorie, nu sunt sisteme foarte complicate. Misiunea lor este de a decide în ce direcție (dacă există) să trimită informația primita. Folosind o tabela de rutare, sistemul trimite pachetele spre segmentul potrivit din rețea și nu trimite spre segmentele din rețea unde știe ca nu va găsi nici un destinatar. în special datorita router-elor de înaltă performanta, rețelele locale de calculatoare(LANs) și Internetul în general, au ajuns la nivelul de eficiența și performanta din zilele noastre. Dacă fiecare calculator din Internet ar trebui să “asculte” de fiecare data când cineva trimite cate un email sau cineva download-eaza o pagina web, acel sistem ar fi complet inutilizabil. Astfel cheia succesului în rețelele peer-to-peer este : o rețea în care fiecare sistem “asculta” este condamnat să devină inutilizabil. Esențial în aceasta problema este cum să se ruteze interogările pentru ca nu toate sistemele dintr-o rețea distribuita să asculte fiecare interogare.

Considerând ruta optima pe care o interogare o poate lua, interogarea respectiva ar trebui să fie procesată doar de nodurile care duc la informația dorita. O ruta optima a unei interogări este prezentată în Figura 3.4. Se poate observă ca interogarea este transmisa în “sus” pe arbore, iar apoi este transmisa în “jos” doar spre acele noduri care conțin informația dorita. Numărul total al interogărilor transmise, dar și factorul de încărcare al rețelei, este proporțional cu numărul de noduri care conțin informația dorită și nu cu numărul total de noduri din rețea.

Figura 3.4: Diagrama unei interogări rutate optim

Prin rutarea interogărilor se realizează o diminuare relevanta a comunicațiilor între noduri, putându-se preveni totodată și problemele fragmentare ale rețelei, dar și de congestionare a traficului, probleme la care sunt expuse în special nodurile cu lățimea de banda redusa.

Pentru ca o interogare să fie optim rutată fiecare nod din rețea trebuie să cunoască conținutul complet a-l nodurilor vecine. Colectarea, actualizarea, și căutarea informațiilor de la toate nodurile vecine sunt operații costisitoare care în final duc la creșterea semnificativă a factorului de încărcare al nodurilor din rețea. Natura dinamica a rețelei și datele pe care le conține face aceasta abordare aproape nerealista. Mergând mai departe, dacă fiecare nod ar avea informații complete despre toate nodurile, atunci orice nod ar putea să rezolve singur interogarea. Dar scopul declarat e de a ruta interogarea nu de a o rezolva exact. Pentru aceasta nu este necesară o procesare completa a interogării la nivelul unui nod proxy. Este necesar doar a nu se ruta interogările irelevante pentru un anumit nod sau anumite părți ale rețelei. Problema care apare în aceasta situație este cum putem să știm dacă interogarea este irelevantă pentru un nod sau pentru o parte a rețelei fără a verifica conținutul acestora.

Nu se poate ști precis dacă o interogare este relevanta pentru un nod sau pentru o anumita parte a rețelei fără informații complete, dar e posibil procesarea aproximativa a interogării folosind un set redus de informații și rutarea interogării pe baza acelor aproximări. Un test cu o procesare aproximativa a interogării poate duce la rezultate false, ceea ce va cauza rutarea interogărilor spre noduri sau spre părți ale rețelei care nu conțin informații relevante. în concluzie, procesarea aproximativa a interogărilor duce la o rutare sub-optimala, dar atât timp cât numărul rezultatelor false este relativ mic vom avea majoritatea interogărilor rutate pe o cale optima, iar majoritatea nodurilor care în final primesc interogările conțin informații relevante. în plus se poate proiecta ca aceasta procesare aproximativa a interogărilor să garanteze ca nu vor apărea rezultate false, în consecința fidelitatea interogării rămânând intacta.

3.1.3. Scheme de Indexare și Procesarea Aproximativa a Interogărilor

Există multa literatura de specialitate în care este tratata problema accelerării proceselor de căutare, dintre care amintim cartea lui Donald Knuth: The Art of Computer Programming, Volume 3 [1], dar din păcate majoritatea algoritmilor prezentați în aceste cărți au fost elaborați pentru bazele de date centralizate. în cazul rețelelor peer-to-peer bazele de date care trebuie interogate sunt distribuite și cu o caracteristica dinamica foarte ridicata. Cu toate acestea, sunt multe caracteristici ale acestor algoritmi care se pot împrumuta pentru a construi o schema de căutare valabila pentru bazele de date distribuite.

În cazul acestei probleme soluția este construirea unui index cât mai adecvat pentru a permite interogări foarte rapide pe bazele de date distribuite. Acest index trebuie să fie o reprezentare cât mai compresată a datelor din baza de date, căutarea folosind acest index reușind a fi mult mai eficiența decât căutarea pe o întreaga baza de date. Un exemplu de index de acest tip este o funcție de hashing (distribuție) care să reducă cuvintele cheie într-un set restrâns de numere întregi, acest index fiind format dintr-o lista de numere întregi. Folosind acest index, căutările pe o baza de date vor fi mult mai eficiente, ne mai fiind nevoie să se parcurgă tot conținutul bazei de date, ci doar căutându-se indexul respectiv.

În continuare va fi prezentat un exemplu simplu al folosirii funcției de hashing. Consideram ca baza noastră de date conține următorul fragment:

When în the course of human events, it becomes necessary for one people to dissolve the political bands…

Schema de indexare nu va lua în considerare cuvintele care pot apărea frecvent într-o fraza și fără o încărcare semantica deosebita cum ar fi : when, in, becomes, the, it, for, to, rămânând doar cuvintele cheie: course, human, events, necessary, one, people, dissolve, political, bands. La cuvintele indexate nu se va tine cont dacă respectivul cuvânt este scris cu litere mari sau cu litere mici, aceste cuvinte fiind indexate cu aceeași valoare. Spre exemplu :

one = ONE = One

Presupunând ca avem o funcție de hashing care asociază fiecărui cuvânt cheie o valoare între 0 și 99999, putem să asamblam o parte din indexul bazei de date corespunzător fragmentului precedent.

course = 02123

human = 10932

events = 34394

necessary = 50234

one = 68023

people = 43020

dissolve = 10593

political = 42330

bands = 92399

Folosind aceasta schemă de indexare, pentru căutarea unui cuvânt nu mai este necesară parcurgerea întregii baze de date, putându-se căuta în indexul bazei de date după valoarea de hashing corespunzătoare respectivului cuvânt. în cazul exemplului de mai sus putem găsi cuvântul political căutând în index după valoarea 42330. Totodată, căutând cuvântul nation în index după valoarea să 14092 vom obține un rezultat negativ, cuvântul nefiind în baza de date.

Schema de indexare bazata pe hashing este de obicei aplicata pentru porțiuni individuale din baza de date. Am putea construi un index per pagina ori per paragraf pentru documente foarte lungi și astfel am putea căuta foarte rapid o porțiune din document și identifica ce porțiune conține datele căutate sau să ignorăm porțiunile care nu conțin date relevante. Folosind aceasta abordare se poate construi un mecanism pentru căutarea în baze de date distribuite. Funcția de hashing prezentată mai sus putând fi aplicata pentru metadata din datele partajate de fiecare nod dintr-o rețea peer-to-peer.

La construirea indexului cu funcții de hashing este necesar a se examina dacă nu există coliziuni, adică 2 sau mai multe cuvinte cheie care au aceeași valoare. Dacă nu apare nici o coliziune atunci putem spune ca avem un hash perfect. Dacă totuși apar coliziuni trebuie implementat un mecanism pentru evitarea, pe cât posibil, a acestor coliziuni. Coliziunile apar în special în cazul când se alege un univers al cheilor prea restrâns. Pentru exemplu de mai sus dacă am alege o funcție de hash care să asocieze cuvintelor cheie numere din intervalul 0 – 7 (pe 3 bits), indexul ar putea arata astfel :

course = 4

human = 7

events = 0

necessary = 1

one = 5

people = 7

dissolve = 6

political = 3

bands = 5

Având în vedere ca avem 9 cuvinte cheie și doar 8 stări posibile ale indexului, vom avea cel puțin o coliziune. în cazul de fata avem 2 coliziuni, pentru valorile 5 și 7, valoarea 2 neapărând deloc. Folosind indexul în acest caz, la unele interogări putem obține rezultate eronate, deoarece după valorile indexului următoarele cuvinte cheie ar fi egale :

human == people

one == bands

Dacă se alege o funcție de hashing optima, distribuția rezultatelor este foarte aleatoare pe universul hashingului, în general existând mult mai puține coliziuni pe un univers al hashingului mai larg. Spre exemplu, dacă s-ar dubla dimensiunea universului de hashing, numărul coliziunilor ar scădea în medie la jumătate.

Din păcate nu se prea pot testa coliziunile și nici nu se poate furniza o rezoluție a coliziunilor, care să fie și eficiența în același timp, în special datorita caracterului distribuit și dinamic al datelor. Deoarece nu putem rezolva o interogare exact, aceasta metoda trebuie tratata ca o metoda aproximativa. Însă, foarte important este ca prin creșterea dimensiunii hashingului putem avea un mecanism de creștere a acurateți de aproximare.

Din fericire, rutarea interogărilor nu necesita acuratețe absolută. Avem nevoie să știm doar dacă un nod, sau o parte a rețelei, ar putea(în principiu) satisface o interogare, nu și dacă o satisface pozitiv. Se va folosi schema de indexare aproximativa pentru a alege din populația de noduri și a ruta interogarea. Important este ca aceasta indexare aproximativa nu va afecta fidelitatea interogării: nodurile care primesc aceasta interogare vor decide dacă conțin sau nu date pentru a satisface respectiva interogare. Acest mecanism de procesare aproximativa a interogărilor evita doar transmiterea interogărilor spre acele noduri care nu vor putea satisface interogarea.

3.1.4. Rutarea Interogărilor bazate pe Conținut (Content based Query Routing)

Funcția de hashing aplicata cuvintelor cheie din metadate ne furnizează o metoda de a determina dacă un nod conține sau nu informații relevante pentru o anumita interogare. Aceasta informație este foarte utila deoarece dacă fiecare host al vreunui nod ar avea aceasta informație el ar putea să decidă dacă să trimită sau nu o anumita interogare spre nodul respectiv. Metoda aceasta ne permite să tratam doar ultimul hop din rețea, permițând rutarea interogărilor doar la baza arborelui.

Abordarea precedenta este folositoare dar nu reprezintă un pas foarte mare înainte. Din acest motiv vom folosi o masca de biți (bitmask) pentru reprezentarea indexului construit prin aplicarea funcției de hashing. Dacă vom avea intrări în hash, am putea reprezenta semnătura unui nod cu o masca de biți compusa din biți. Un bit va fi setat sau nu în funcție de prezenta sau nu în nodul respectiv a acelei intrări din hash. Folosind aceasta metoda vom avea 256000 de intrări în hash și vom avea nevoie doar de 32 KiloBytes pentru păstrarea liniara a acestuia. Folosind codificări speciale dimensiunea acestuia s-ar putea reduce semnificativ.

Semnătura fiecărui nod din rețea trebuie transmisa spre host-ul acestuia, iar fiecare host trebuie să retina fiecare semnătura ale nodurilor fiu. După aceea fiecare nod cu masca de biți din indexul propriu face un ORI logic cu toate măștile de biți ale indecșilor de la toate nodurile fiu. Aceasta masca de biți agregata furnizează o semnătura pentru toate datele din respectiva ramura de rețea. La rândul sau nodul host va transmite aceasta masca de biți agregata spre hostul sau, aceasta abordare aplicându-se recursiv pe tot arborele rețelei.

Folosind aceste informații interogările pot fi rutate la fiecare nivel din rețea. Dacă un nod sau o ramura a rețelei nu conține toate cuvintele cheie dintr-o anumita interogare, acea interogare nu va fi rutată prin nodul respectiv. Aceasta abordare este perfect scalabilă, agregarea măștilor de biți continuând în sus pe arborele rețelei. O caracteristica importanta a acestei abordări este ca masca de biți nu crește, ea ne fiind mai mare de 32 KiloBytes. Aceasta limitare a dimensiuni măștii de biți previne ca nodurile din nivelele superioare ale arborelui rețelei să fie supra încărcate cu informații de index.

În Figura 3.5 este prezentată rutarea unei interogări într-o rețea de tip arbore. Un anumit nod din rețea creează o interogare, aceasta interogare fiind trimisa în sus pe arbore la nodul host. Apoi interogarea este testata cu fiecare mască de biți a nodurilor și ramurilor din respectiva rețea. Dacă aceasta testare conduce la un rezultat pozitiv atunci interogarea este rutată prin nodul respectiv, iar dacă nu va avea rezultat pozitiv ea nu va fi rutată prin nodul respectiv. Nodul care primește interogarea la rândul sau trimite interogarea spre nodul părinte, iar apoi testează interogarea cu măștile sale de biți de la nodurile, ramurile rețelei, care sunt conectate la el, trimițând mai apoi interogarea în funcție de rezultatul testări spre nodurile respective. în medie doar o mica parte a nodurilor vor trece acest test, doar acele noduri primind interogare care potențial ar putea rezolva acea interogare.

Figura 3.5: Diagrama transmiterii unei interogări rutată aproximativ

În cazul metodei, rutarea interogărilor bazate pe conținut, prin folosirea măștilor de biți ca indecși aproximativi pentru reprezentarea datelor unui nod, nodurile din rețea pot lua decizii inteligente în legătura cu rutarea și transmiterea interogărilor. Aceasta este o metoda mult mai eficiența decât transmiterea interogării în broadcast la fiecare nod. Printr-o implementare adecvata și integrata în protocoalele de comunicație din rețelele peer-to-peer, aceasta metoda ar putea elimina problema scalarii care apare în acest tip de rețele.

Metoda rutării interogărilor bazate pe conținut, are 3 componente cheie. Prima componente este aproximarea conținutului datelor din fiecare nod. A doua este agregarea măștilor de biți și distribuirea acestei măști de biți agregate la nodul părinte. Ultima componenta este chiar schema de rutare.

3.1.5. Evaluarea Aproximărilor unei Interogări

Folosind metoda prezentată mai sus este imposibil de a obține rezultate negative care să fie false. Dacă unul sau mai multe cuvinte cheie din interogare nu există în indexul unui nod sau al unei ramuri a rețelei, atunci respectivul nod, ramura a rețelei, nu poate satisface interogarea. în schimb pot apărea 2 tipuri de rezultate pozitive false : datorita coliziunilor din universul de hashing și din cauza agregării cuvintelor cheie. Aceste rezultate, datorate metodei de căutare aproximativa, vor duce la o rutare greșită a interogării.

Pentru diminuarea probabilității de apariție a coliziunilor trebuie ca universul de hashing să fie cât mai mare. în acest caz trebuie făcut un compromis între dimensiunea universului de hashing, care cu cât ar fi mai mare ar determina indexul din fiecare nod să fie mai mare. Astfel, dacă s-ar alege să se mapeze cuvintele cheie într-un interval de numere între 0 și (aproximativ 4 miliarde), probabilitatea de apariție a coliziunilor între cuvintele cheie ar fi foarte redusa în acest caz(în limba engleza sunt doar 300000 de cuvinte), dar masca de biți, în acest caz, ar fi de peste 500 MBs. Aceasta dimensiune a măștii de biți ar fi mult prea mare pentru o căutare eficiența. Din acest motiv este nevoie ca spațiul de index să fie limitat între și intrări, care ar duce la niște măști de biți cuprinse între 32 KB și 128 KB. Acest lucru ne conduce la acceptarea unor coliziuni și ale unor rutări greșite ca făcând parte din algoritm. în cazul rutărilor greșite, acestea se vor perpetua până se ajunge la nodul care conține coliziunea de cuvinte cheie, acest fapt având urmări negative asupra comportamentului rețelei, dar atât timp cât ele sunt relativ rare, ar putea fi trecute cu vederea.

În figura 3.6 este prezentată diagrama unei interogări rutate greșit cauzata de coliziunea cuvintelor cheie din respectiva interogare. Acesta interogare conține cuvântul cheie nation care are indexul de hash de 340312. Nodul părinte rutează corect aceasta interogare înspre ramura stânga a arborelui rețelei, interogarea fiind satisfăcută, dar o rutare greșită apare când interogarea este trimisa și înspre ramura dreapta a rețelei. Acel nod spre care s-a rutat greșit interogarea conține într-adevăr indexul 340312, dar aceasta valoare este corespunzătoare cuvântului wildflower. în cele din urmă acest nod nu poate satisface aceasta interogare, cu toate ca conține respectiva valoare de index.

Figura 3.6: Exemplu de interogare rutată greșit, cauzată de coliziunea indexului

Al doilea tip de erori la rutare provine din agregarea unor măști de biți diferite. Pentru căutările care conțin mai mult de un cuvânt cheie, este posibil ca mai multe noduri dintr-o anumita ramura a rețelei să conțină anumite cuvinte din acea interogare, dar nici un nod să nu conțină toate cuvintele. Acest tip de eroare de rutare este mult mai des întâlnită și apare în special în ramuri ale rețelei care conțin foarte multe noduri. Măștile de biți ale nodurilor din nivelele superioare ale arborelui rețelei, pot fi foarte "complete", ceea ce poate duce la interogări rutate greșit. Interogările de acest tip rutate greșit vor fi rutate doar pe câteva nivelele ale arborelui, rutarea lor oprindu-se când ramurile de rețea nu vor mai conține toate acele cuvinte cheie.

Figura 3.7 ilustrează o interogare rutată greșit, cauzata de agregarea cuvintelor cheie. Interogarea conține 2 cuvinte cheie : nation și prudent. Această interogare este rutată corect înspre partea stânga a subarborelui rețelei până ajunge la un nod care conține ambele cuvinte cheie. Interogarea, este rutată incorect, însă, înspre subarborele drept al rețelei, deoarece masca de biți agregata conține indicii pentru ambele cuvinte cheie, fiecare cuvânt cheie fiind prezent în alt nod al subarborelui rețelei. Interogarea avansează în rețea doar încă un nivel până când se produce separarea celor 2 cuvinte cheie. Cuvântul cheie nation este conținut în subarborele drept al rețelei, pe când cuvântul cheie prudent este conținut în subarborele stâng al rețelei, din acest motiv interogarea nefiind rutată mai departe.

Figura 3.7 : Exemplu de interogare rutată greșit, cauzata de agregarea cuvintelor cheie

Din păcate nu este nici o cale pentru a menține, în același timp, o dimensiune fixa a măștii de biți și a evita coliziunile de tip agregare. Orice alta tehnica, pe care am folosi-o, ar cauza creșterea măștii de biți o data cu avansarea acesteia prin arbore. S-ar putea folosi în loc de ORI-ul logic o metoda prin care să se păstreze toate măștile de biți, dar transmiterea de informații complete despre fiecare nod al rețelei ar duce la un trafic excesiv, în special pentru nodurile din partea superioara a arborelui rețelei.

Decât să se păstreze toate informațiile despre un nod, mai bine s-ar pune în valoare natura aleatoare a funcției de hashing pentru păstrarea de informații corelate despre fiecare nod. Pentru un spațiu de index mare, un anumit nod ar produce o semnătura de masca de biți foarte diversificata. Este foarte probabil ca pe un anumit nod să fie prezente doar câteva mii de cuvinte. Algoritmul de creare a semnăturilor pentru fiecare nod ar putea fi modificat, astfel încât după aplicarea funcției de hashing să se efectueze o rotație a biților (bit rotation). Astfel ca masca de biți, la final, va fi rotita cu un număr fix de biți, număr ce identifica unic nodul respectiv, fiind cheia nodului respectiv. Aceasta cheie poate fi generata aleator de către fiecare nod. Nu ar fi necesar ca aceasta cheie să fie asignată de către nodul părinte, deoarece universul cheilor este suficient de mare pentru ca cheile generate aleator să nu se intersecteze aproape niciodată. Aceasta cheie trebuie să aibă aceeași dimensiune cu numărul de biți din masca de biți. Cheia va fi transmisa spre nodul părinte o data cu masca de biți. Folosind aceasta metoda, chiar dacă 2 noduri conțin același cuvânt cheie, codificarea acestui cuvânt cheie va fi diferita pe cele 2 noduri, putând să codifice diferiți biți în masca de biți agregata.

Fiecare nod va colecta masca de biți de la toate nodurile care sunt conectate la el, apoi își va genera propria masca de biți, iar apoi o va roti folosind propria cheie. Aceste măști de biți separate pot fi combinate folosind ORI-ul logic, iar cheia sa împreună cu lista cheilor de la nodurile fiu vor fi trimise mai departe la următorul nivel. Prin folosirea acestei metode traficul în rețea va crește puțin, datorita faptului ca toate cheile unice trebuie propagate prin rețea, dar dimensiunea unei chei va fi cuprinsa între și și atunci va fi nevoie pentru codarea cheii de doar 2.25 până la 2.5 bytes. Chiar și pentru o rețea în care sunt prezente 40000 de calculatoare, semnătura datelor la nivelul superior al arborelui rețelei va fi de doar 10 KB.

Nodul părinte va trebuie să păstreze masca de biți și cheia pentru fiecare nod din subarborele sau. Când sosește o interogare, mai întâi trebuie aplicata funcția normala de hashing pentru a identifica indexul nerotit, iar apoi să roteasca rezultatul pentru fiecare nod în parte, folosind cheia proprie. Aceasta metoda, datorita rotației măștii de biți din fiecare nod, duce la creșterea efortului computațional pentru a determina dacă o interogare va fi satisfăcută pentru un anumit subarbore al rețelei.

Prin intermediul schemei de hashing acest algoritm determina păstrarea informației care se suprapune în nodurile individuale. Pentru un anumit nod masca de biți a hashingului va fi foarte dispersata, fiind puțin probabil să existe 2 noduri cu aceeași cheie. Este foarte probabil ca mai multe noduri dintr-un subarbore al rețelei să conțină aceleași cuvinte cheie, dar datorita faptului ca fiecare tabel de index este rotit, aceste cuvinte cheie comune nu se vor suprapune ci vor ocupa poziții diferite în indexul respectiv. Masca de biți va fi completata mult mai rapid, deoarece este nevoie să se păstreze informațiile suprapuse. Erorile de rutare pot apărea și în acest caz dar sunt mult mai subtile, iar în principiu erorile datorita coliziunii indexului și agregării cuvintelor cheie s-au contopit. Folosind aceasta abordare este posibil a menține o dimensiune aproape constanta a semnăturii datelor și totodată a elimina coliziunile datorate agregării cuvintelor cheie. Se poate reduce probabilitatea de apariție a tuturor tipurilor de coliziuni prin creșterea dimensiunii universului de hash.

În cazul acestei abordări trebuie tratata cu atenție problema eliminării cuvintelor comune înaintea aplicării funcției de hashing. Cuvinte comune ca și : and, the, în … vor apărea de fapt în fiecare nod al rețelei. Datorita rotirii biților, fiecare dintre aceste cuvinte comune vor ocupa poziții diferite în indexul fiecărui nod, dar vor popula măștile de biți agregate foarte repede. Presupunând ca avem 50 de cuvinte comune și o rețea de 100 de noduri, se vor pierde aproximativ 5000 de locații sau cam 2% dintr-o masca de biți de dimensiune . Masca de biți trebuie aleasa destul de larga pentru a putea include și informațiile care se suprapun, datorita existentei unor cuvinte cheie pe mai multe noduri. în cazul acestei abordări coliziunile cuvintelor-cheie sunt proporționale cu numărul nodurilor din rețea și de aici nevoia de o masca de biți din ce în ce mai mare. Măștile de biți din nivelele superioare ale arborelui rețelei vor fi din ce în ce mai completate, datorita includerii informației rotite în fiecare nod al rețelei. Acest lucru va scădea puțin eficiența schemei de codificare care ar trebui să producă rezultate cât mai dispersate în spațiul de hashing.

Nu este chiar evident ca complexitatea sporita al celei de a doua abordări este justificata și va produce rezultate mai bune decât prima abordare. Este foarte posibil ca coliziunile de index să nu fie foarte frecvente, iar erorile de agregare ale cuvintelor cheie sa nu reprezinte o încărcare smnificativa a rețelei, deoarece ele nu se propaga de obicei prea mult în rețea. Este, oarecum, imposibil a se testa aceste 2 metode fără a folosi date reale. Se recomanda aplicarea metodei mai complicate doar în cazurile în care implementarea mai simpla se dovedește a fi inacceptabila.

3.1.6. Problemele Implementării și Modificările Protocolului

Problema procesării interogărilor într-o baza de date distribuita, este deosebit de complexa, astfel ca prin introducerea măștilor de biți, bazate pe funcții de hashing, s-a introdus cate o semnătura pentru datele fiecărui nod. Aceasta semnătura se propaga prin nodurile rețelei, folosindu-se pentru a se decide dacă un nod să primească sau nu o anumita interogare. Mai mult, aceste măști de biți pot fi agregate pentru a fi trimise mai departe spre nodurile părinte, care pot decide dacă să ruteze sau nu o anumita interogare prin acea ramura a rețelei. în continuare, trebuie a se dezvolta un plan general de implementare, care să permită rețelelor peer-to-peer să implementeze efectiv aceasta abordare.

Este necesar ca toți clienții unei rețele peer-to-peer să știe cum să își indexeze propriile date, dar și să conțină un protocol prin care să se conecteze la nodurile părinte. Implementarea algoritmului Rutarea Interogărilor bazate pe Conținut (Content based Query Routing) necesita selectarea unei scheme comune de hashing, un protocol de "handshake" care să faciliteze transmiterea măștii de biți spre nodurile părinte, un plan bine pus la punct, în legătura cu actualizarea și ștergerea măștilor de biți și o codificare corespunzătoare pentru a reduce traficul de comunicație între un nod și părintele sau.

La implementarea acestui algoritm o atenție mare necesita selecția funcție de hashing. Cartea lui Donald Knuth oferă ceva recomandări în alegerea unei funcții de hashing. Având în vedere ca universul cuvintelor cheie nu poate fi cunoscut în totalitate, singurele cerințe ale unei funcții de hashing sunt :

Trebuie să suporte string-uri de lungime arbitrara.

Trebuie să utilizeze un index de dimensiune arbitrara.

Trebuie să fie relativ rapida și complet independenta de platforma.

Pentru a face implementarea algoritmului "Rutarea Interogărilor bazate pe Conținut (Content based Query Routing)" complet compatibila cu implementările deja existente, transmiterea măștilor de biți ar trebui să fie opționale. Acest lucru ar înseamnă ca masca de biți standard pentru toate implementările care nu suporta algoritmul menționat mai sus, ar trebui să fie completa, iar masca de biți trimisa la nodul părinte să fie de asemenea completa. Aceasta ar putea fi o bariera în acceptarea acestui protocol nou, deoarece un singur client "mai vechi" care s-ar conecta la un nod, ar umple masca de biți pentru tot subarborele rețelei, ceea ce ar face algoritmul algoritmului "Rutarea Interogărilor bazate pe Conținut " inutilizabil. Pentru a preveni aceasta stare, ar trebui ca fiecare nod care primește o masca de biți de la un client "mai vechi" să golească aceasta masca de biți.

Protocolul de "handshake" trebuie să ii permită clientului să se conecteze relativ rapid la rețea, iar după conectare să trimită masca de biți. Până când masca de biți nu a fost trimisa respectivul client va funcționa cu o masca de biți null-a. După ce masca de biți a fost construita și transmisa nodului părinte, iar acesta va construi masca de biți agregata și la rândul sau o va transmite nodului părinte. Pentru a menține procesul de actualizare acceptabil și pentru a nu crea trafic excesiv în rețea ar trebui să fie un protocol de tipul menținerea conexiunii pentru câteva minute (several minute keep-alive protocol). Spre exemplu ar putea să fie un protocol cu menținerea conexiunii de 10 minute, iar dacă un nod nu se înregistrează la fiecare 12 minute va fi deconectat. Pentru implementare se recomanda următoarea abordare :

Când un nod nou se conectează la un anumit nod din rețea, noul nod ar trebui să consulte acest timp de menținere a conexiunii. Dacă sunt mai mult de 5 minute de la ultima transmitere a măștii de biți, el ar trebui să construiască o noua masca de biți agregata și să o trimită spre nodul părinte. Nodul părinte va răspunde, setând următoarea limita de timp pentru menținerea conexiunii, iar nodul nou își va reseta timerul.

Dacă sunt mai puțin de 5 minute de la ultima transmitere de informații către nodul părinte, transmiterea de informații va aștepta până la următoarea transmitere prevăzuta.

Dacă nu s-a schimbat nimic, nodul trebuie să trimită doar mesajul "No Change", părintelui sau.

Fiecare nod va încerca să sincronizeze actualizările primite de la nodurile fii, acestea să se petreacă cu 1 – 2 minute mai devreme decât timpul planificat. Acest fapt va preveni întârzierile propagării datelor din nodurile conectate recent în rețea. Sincronizările de informații pot să se materializeze în modificarea timpului de menținere a conexiunii. Când un nod răspunde altui nod fiu, poate să ajusteze următoarea limita de timp pentru menținerea conexiunii.

Aceasta abordare previne traficul excesiv în rețea, în special în nodurile foarte solicitate, și va minimiza timpul necesar pentru ca un nod să fie "online" și să fie vizibil în restul rețelei.

Pentru a eficientiza transferul măștilor de biți în rețea se recomanda transferul acestora codificate. Aceasta codificare ar putea duce la o reprezentare mult mai mica a măștilor de biți și să reducă datele de transferat în rețea de la 10 KB, ori 100 KB la doar câțiva KB. Pentru a se menține compatibilitatea cu implementările anterioare se recomanda folosirea ambelor abordări, adică măștile de biți să poată fi transmise atât codificat cât și necodificat.

Căutarea într-o Federație de Depozite de Arhive

O federație de Depozite de Arhive (Archival Repositories) trebuie nu numai să păstreze informația pentru perioade lungi de timp ci să ofere acces la aceasta informație. Scopul declarat al acestei abordări este găsirea eficiența a documentelor căutate aflate într-o rețea distribuita.

Există 3 categorii de mecanisme de căutare : mecanisme fără index, mecanisme cu noduri specializate în indexarea informațiilor (căutare centralizata) și mecanisme cu indecși care sunt păstrați în fiecare nod (căutare distribuita). Spre exemplu într-o federație de noduri puternic descentralizata în care nodurile nu au index propriu, interogările sunt propagate de la un nod la altul, până când au fost găsite respectivele documente. Acest mecanism de căutare flood-eaza rețeaua, ori un subset al acesteia, în speranța de a găsi documentele căutate. în pofida faptului ca aceasta abordare este simpla și robusta, are dezavantajul costului enorm al căutării distribuite în rețea de fiecare data când o interogare este generata.

În cazul sistemelor cu căutare centralizata(spre exemplu Napster), acestea folosesc noduri specializate care mențin un index central al documentelor disponibile în federația depozitelor de arhive. Pentru a găsi un document, utilizatorul interoghează un nod care deține acest index pentru a identifica nodurile care conțin respectivul document. Acești indecși centrali pot fi construiți cu cooperarea nodurilor, de exemplu nodurile din rețeaua Napster furnizează o lista cu fișierele disponibile la conectarea în rețea, sau interogând rețeaua P2P (peer-to-peer), ca și într-un motor de căutare pe web. Marele avantaj al unui mecanism de căutare centralizată este eficiența, deoarece un singur mesaj este necesar pentru a satisface o interogare. Dezavantajele acestui tip de rețea sunt : vulnerabilitatea la atacuri ( sistemele care conțin indexul pot fi distruse de hackeri sau oprite de către o decizie judecătoreasca) și dificultatea de a actualiza indecșii.

Mecanismul cu indecși distribuiți, are la baza principiul menținerii cate unui index în fiecare sistem din rețeaua distribuita. Acești indecși distribuiți, trebuie să fie relativi mici, din acest motiv folosindu-se Indecșii de Rutare (Routing Indices), care oferă o direcție în care un document poate fi găsit și nu locația exacta a respectivului document. în Figura 3.8 sunt prezentate 4 noduri : A, B, C și D care sunt conectate prin linii solide. Documentul cu conținutul x se afla în nodul C, dar indecși de rutare din nodul A indica spre nodul B (săgeata punctata), în loc să indice direct spre nodul C. Folosind ‘rutele’ în locul destinațiilor, dimensiunea indexului fiind astfel proporționala cu numărul vecinilor, nu cu numărul documentelor. Dimensiunea indecșilor de rutare poate fi redusa și mai mult prin folosirea indecșilor aproximativi, rolul acestor indecși fiind acela de a sugera locația unui document, nu de a da un răspuns fix în legătura cu locația acestuia. Spre exemplu presupunând ca în tabela indecșilor de rutare pentru nodul A avem intrări pentru documentele cu conținutul ‘x’, ‘y’ ori ‘z’, la o cerere cu conținutul ‘x’ se va produce o sugestie corecta, dar pentru conținutul ‘y’ sau ‘z’ se va produce o sugestie incorecta.

Figura 3.8 : Indecși de Rutare

Aceste tehnici pot fi aplicate nu numai unei federații de depozite de arhive, ci și unor sisteme peer-to-peer (P2P) mai generale ; nodurile distribuite din aceste rețele schimbând informațiile direct de la unul la celalalt. Aceste rețele reprezintă o diversitate incredibila de informații, permițând utilizatorilor să schimbe între ei : documente (Freenet [13]), muzica (Napster [18], Gnutella [19]) și cicluri computaționale (Seti-at-home [20]). Având în vedere ca federațiile de depozite de arhive sunt un caz special de sisteme P2P, vom studia în continuare problema căutării eficiente în rețelele P2P. Cheia acestei căutări eficiente este construirea indecșilor de rutare, aceștia reprezentând o metoda eficiența de găsirea de documente în rețelele P2P. Acești indecși de rutare pot fi de 3 feluri : compuși (compound), cu numărarea hopurilor (hop-count) și exponențiali (exponențial).

Prin intermediul simulărilor acești indecși de rutare au demonstrat ca pot dubla sau chiar tripla performanțele, în cazul căutărilor în rețelele P2P, fata de rețelele care folosesc un mecanism de flood-are și îmbunătăți cu 50 – 100% performanta fata de rețelele care folosesc un mecanism de trimitere aleatoare a interogărilor.

Problema indexării rețelei P2P este foarte asemănătoare cu problema indexării unei baze de date distribuita. Totuși algoritmii pentru indexarea bazelor de date distribuite folosesc 2 principii fundamentale care nu se aplica și în cazul sistemelor P2P :

nodurile sunt stabile și conectate în cea mai mare parte a timpului

numărul de noduri este relativ redus.

Actualmente există câteva rețele P2P disponibile, fiecare cu propria abordare asupra metodei de indexare. Napster [18] folosește indecși centralizați, care așa cum am mai spus, sunt vulnerabili la atacuri. Gnutella [19] nu construiește indecși, în schimb, interogările flood-eaza o parte importanta a rețelei, rezultând astfel o abordare simpla, dar foarte costisitoare din punct de vedere al traficului în rețea, deoarece o interogare se poate dezvolta în sute de mii de interogări în rețeaua Gnutella. Freenet [13] folosește o abordare interesantă pentru indexare : fiecare nod construiește un index, cu locația documentelor accesate recent, așa încât dacă vor fi căutate din nou, acele documente pot fi găsite la un cost redus.

Selectarea unui vecin pentru transmiterea unei interogări este totodată legata și de algoritmii tradiționali de rutare, cum ar fi Bellman-Ford [6, 7]. în cazul algoritmilor noștri diferența majora fata de algoritmii standard de rutare este ca aceștia din urmă sunt proiectați să transmită un ‘pachet’ între 2 noduri prin calea cea mai scurta. în cazul nostru trebuie ca pachetul să fie trimis la unul sau mai multe noduri, așa încât să putem avea cele mai bune răspunsuri la o interogare. De asemenea destinația unui pachet nu este predefinită (ca în rutarea IP), ci în schimb depinde de interogarea conținuta de pachet. Rutarea IP pentru destinații multiple (algoritmi multicast) au fost studiați intenși în special în cartea lui Miller, ‘Multicast Networking and Applications’ [8], dar acești algoritmi necesita crearea unui arbore de multicast relativ stabil.

3.2.1. Rețelele Peer-to-peer

O rețea P2P este formata dintr-un număr mare de noduri care pot să între sau se iese din rețea în orice moment și care au capacități egale. Fiecare nod este conectat la un set de vecini relativ restrâns, care la rândul lor sunt conectați la alte noduri. în Figura 3.9 vecinii nodului A sunt B, C și D. Într-o astfel de rețea pot există cicluri, ca cel cauzat de legătura dintre E și G. Fiecare nod are o baza de date locala, care poate fi accesata cu ajutorul indexului local. Acest index local primește interogări, spre exemplu o interogare în care se căuta cuvintele ‘database systems’ și returnează pointeri înspre documentele care satisfac interogarea.

Figura 3.9 : Exemplu de rețea P2P

3.2.2. Procesarea Interogărilor într-un Sistem P2P de Căutare Distribuita

Într-un sistem P2P de căutare distribuita utilizatorii generează interogări, care au o condiție de oprire, spre exemplu numărul de rezultate dorit. Un nod care primește interogarea prima data evaluează aceasta interogare pe baza bazei de date locale, returnează utilizatorului pointeri înspre rezultate, iar dacă condiția de stop nu a fost satisfăcută nodul selectează unul sau multe noduri dintre vecinii săi și le trimite acestora interogarea. La rândul lor fiecare dintre vecini evaluează acea interogare, returnează pointeri înspre rezultatele obținute și trimite la rândul sau interogarea vecinilor săi.

În Figura 3.9, nodul A primește o interogare, verifica dacă există rezultate locale, iar dacă există trimite acele rezultate nodului de la care a primit interogarea. Apoi, presupunând, ca interogarea nu a fost satisfăcută, nodul A selectează nodul D ca fiind cel mai ‘bun’ vecin al sau și ii trimite interogarea acestuia (linia punctata). Pentru ca nodurile să poată verifica dacă condiția de oprire a fost satisfăcută este necesar a se include, numărul de rezultate găsite până atunci, ca informație de stare la fiecare mesaj de transmitere a interogării. Apoi, nodul D procesează interogarea și selectează nodul I ca fiind cel mai ‘bun’ vecin al sau și trimite interogarea spre acest nod. Presupunând ca nodul I procesează aceasta interogare, dar nu au fost găsite destule rezultate pentru satisfacerea condiției de oprire, nodul I returnează interogarea nodului D care o trimite la următorul cel mai ‘bun’ vecin al sau (în acest caz nodul J).

Interogările pot fi transmise, de către noduri la cel mai ‘bun’ vecin al lor, în paralel sau secvențial. O abordare folosind transmiterea în paralel produce un timp de răspuns mai bun, dar generează un trafic mai mare în rețea și poate duce la epuizarea resurselor, din acest motiv este recomandat a se folosi transmiterea secvențiala a interogărilor.

3.2.3. Indecșii de Rutare

În aceasta secțiune este prezentat un exemplu cum s-ar putea folosi indecșii de rutare compuși (Compound Routing Indicies, CRI), IRC. Scopul folosirii acestor indecși de rutare este de a permite unui nod să selecteze care este cel mai ‘bun’ vecin al sau căruia să ii trimită o interogare. Un index de rutare este o structura de date (si algoritmii asociați), care dându-i-se o interogare, returnează o lista cu vecinii, clasificați în funcție de utilitatea lor pentru a rezolva respectiva interogare. Noțiunea de utilitate poate varia, dar în general se refera la numărul de documente din ‘vecinătatea’ nodului.

Figura 3.10 : Exemplu de indecși de rutare compuși (IRC)

În exemplul următor se considera o rețea P2P în care se vor căuta documente text cu diferite teme, presupunându-se, pentru simplitate, ca rețeaua nu are cicluri. în aceasta rețea un document poate avea 0 sau mai multe teme, iar interogările se vor face după o anumita tema. Fiecare nod din rețea are un index local pentru a găsi repede documentele locale atunci când primește o interogare. Aceste noduri mai au și un index compus de rutare, care conține numărul de documente de pe fiecare cale și numărul documentelor care conțin temele de interes. în Figura 3.10 este prezentat un exemplu de index de rutare compus pentru nodul A, care are 3 vecini (cai) : B, C și D. Pentru a simplifica problema, presupunem ca există doar 4 teme, domenii, de interes : baze de date (BD) , rețele (R), teorie (T) și limbaje (L). Din figura se poate deduce ca prin nodul C se pot accesa 1000 de documente (acestea 1000 de documente sunt localizate în nodurile : C, G și H) și din aceste documente 300 sunt despre rețele și 50 despre limbaje.

Indecșii de rutare, pot fi mai puțin complecși decât indecșii locali menținuți în fiecare nod. Astfel, nodul A, ar putea menține un index local mult mai complex, în care fiecare document este clasificat în sub categorii. Ținându-se, doar un sumar al indexului detaliat, se poate atinge un index de rutare mult mai compact, dar cu costul introducerii unor erori când interogarea unui utilizator sunt bazate pe sub categorii. Prin aceasta compactare a indexului local, se pot introduce erori la contabilizarea documentelor în cadrul indexului de rutare. Spre exemplu, o compactare a diferitelor subteme într-o singura tema, mai generală, (ex: ‘indecși’, ‘recuperare’ și ‘SQL’ în ‘baze de date’) poate introduce erori la contabilizare, rezultând un număr mai mare de documente disponibile decât cel real. Astfel o interogare pentru documentele cu tema ‘SQL’ este convertita într-o interogarea pentru documente cu tema ‘baze de date’, făcându-ne a crede ca sunt mai multe documente cu tema ‘SQL’ decât sunt în realitate, sau chiar nefiind nici un document cu aceasta tema. Aceasta compactare a temelor, mai poate introduce un tip de erori, în sensul ca, folosindu-se un anumit pas, unele teme care au un număr redus de documente pot fi ignorate, creând impresia ca nu există nici un document pe tema respectiva.

Fiind dat un index, este necesar a se calcula ‘utilitatea’ fiecărui nod pentru o anumita interogare. Pentru indecșii de rutare compuși, ca măsura a acestei utilitati, se folosește numărul de documente care poate fi găsit urmărind o anumita cale (path). Numărul de rezultate dintr-o anumita cale poate fi calculat cu următoarea formula :

– reprezintă valoarea celulei cu coloana cu tema și cu rândul pentru un anumit vecin.

Spre exemplu, să presupunem ca nodul A primește o interogare pentru documente cu tema ‘baze de date’ și ‘limbaje’. Estimam numărul de rezultate pentru nodul B la : , pentru nodul C la : și pentru nodul D la : . Prin urmare, ‘utilitatea’ caii B va fi 6, a caii C va fi 0, iar a caii D va fi 75. Aceste numere sunt doar estimări, putând apărea diferite erori de contabilizare. Astfel, dacă există o legătura strânsă între temele ‘baze de date’ și ‘limbaje’, atunci calea B poate să aibă până la 20 de documente care să satisfacă interogarea respectiva. Pe de alta parte, dacă aceste teme sunt foarte diferite între ele, atunci este posibil să nu apară nici un document pe calea B la interogarea respectiva.

O limitare serioasa a acestui algoritm de construire a indecșilor de rutare compuși (IRC) este ca nu ia în considerare numărul de ‘hopuri’ necesare pentru a accesa un document. De exemplu, documentele care pot fi accesate de pe calea B pot fi toate la o distanta de un ‘hop’, în timp ce documentele care pot fi accesate de pe calea C pot fi împrăștiate într-un lung lanț de noduri, pentru găsirea cărora fiind necesare multe mesaje.

3.2.4. Utilizarea Indecșilor de Rutare (IR)

În Figura 3.11 este prezentată o parte a rețelei P2P cu indecșii de rutare atașați la fiecare nod. Pentru compactare temele de interes vor fi reprezentate cum urmează : ‘baze de date’ – BD, ‘rețele’ – R, ‘teorie’ – T, ‘limbaje’ –L. Prima linie din tabel pentru fiecare index de rutare conține un sumar al indexului local. în cazul nostru sumarul indexului local al nodului A, arata ca nodul A are : 300 de documente, dintre care 30 sunt despre ‘baze de date’ , 80 despre ‘rețele’, nici unul despre ‘teorie’ și 10 despre ‘limbaje’. Restul rândurilor reprezintă un IRC. în exemplul prezentat indexul de rutare arata ca nodul A poate accesa 100 de documente cu tema ‘baze de date’ prin nodul D (60 în D, 25 în I și 15 în J).

Figura 3.11 : Indecși de Rutare (IR)

Când nodul A primește de la un client o interogare despre documente cu tema ‘baze de date’ și ‘limbaje’, în primul rând acesta folosește baza de date locale pentru a răspunde interogării. Dacă nu au fost găsite destule rezultate, calculează ‘utilitatea’ fiecărei ‘cai’, după modelul explicat mai sus. în acest caz utilitatea nodurilor B, C și D este de 6, 0 respectiv 75, așa încât A selectează D ca fiind ‘cel mai bun’ vecin căruia să ii trimită interogarea. La rândul sau nodul D returnează toate rezultatele locale și dacă nici în acest caz nu au fost găsite destule rezultate pentru a satisface interogarea, se calculează ‘utilitatea’ nodurilor I și J (25 și 7.5). Având în vedere ca I are ‘utilitatea’ cea mai mare, nodul D transmite interogarea nodului I. La rândul sau, nodul I returnează rezultatele locale, dar nu mai poate transmite interogarea mai departe, deci (dacă sunt necesare mai multe rezultate) returnează interogarea nodului D, care o transmite la nodul vecin următoarea cea mai mare ‘utilitate’ (nodul J). Deși rețeaua din acest exemplu este foarte mica o interogare cu o condiție de stop de 50 de documente va genera 9 mesaje când va folosi ca flood-area ca tehnica de transmitere a mesajelor și doar 3 mesaje dacă folosește IR. Numărul redus al mesajelor ce trebuie trimise folosind IR este rezultatul transmiterii interogării numai către acele noduri care au un potențial ridicat de a obține rezultate.

Spațiul de stocare necesar unui IR într-un nod este relativ modest, având în vedere ca se stochează doar o informație de index pentru fiecare vecin. Mai mult, spațiul de stocare per vecin poate fi ajustat mărind sau micșorând nivelul de compactare al indexului. Spre exemplu, dacă d este dimensiunea numărului de documente în bytes, c numărul de categorii, N numărul de noduri din rețea și v numărul de vecini, atunci un index centralizat ar avea nevoie de bytes, în timp ce fiecare nod dintr-o rețea distribuita ar avea nevoie de bytes. Deși numărul total de bytes pentru toata rețeaua distribuita este de : , care este mai mare decât numărul de bytes pentru un index centralizat, costul de stocare al indexului este împărțit în toate nodurile rețelei.

3.2.5. Crearea Indecșilor de Rutare

Revenind la exemplul anterior, să presupunem ca inițial nu este nici o conexiune între nodurile A și D, starea inițială a sistemului este prezentată cu linii conține în Figura 3.12.a. în momentul în care se stabilește conexiunea dintre nodul A și nodul D, nodul A informează nodul D de toate documentele ce pot fi accesate prin el. Cu alte cuvinte nodul A trimite indexul de rutare agregat nodul D. în exemplul nostru aceasta agregare se face prin adăugarea tuturor vectorilor în indexul de rutare (IR). Deci nodul A trimite nodului D ca el are acces la 1400 de documente (300+100+1000), dintre care 50 au tema ‘baze de date’ (30+20+0), 380 au tema ‘rețele’ (80+0+300), 10 au tema ‘teorie’ (0+10+0) și 90 cu tema limbaje (10+30+50). Nodul A nu trebuie să trimită mai multe informații, deoarece nodul D nu trebuie să știe locația exacta a documentelor, doar ca aceste documente pot fi accesate prin A. După ce nodul D primește indexul agregat al nodului A, adăuga o noua linie indexului sau de rutare, cu identificatorul lui A și indexul agregat al lui A (ca în Figura 3.12.b). Prin agregarea indexului de rutare se reduce atât cantitatea de informații transmisa prin rețea cât și spațiul necesar stocării acestei informații. La fel și nodul D își va agrega IR-ul (excluzând linia corespunzătoare nodului A, dacă aceasta este deja în IR) și va trimite IR-ul agregat nodului A. Pentru creșterea performantei rețelei, procesul de creare a IR-ului în nodurile A și D poate fi făcut în paralel.

După ce nodurile A și D si-au actualizat proprii indecși de rutare, ei trebuie să își informeze și ceilalți vecini ca acum au acces la mai multe documente. Astfel ca nodul D trimite o copie a indexului de rutare agregat nodului I (excluzând linia corespunzătoare nodului I) și nodului J (excluzând linia corespunzătoare nodului J), la fel ca în Figura 5.b. Apoi nodurile I și J își actualizează indecșii de rutare prin înlocuirea liniei corespunzătoare nodului D cu noua informație primita. Dacă nodurile I și J ar fi conectate și la alte noduri, în afară de D, ar trebui să trimită o actualizare a informațiilor și acelor noduri.

Figura 3.12 : Crearea Indecșilor de Rutare

3.2.6. Menținerea Indecșilor de Rutare

Procesul menținerii indecșilor de rutare este identic cu cel al creării acestora. Pentru a ilustra acest fapt, să presupunem ca nodul I introduce 2 documente noi despre ‘limbaje’ în baza să de date . Pentru a actualiza indecșii de rutare ai vecinilor, nodul I își compactează noul index local, agreghează toate rândurile ale indexului sau de rutare compus (excluzând rândul pentru nodul D) și trimite aceasta informație lui D. Apoi D înlocuiește vechiul rând pentru I cu indexul de rutare agregat primit. La rândul sau, nodul D calculează și trimite noi agregate lui A și J. Când primesc aceste actualizări, A și J își actualizează proprii indecși de rutare și calculează noi agregate pentru vecinii lor ș.a.m.d.. Pentru a eficientiza traficul în rețea se poate întârzia trimiterea actualizării pentru o perioada scurta de timp, așa încât să se grupeze mai multe actualizări. Se poate decide a nu se trimite actualizări, când diferența între vechea și noua valoare nu e semnificativă. Netrimițând actualizări minore, se poate face un compromis între costul redus al actualizării și acuratețea indexului de rutare.

Un caz special poate apărea când un nod se deconectează de la rețea. Să presupunem ca nodul I se deconectează de la rețeaua distribuita. Nodul D detectează aceasta deconectare și își actualizează indexul de rutare, înlăturând rândul corespunzător nodului I. Apoi nodul D își informează vecinii asupra schimbării numărului de documente pe care le poate accesa, trimițând noi agregate ale indexului sau de rutare către aceștia. La rândul lor, vecinii lui D își actualizează indecșii de rutare și transmit noua informație vecinilor lor. Astfel, nu a fost nevoie de participarea nodului I în procesul de deconectare. Lipsa necesitații participării unui nod care se deconectează este o trăsătura definitorie într-un sistem P2P, în cadrul căruia nodurile pot să între și să iasă în orice moment.

3.2.7. Indecși de Rutare cu numărarea Hop-urilor

Principala limitare a indexului de rutare compus este ca nu ia în considerare numărul de ‘hop-uri’ (trimiteri ale interogării) necesar pentru a găsi anumite documente. în cadrul indexului de rutare cu numărarea hop-urilor se stochează indexul de rutare agregat pentru fiecare ‘hop’, până la numărul maxim de hop-uri (orizontul indexului de rutare). în Figura 3.13 este prezentat un exemplu de IR cu numărarea hopurilor cu orizont de 2 ‘hopuri’. Acest nod cu IR-ul cu numărarea hop-urilor are 3 vecini :X,Y și Z. Cu un hop via vecinul X, nodul poate să găsească 60 de documente, dintre care 4 sunt despre ‘baze de date’, 2 despre ‘rețele’, 5 despre ‘teorie’ și 10 despre ‘limbaje’. Nodul poate și să găsească alte 20 de documente prin X la distanta de 2 ‘hop-uri’ (de exemplu : la vecinii lui X). Nu există informații dincolo de orizont, cu acest tip de IR.

Figura 3.13 : Un exemplu de IR cu numărarea ‘hop-urilor’ pentru nodul W

Pentru estimarea unui IR cu numărarea ‘hop-urilor’ este nevoie de un model de cost pentru a calcula ‘utilitatea’ unui vecin. De exemplu, vecinul X, poate fi preferat fata de vecinul Y pentru o interogarea cu tema ‘BD’, deoarece prin X putem găsi 13 rezultate la distanta de 1 hop, în timp ce prin Y ar fi nevoie de 2 hop-uri pentru a găsi rezultate. Pe de alta parte, se pot găsi mai multe rezultate (31) prin nodul Y.

Costul poate fi definit prin numărul de mesaje care se transmit, iar apoi putem defini ‘utilitatea’ unui vecin ca un raport (ratio) dintre numărul de documente disponibile prin acel vecin și numărul de mesaje necesare pentru obținerea acelor documente. Deci un vecin care ne permite găsirea a 3 documente per mesaj este mai util decât un vecin care permite găsirea unui singur document per mesaj.

Un model simplu care permite calcularea acestui raport (ratio) este modelul cu cost de tip arbore (regular-tree cost model). Acest model presupune ca documentele găsite sunt distribuite uniform în rețea și ca rețeaua este asemenea unui arbore cu ramificația (fanout) F. Conform acestor presupuneri sunt necesare mesaje pentru a găsi toate documentele aflate la hop-ul h. De aceea, se poate calcula numărul de documente per mesaj împărțind numărul prevăzut de documente rezultate la fiecare hop cu numărul de mesaje necesare pentru aflarea acestora. Se definește utilitatea () cu privire la interogarea I pentru indexul de rutare cu numărarea hop-urilor ca fiind : , unde h este orizontul al IR-ului cu numărarea hop-urilor, utilitate() ca o estimare pentru indexul de rutare compus (IRC), este intrarea în IR pentru aflat la o distanta de j hop-uri. în exemplul nostru, dacă presupunem ca F=3, utilitatea lui X pentru o interogare cu tema ‘BD’ ar fi : 13 + 10/3 = 16.33 și pentru Y ar fi : 0 + 31/3 = 10.33, așa încât X este preferabil lui Y.

Un nod care trebuie să își informeze vecinii despre o actualizare, la început construiește IR-ul agregat după același model ca și IR-ul compus. Apoi muta coloanele spre dreapta, așa încât intrările pentru distanta de 1 hop devin intrări pentru distanta de 2 hop-uri, iar intrările pentru distanta de 2 hop-uri devin intrări pentru distanta de 3 hop-uri s.a.m.d. Intrările din ultima coloana a IR-ului inițial sunt înlăturate și compactarea indexului local este introdusa în prima coloana a noului tabel. Acest IR agregat este transmis tuturor vecinilor care la rândul lor își actualizează propriile IR-uri.

3.2.8. Index de Rutare Agregat Exponențial

Indexul de rutare cu numărarea hop-urilor este eficient în luarea în calcul a numărului de hop-uri. Totuși acest avantaj are ca efect necesitatea mai mare de stocare și de transmitere datelor fata de IR-ul compus. S-a constatat ca performanta IR-ului cu numărarea hopurilor este afectata negativ de lipsa de informație dincolo de orizont (un IRC-IR cu numărarea hop-urilor hibrid depășește acest avantaj, dar nu rezolva, totuși, problema stocării și a costului de transmisie).

IR-ul agregat exponențial reprezintă o structura de index alternativ, care depășește aceste neajunsuri cu prețul unor potențiale pierderi de acuratețe. Indexul de rutare agregat exponențial (IRAE) stochează rezultatul aplicării formulei costului de tip arbore unui IR cu numărare de hop-uri. Fiecare intrare a indexului de rutare exponențial (IRE) pentru un nod N, conține o valoare calculata astfel : , unde h este înălțimea și F ramificația (fanout) arborelui, utilitate() este estimarea indexului de rutare compus, V[j] este compactarea indexului local al vecinului j pentru nodul N și T este tema de interes a intrării.

Figura 3.14 : Un exemplu de index de rutare exponențial pentru nodul W

În Figura 3.14 prezentam un IRAE calculat din exemplu precedent din Figura 6. Presupunem astfel ca vecinii X, Y și Z sunt noduri ‘frunza’ și ca ramificația (fanout) arborelui este 3. Intrările cu tema ‘BD’ pentru X și Y au valorile 13 + 10/3 = 16.33 și 0 + 31/3 = 10.33.

IR-ul exponențial face aceleași presupuneri ca și modelul de cost de tip arbore și poate să nu fie realist în unele situații, dar poate fi totuși folosit ca un index aproximativ. Există o diferența fundamentala între IR-ul exponențial și IR-ul cu numărarea hop-urilor. în timp ce acesta din urmă nu are nici o informație dincolo de orizont, IR-ul exponențial păstrează informația pentru toate nodurile accesibile. Se poate constata ca IR-ul exponențial depășește din punct de vedere al performantelor IR-ul cu numărarea hop-urilor în cele mai multe cazuri.

Pentru actualizarea indecșilor de rutare exponențiali, nodul care trebuie să trimită actualizarea unui vecin, trebuie să adauge toate rândurile (exceptând rândul asociat vecinului către care este trimis vectorul de actualizare), multiplica vectorul rezultat cu 1/F și adăuga ‘utilitatea’ compactării indexului sau local. Se poate observă ca multiplicarea cu 1/F are același efect ca și ‘mutarea’ coloanelor în IR-ul cu numărarea hop-urilor, deoarece se adăuga ‘utilitatea’ indexului local ca și cum ar fi primul hop. Când vecinul primește acest vector de actualizare, înlocuiește rândul corespunzător nodului care i-a trimis actualizarea cu noul vector și transmite mai departe actualizările vecinilor săi. în actualizarea IR-urilor exponențiale este esențiala transmiterea actualizărilor numai când noile și vechile valori ale vectorului sunt destul de ‘diferite’ (spre exemplu: ca distanta Euclidiana dintre cei 2 vectori să fie mai mare decât un număr dat).

Proiectarea de Detaliu

4.1. Prezentarea Generală a Aplicației (Arhitectura)

Aplicația Gdownloader a fost dezvoltată în .NET, mai precis în C#, cu ajutorul Microsoft Visual Studio .NET 2003 și este un client al rețelei P2P Gnutella. Cazul de utilizare al aplicației este prezentat în imaginea următoare cu ajutorul diagramelor Use-Case.

Figura 4.1: Diagrama Use-Case

În continuare este prezentată diagrama de colaborare a proiectului, diagrama care evidențiază principalele elemente ale aplicației și colaborarea acestora în contextul unui comportament dinamic al sistemului. Aceste diagrame sunt utile pentru a vizualiza cum mai multe elemente ale unui sistem colaborează pentru realizarea unei anumite sarcini, dar și pentru compararea modelului dinamic al proiectului cu cel static.

Figura 4.2: Diagrama de Colaborare

Diagrama de secvență a proiectului, în care accentul se pune pe temporalitate și pe ordinea în care sunt mesajele transmise și nu pe relațiile între elemente, este prezentată în figura următoare.

Figura 4.3 : Diagrama de Secvență

Aplicația GDownloader este formată din 16 clase. în imaginea următoare este ilustrată diagrama de clase în care este scoasă în evidență relația de moștenire între clase ; este prezentată fiecare clasa și clasa pe care o moștenește.

Figura 4.4 : Diagrama de Clase. Relația de Moștenire

Gdownloader a fost concepută ca o aplicație MDI (Multiple-Document Interface). Acest tip de aplicație permite afișarea mai multor documente, fiecare document fiind afișat în propria fereastră, toate documentele fiind conținute într-un singur ‘container’ părinte. Temelia tipului de aplicație MDI este ‘form-ul’ părinte care conține toate ferestrele MDI copil, care sunt sub-ferestrele prin care utilizatorul interacționează cu aplicația MDI. Spre deosebire de aplicațiile SDI (Single-Document Interface), în care există o singură instanță a clasei document, într-o aplicație MDI pot există simultan mai multe obiecte document. Crearea unui obiect document duce întotdeauna la crearea unei noi ferestre reprezentare, asocierea acesteia cu documentul și crearea unei noi ferestre cadru care va conține reprezentarea. Pentru că la un moment data pot există mai multe instanțe document, infrastructura MDI, introduce conceptul de document activ. Un document devine activ în momentul în care utilizatorul interacționează cu una din reprezentările asociate acestuia.

În afara de ‘container-ul’ MDI părinte care este reprezentat în aplicația Gdownloader de clasa MainForm, aplicația are 3 tipuri de ferestre MDI copil, acestea fiind :

Fereastra de conexiuni (Connections) în care sunt afișate informații în legătura cu nodurile la care clientul Gnutella s-a conectat și nodurile la care încearcă să se conecteze, clasa care se ocupa de acest proces fiind clasa Connections.

Fereastra de căutare efectiva a informațiilor (Search) în care sunt prezentate opțiunile după care se pot face căutările în rețeaua Gnutella și rezultatul acestor căutări, de aceasta secțiune a aplicației ocupându-se clasa SearchResult.

Fereastra de transfer al fișierelor (Traffic) în care sunt afișate fișierele care au fost selectate pentru a fi descărcate (download-ate) și informații despre procesul de descărcare (downloading) al fișierelor, implementarea acestor procese făcându-se în clasa Traffic.

4.2. Container-ul MDI Părinte (MainForm)

Container-ul MDI părinte este responsabil de inițializarea și dealocarea resurselor pentru toate tipurile de ferestre MDI copil, făcând totodată posibilă și comunicarea între aceste ferestre copil.

Clasa MainForm, care reprezintă acest container MDI, este și punctul de intrare pentru aplicația GDownloader, fiind responsabila totodată și cu primitivele de conectare și deconectare la rețeaua Gnutella. în aceasta clasă se fac toate inițializările necesare unei bune funcționari a aplicației, se încarcă fișierul ‘GDownloader.ini’ (dacă există) în care sunt salvate opțiunile și preferințele pentru aplicația Gdownloader, se încarcă fișierul ‘WebCache.ini’ (dacă există) din care se citesc adresele host-urilor unde aplicația GDownloader va încerca să se conecteze. Tot în aceasta clasă se face și inițializarea și verificarea versiunii librăriei GnucDNA care oferă funcțiile de acces la rețeaua și protocolul Gnutella.

Figura 4.5 : Containerul MDI al Aplicației

Clasa MainForm este totodată responsabilă și cu inițializarea și managementul meniului dar și cu gestionarea ‘barei de stare’ (status bar) a aplicației GDownloader.

Meniul este format din 4 elemente ‘pop-up’ : File, View, Window și Help. Meniul ‘pop-up’ File conține elementele: ‘Connect’, care afișează fereastra de conexiuni prin care aplicația se conectează la rețeaua Gnutella; ‘Disconnect’ prin care se realizează deconectarea aplicației de la rețeaua Gnutella, presupunând în prealabil ca aplicația este conectată la rețea; ‘Preferences’ care afișează fereastra de dialog unde pot fi vizualizate și setate opțiunile de configurare ale aplicației Gdownloader; ‘Exit’, element care ne permite părăsirea aplicației. Meniul ‘pop-up’ View conține 3 elemente: Connections, Search și Traffic acestea reprezentând tipurile de ferestre MDI copil, aceste elemente fiind activate doar după ce s-a realizat conectarea la rețea. Meniul ‘pop-up’ Window este un element de meniu specific arhitecturii MDI (Multiple-Document Interface) care permite navigarea printre ferestrele MDI copil care sunt deschise. Meniul ‘pop-up’ Help conține un singur element About care prezintă macheta de dialog unde sunt afișate informații despre versiunea aplicației, precum și de dezvoltatorul aplicației.

Bara de stare (status bar-ul) este divizată în 3 subunități. Prima subunitate, din partea stângă ne prezintă informații în legătură cu starea curentă a aplicației, această stare putând fi: ‘Disconnected’ când aplicația a fost deconectată de la rețeaua Gnutella, ‘Connecting…’ când se încearcă conectarea la rețea și “Connected to x nodes”, când s-a reușit conectarea la rețea, x reprezentând numărul de noduri la care aplicația este curent conectată. Celelalte 2 subunități ale barei de stare prezintă: rata de date primite (Receive Rate), care se calculează făcând media pe ultimul minut al numărului de bytes primiți în ultima secunda și rata de date trimise (Send Rate), care se calculează făcând media pe ultimul minut al numărului de bytes trimiși în ultima secunda.

La închiderea programului tot clasa MainForm, este responsabila și cu dealocările de resurse folosite pe parcursul rulării programului, realizând totodată și deconectarea aplicației de la rețeaua Gnutella și salvarea în fișierul de configurări ‘GDownloader.ini’ a preferințelor aplicației.

Diagrama de clase pentru clasa MainForm este prezentată în figura următoare. Rolul diagramelor de clase este de a descrie clasele relativ la un anumit model. în aplicațiile orientate obiectual, clasele au atribute (variabile), operații (funcții), dar și relații (moștenire, agregare, asociere) cu alte clase, toate acestea fiind descrise în diagrama de clase. în această diagrama de clase sunt prezentate doar relațiile clasei MainForm cu clasele care fac parte din pachetul (namespace-ul) ‘GDownloader’ și ce clasă moștenește clasa MainForm.

Figura 4.6 : Diagrama de Clase pentru clasa MainForm

4.3. Procesul de Conectare (Connections)

Această parte a aplicației se ocupă de managementul conexiunilor pe care aplicația GDownloader le menține active pentru a putea efectua căutări și transferuri de fișiere din rețeaua Gnutella. Astfel sunt oferite funcții de inserare de noduri la care aplicația să încerce să se conecteze, posibilitatea de a elimina unul sau mai multe noduri la care aplicația s-a conectat deja, dar și de a vizualiza proprietățile și anumite informații în legătura cu nodurile la care s-a reușit conectarea.

Diagrama de clase pentru clasa Connections care este clasa care se ocupă cu managementul conexiunilor este prezentată în figura următoare. în această diagrama de clase sunt prezentate doar relațiile clasei Connections cu clasele din pachetul ‘GDownloader’ și mai este prezentată clasa de bază a clasei Connections.

Figura 4.7 : Diagrama de Clase pentru clasa Connections

În fereastra de dialog din Figura 4.8 sunt prezentate în partea stângă o listă cu nodurile la care aplicația încearcă să se conecteze, iar în partea dreaptă a ferestrei este afișată o lista cu nodurile la care aplicația s-a conectat deja.

Figura 4.8: Fereastra de Conexiuni (Connections)

În lista cu nodurile la care se încearcă conectare (Trying To Connect) sunt specificate următoarele informații:

Node – adresa de IP a nodului la care se încearcă conectarea.

Port – portul pe care se încearcă conectarea.

Status – starea acestui proces de conectare.

În lista cu nodurile la care aplicația Gdownloader s-a conectat deja (Connected Nodes) sunt disponibile următoarele informații despre nodurile respective :

Node – adresa de IP a nodului la care s-a reușit conectarea.

Port – portul nodului respectiv.

Type – tipul nodului. Tipurile de noduri suportate de rețeaua Gnutella sunt următoarele : Normal, Ultrapeer și Leaf. în mod obișnuit aplicația se conectează la nodurile declarate Ultrapeer.

Bandwidth – lățimea de bandă a nodului. Lățimea de bandă a unui nod la care s-a conectat aplicația se calculează ca fiind suma dintre numărul de bytes trimiși în ultima secundă și numărul de bytes primiți în ultima secundă de acel nod.

Client – reprezintă numele aplicației care rulează pe nodul la care s-a reușit conectarea.

Up Time – durata conectării. Aceasta durată indică diferența de timp între momentul actual și momentul conectării aplicației la nodul respectiv.

Efficiency – eficiența acelui nod. Eficiența fiecărui nod la care aplicația Gdownloader s-a conectat se calculează făcând raportul pe ultima secundă dintre numărul de pachete ‘utile’(good) și numărul total de pachete.

Aplicația Gdownloader permite totodată vizualizarea unor informații și mai detaliate despre nodurile la care aplicația s-a conectat, cu alte cuvinte proprietățile nodurilor la care aplicația este conectată. Vizualizarea proprietăților unui nod se poate face în 2 feluri : fie se face ‘dublu click’ pe nodul al cărui proprietăți vrem să le vizualizăm fie se selectează opțiunea ‘Properties’ din meniu contextual asociat listei cu nodurile conectate.

Figura 4.9: Fereastra de Proprietăți ale unui Nod

În cadrul ferestrei de proprietăți ale unui nod sunt accesibile următoarele informații în legătură respectivul nod la care aplicația GDownloader s-a conectat :

IP – adresa de IP a host-ului respectiv.

Port – port-ul host-ului respectiv.

Host – numele host-ului. Cunoscându-se adresa de IP a nodului respectiv se poate rezolva și numele host-ului cu ajutorul DNS-ului (Domain Name System). Dacă acest nume, totuși nu poate fi rezolvat va apărea un mesaj de eroare ‘Unable to resolve the host name’.

Type – tipul nodului respectiv.

Time Connected – data și ora când aplicația Gdownloader s-a conectat la nodul respectiv.

HandShake – protocolul de conectare dintre aplicație și nodul respectiv. Protocolul de conectare (handshake) dintre aplicație și un nod specifică toate informațiile necesare conectării și comunicării între aplicație și nodul respectiv. Sunt specificate 2 categorii de informații : în legătură cu aplicația și în legătură cu nodul la care aplicația s-a conectat. Astfel trebuie specificată versiunea de protocol Gnutella care este folosită de aplicație, această versiune fiind Gnutella 0.6, care este a 2-a versiune oficială după Gnutella 0.4, în prezent lucrându-se la introducerea unui nou standard în ce privește protocolul Gnutella, acest nou standard purtând numele de Gnutella2 sau G2. O altă informație în legătură cu aplicația este numele și versiunea clientului (User-Agent), care în acest caz este GDownloader 1.0. Alte informații în legătură cu aplicația ar fi : specificarea proprietății dacă poate să devină ‘ultrapeer’ (X-Ultrapeer) și numărul maxim de sisteme care pot fi legate simultan la acest nod (X-Leaf-Max), dar și diferența de timp, specificată în zile, ore și minute, dintre momentul pornirii aplicației și momentul în care aplicația s-a conectat la nodul respectiv (Uptime). Informațiile în legătura cu nodul la care aplicația s-a conectat specifică versiunea de protocol Gnutella pe care respectivul nod o folosește, care este tot Gnutella 0.6, adresa de IP a nodului respectiv, numele clientului de Gnutella care rulează pe nodul respectiv, dacă nodul respectiv este ‘ultrapeer’ și o listă cu alte noduri la care respectivul nod a reușit să se conecteze (X-Try-Ultrapeers).

Utilizatorul are posibilitatea de a introduce noi noduri la care aplicația Gdownloader să se conecteze, dar totodată să și elimine din nodurile la care aplicația s-a conectat deja. Eliminarea de noduri la care aplicația s-a conectat se poate face în 2 moduri fie prin apăsarea butonul ‘Remove Node’ fie prin selectarea opțiunii ‘Remove Node’ din cadrul meniului contextual asociat listei de noduri conectate. Adăugarea unui nod la care aplicația să se conecteze se poate face cu ajutorul butonului ‘Add Node’. în fereastra de dialog pentru adăugarea unui nod sunt necesare introducerea adresei și portulului, ale host-ului la care se dorește conectarea.

Figura 4.10: Fereastra de Adăugare a unui Nod

4.4. Procesul de Căutare (Search)

Această secțiune a aplicației se ocupă cu căutarea efectivă de informații și fișiere, oferind posibilitatea de a selecta unul sau mai multe fișiere, rezultate, pentru a fi transferate (download-ate) dar și posibilitatea de a vizualiza anumite date și proprietăți ale fișierelor găsite ca rezultat la interogarea introdusă.

Aplicația GDownloader suportă 2 tipuri de căutări :

căutarea de informații în rețeaua Gnutella. Despre acest tip de căutare vom vorbi în continuare în acest subcapitol.

căutarea de informații pe Web, căutare care se face cu ajutorul motorului de căutare Google [14]. Acest tip de căutare va fi tratată în alt subcapitol.

În diagrama din figura următoare este prezentată diagrama de clase pentru clasa SearchResult, clasa care se ocupa cu procesul de căutare. și în cazul acestei diagrame sunt prezentate doar relațiile clasei cu clasele care fac parte din pachetul ‘GDownloader’ și cu clasa pe care o moștenește.

Figura 4.11 : Diagrama de Clase pentru clasa SearchResult

Figura 4.12 : Fereastra de Căutare (Search)

Pentru a iniția o simplă căutare în rețeaua Gnutella trebuie să se introducă un text după care să se facă căutarea și să se apese tasta enter sau butonul ‘Start Search’. Textul după care se face căutarea trebuie să aibă cel puțin 2 caractere, deoarece căutarea după un singur caracter nu ar fi deloc elocventă; în cazul în care textul de căutare nu conține cel puțin 2 caractere se va afișa un mesaj de eroare utilizatorului : ‘The searched word must be at least 2 letters long !’. Foarte important este că, căutarea în rețeaua Gnutella se face după cuvinte (căutare după stringuri) și nu după, părți din cuvinte (substringuri). Acesta fiind încă un motiv pentru a nu se face o căutare după a singura literă, deoarece sunt prea puține cuvinte care conțin doar o singură literă.

Aplicația GDownloader suportă și o căutare avansată în rețeaua Gnutella, putându-se căuta după tipul aplicației dorite și dimensiunea fișierelor. Căutarea standard, simplă, se face după toate tipurile de aplicații și după fișiere cu dimensiunea cuprinsa între 1 și 1000 de Mega Bytes.

Căutarea după tipul aplicației se face în funcție de extensia fișierelor. Managementul extensiilor de fișiere și implicit al tipurilor de aplicații recunoscute de GDownloadar este făcut în clasa ApplicationType. Astfel aplicația GDownloader suportă 6 categorii de tipuri de aplicații diferențiate în funcție de extensii :

Audio. Include extensiile : mp2, mp3, wav și wma.

Video. Include extensiile : asf, avi, divx, m1v, m2v, mov, mpe, mpeg, mpg, mp2v, mpv2, qt și wmv.

Picture. Include extensiile: bmp, gif, iff, jpeg, jpg, pcx, png, psd, ras, rsb, sgi, tga și tiff.

Document. Include extensiile: chm, doc, pdf, ppt, rtf și txt.

Compressed. Include extensiile: ace, arj, bz2, cab, gz, lha, rar, tar, uha și zip.

Anything Else. în aceasta categorie intră toate celelalte tipuri de aplicații ale căror extensii nu au fost specificate.

În cazul căutării după dimensiunea fișierelor, această dimensiune a fișierelor poate fi de ordinul : Bytes-ilor, Kilo Bytes-ilor, Mega Bytes-ilor și Giga Bytes-ilor. în cazul în care în căsuțelele de editare (edit box-urile) asociate specificării dimensiunii fișierelor nu se introduce un număr sau se introduce un număr negativ sau primul număr este mai mare decât al doilea, utilizatorul va primi un mesaj de eroare de genul : “File size error”.

Aplicația Gdownloader afișează pentru fiecare căutare în rețeaua Gnutella, o listă cu rezultatele găsite în care sunt specificate următoarele informații:

File – numele fișierului.

Type – extensia fișierului

Media – tipul aplicației, care poate avea, în funcție de extensia fișierului, una dintre următoarele valori : Audio, Video, Picture, Document, Compressed, Executable sau caracterul ‘-’ dacă extensia respectiva nu aparține nici unui tip enumerat mai sus.

Size – dimensiunea fișierului. Aceasta dimensiune este formatată astfel încât să fie afișată într-un format optim, convertindu-se după caz numărul de Bytes în Kilo Bytes, Mega Bytes sau Giga Bytes.

Hashed – dacă fișierul este indexat folosind o funcție de hashing. Cu ajutorul coloanei ‘Hashed’ din lista putem vedea dacă fișierul respectiv a fost indexat cu o funcție de hashing (spre exemplu SHA – Secured Hash Algorithm). Această informație este utila pentru a se păstra compatibilitatea cu versiunile anterioare ale protocolului Gnutella. Prima versiune a protocolului Gnutella, Gnutella 0.4 nu suporta indexarea fișierelor și în cazul unei căutări interogarea era trimisa prin flood-are întregii rețea. Indexarea fișierelor folosind funcții de hashing a fost introdusă din versiunea următoare a protocolului, Gnutella 0.6, care este versiunea curentă a protocolului Gnutella, în prezent făcându-se eforturi pentru adoptarea unui nou standard Gnutella 2 sau G2.

Hosts – numărul de host-uri unde a fost găsit un anumit fișier. Acesta se calculează ca fiind numărul de sisteme unde a fost găsit fișierul care are exact aceeași intrare în indexul de hashing. Această informație este utila în selectarea rezultatelor care vor fi transferate (download-ate), deoarece protocolul Gnutella și implicit aplicația GDownloader suportă transferul concurent de la multe surse (multi-source downloading), astfel un fișier care a fost găsit pe mai multe host-uri având șanse, cel puțin teoretice, de a avea o rată mai mare de transfer și de a fi transferat (download-at) într-un timp mai scurt.

Speed – viteza de transfer specificata pentru acel fișier. Viteza de transfer pentru fiecare fișier care a fost găsit ca rezultat este afișată în Kilo Bytes/sec (KB/s). Această viteză de transfer se calculează făcându-se o medie din toate vitezele de transfer ale sistemelor care conțin fișierul respectiv.

De formatarea informațiilor pentru o afișare cât mai optimă la utilizator se ocupă clasa Service, în care sunt definite metode pentru formatarea dimensiunii unui fișier din Bytes în Kilo Bytes, Mega Bytes sau Giga Bytes, dar și metode pentru verificarea dacă dimensiunea unui fișier este într-un anumit domeniu dat.

Transferul de fișiere (download-ul) se poate face fie cu ajutorul butonului ‘Download’ fie cu ajutorul opțiuni ‘Download’ din meniul contextual asociat listei în care sunt prezentate rezultatele căutării. în fața fișierelor care au fost selectate pentru a fi transferate fiind afișata o săgeată, aceasta indicând că aceste fișiere se transferă. Tot din meniul contextual asociat listei în care sunt prezentate rezultatele ‘căutării’, cu ajutorul opțiunii ‘Cancel Download’, putem să anulăm transferul unui fișier. Odată cu anularea transferului unui fișier se observă și dispariția săgeții din fata fișierului care se transferă.

Când se face o noua căutare se verifica în lista de transferuri dacă nu sunt printre rezultatele găsite fișiere care au fost selectate pentru a fi transferate (download-ate), în acest caz afișându-se în fața acestora săgeata care indică că fișierul respectiv se transferă. La fiecare activare a ferestrei de căutare (Search) se verifică în lista de transferuri dacă nu anumite transferuri au fost anulate, în acest caz înlăturându-se săgeata care marca transferul unui fișier, din dreptul acestuia.

Fereastra de căutare dispune de un buton default, buton care nu este vizibil, și a cărui funcție este de a decide ce tip de căutare se lansează atunci când a fost apăsată tasta enter. Această decizie se ia în funcție de ultima căutare în clasa SearchResult, care se ocupă cu managementul căutărilor, aflându-se un atribut în care se păstrează tipul ultimei căutări.

Aplicația GDownloader indică, deasupra listei în care sunt afișate rezultatele ‘căutării’, textul căutării curente și numărul de rezultate găsite, care satisfac aceasta ‘căutare’, dar totodată și un cronometru care înregistrează diferența de timp în ore, minute și secunde între momentul actual și momentul în care s-a generat interogarea. Acest cronometru este activ atâta timp cât o anumită ‘căutare’ este activa, ‘căutarea’ putându-se termina prin apăsarea butonului ‘End Search’ sau cu ajutorul opțiunii ‘Disconnect’ din meniul ‘File’ al aplicației, când se dorește deconectarea aplicației de la rețeaua Gnutella. Cronometrul va fi resetat în cazul în care se inițiază o nouă ‘căutare’.

La inițierea fiecărei operații, operații cum ar fi : căutarea, transferul de fișiere, anularea transferului de fișiere, vizulizarea proprietăților unui fișier sau vizualizarea transferurilor de fișiere, se verifica dacă aplicația GDownloader mai este conectată la cel puțin un nod din rețeaua Gnutella. în cazul în care nu mai este conectată la cel puțin un nod din rețea sau aplicația a fost deconectată, operația inițiată nu poate începe și se afișează un mesaj de eroare ‘Not connected !’ utilizatorului. Dacă din meniul ‘File’ al aplicației se apasă opțiunea ‘Disconnect’ căutarea curentă se încheie, oprindu-se totodată și cronometrul, ne mai fiind disponibile nici una dintre operațiile menționate mai sus.

Dacă se doresc mai multe informații în legătura cu un anumit fișier care a fost găsit ca rezultat se poate selecta din meniul contextual asociat listei opțiunea ‘Properties’, putând astfel a fi vizualizate proprietățile și informațiile despre un anumit fișier.

Figura 4.13 : Fereastra de Proprietăți ale unui Fișier

În cadrul Ferestrei de Proprietăți ale unui Fișier sunt accesibile următoarele informații : numele și dimensiunea fișierului, hash-ul rezultatului (Hash), numărul de host-uri pe care fișierul respectiv a fost găsit și o listă cu informații despre fiecare dintre host-uri pe care fișierul a fost găsit. Hash-ul rezultatului este acea informație care indică că exact același fișier se afla pe mai multe host-uri din rețea.

Lista cu informații despre fiecare host pe care a fost găsit fișierul respectiv indică:

Host – adresa host-ului respectiv.

Port – port-ul host-ului respectiv.

Hops – distanta în hop-uri a hostului față de localhost.

Speed – viteza de transfer care este disponibilă la acel host în kilo bytes per secundă.

Free Slots – dacă host-ul are slot-uri de upload libere.

Stable – dacă host-ul este stabil, adică dacă host-ul respectiv a reușit să upload-eze cel puțin un fișier.

Properties – dacă acel host se află sau nu după vreun Firewall.

Client – numele clientului care rulează pe host-ul respectiv.

4.5. Procesul de Transfer (Traffic)

Această secțiune a aplicației se ocupă cu managementul transferurilor de fișiere care au fost selectate spre a fi download-ate. Astfel se oferă funcții de oprire și repornire de download-uri de fișier, posibilitatea de a executa fișierele care s-au transferat și fișierele parțiale, posibilitatea de a înlătura definitiv anumite downloaduri din listă, dar și de a vizualiza proprietățile unui anumit download.

În Figura 4.14 este prezentată diagrama de clase pentru clasa Traffic, fiind prezentate numai relațiile acestei clase cu clasele din pachetul ‘GDownloader’ și clasa pe care o moștenește clasa Traffic.

Figura 4.14 : Diagrama de Clase pentru clasa Traffic

Figura 4.15 : Fereastra de Transferuri (Traffic)

În Figura 4.15 este prezentată fereastra de dialog aferentă procesului de transfer de fișiere din rețeaua Gnutella. Astfel în această fereastră este prezentată o listă cu toate fișierele care sunt transferate, această listă prezentând următoarele informații :

File – numele complet al fișierului care se download-eaza.

Status – reprezintă starea curentă a procesului de download-ing. Această stare poate lua una dintre următoarele valori: No Sources, Pending, Connecting, Connected, Push, Closed, Completed, Cooling Down sau Queued.

Download – cu ajutorul unui progress bar este indicat ce procent din dimensiunea totală a fișierului a fost transferat până în acel moment. Procentul se calculează ca raportul numărului de bytes care au fost aduși până în acel moment și numărul de bytes total al fișierului.

Size – reprezintă dimensiunea totală a fișierului care se downloadeaza. Aceasta dimensiune este formatată, în clasa Service, astfel încât să fie afișată într-un format optim, convertindu-se după caz numărul de Bytes în Kilo Bytes, Mega Bytes sau Giga Bytes.

Completed – indică dimensiunea care a fost adusă din fișierul respectiv până la acel moment de timp. Aceasta dimensiune este și ea formatată după modelul de mai sus, pentru o afișare cât mai optimă.

Speed – reprezintă viteza curentă de transfer a fișierului respectiv. Această viteză de transfer este calculată ca o medie pe ultimul minut și este și ea formatată după modelul de mai sus, pentru o afișare cât mai optimă.

Eștimated Time – reprezintă timpul estimat până la completarea procesului de download-ing al fișierului respectiv. Formatarea și prezentarea acestei informații se face în clasa Service, clasă care se ocupă de formatarea într-un mod cât mai adecvat a informațiilor care sunt prezentate utilizatorului.

Bara de progres (progress bar) care este folosită în coloana ‘Download’ din lista de transferuri reprezintă un control .Net, care a fost implementat în clasa MyProgressBar. Această clasă moștenește clasa UserControl din namespace-ul System.Windows.Forms din C#, clasă care este responsabilă cu cererea de controale utilizator. Această bară de progres a fost dezvoltată cu scopul de a se putea afișa în centrul controlului un text cu procentul indicat de bara de progres. Acest control mai dispune și de alte facilități cum ar fi posibilitatea de setare a culorii textului cu care este afișat procentul, posibilitatea de setare a culorii barei de progress și a fundalului controlului, precum și posibilitatea de setarea a valorilor de minim și maxim a barei de progres.

În cadrul procesului de transferare a unui fișier, datele parțiale care s-au transferat din acel fișier sunt stocate într-un director numit ‘Parțials’ care se află la calea specificată de utilizator în cadrul secțiunii de preferințe ale aplicației GDownloader la opțiunea ‘Parțial Downloads’. Acel fișier care conține datele parțiale va avea exact numele fișierului care se transfera, iar în momentul în care procesul de download al fișierului s-a încheiat acest fișier va fi mutat în directorul specificat de utilizator pentru stocarea fișierelor care au fost downloadate.

La transferarea unui fișier acesta este împărțit în ‘bucăți’, care se mai numesc și ‘chuncks-uri’, cu dimensiuna de 524288 Bytes = 512 Kilo Bytes pentru suportul de download simultan de la mai multe surse (multi-source downloading). Astfel un fișier care a fost găsit pe mai multe host-uri poate fi downloadat simultan de pe mai multe sisteme; de pe fiecare sistem putând a fi downloadat câte o bucată (chunck) a respectivului fișier. Pentru fiecare fișier care se transferă se creează cate un fișier cu numele acestuia și extensia ‘part’ care va conține informații în legătură cu chuncks-urile fișierului respectiv. Acest fișier va conține o listă cu toate bucățile în care este spart fișierul și câți bytes au fost aduși din fiecare bucata și host-ul de la care se aduce (s-a adus) acea bucată.

În directorul pentru transferurile parțiale (parțial downloads) mai este salvat pentru fiecare download și cate un fișier care va avea numele acelui fișier care se downloadează și extensia ‘info’ și conține informații în legătură cu procesul de downlodare. Concret în acest fișier se salvează : starea curentă a procesului de download-ing, numele complet al fișierului care se transferă, dimensiunea în Bytes a acestui fișier, dimensiunea bucăților (chuncks) în care va fi spart fișierul (standard 524288 Bytes), calea unde va fi downlodat fișierul, calea spre directorul care conține datele parțiale ale transferului, informația de hashing obținută cu algoritmul SHA (Secured Hash Algorithm), identificatorul căutării care a găsit acest fișier și o listă cu host-urile unde a fost găsit fișierul respectiv. Această listă cu host-uri conține date referitoare la host-uri cum ar fi : adresa de IP și port-ul host-ului respectiv, numele clientului care rulează pe acel host, dacă host-ul respectiv are slot-uri de upload disponibile, dacă host-ul respectiv este stabil (adică dacă a reușit cel puțin un upload de fișier), viteza curentă de transfer a acelui host și indexul fișierului care se transferă pe acel nod.

Cu ajutorul acestor fișiere în care se păstrează informațiile parțiale și informațiile de transfer despre fiecare download, aplicația GDownloader oferă suport pentru reluarea download-urilor (resume) care au fost oprite, abortate, sau a căror surse nu mai sunt momentan disponibile. Astfel la fiecare pornire a aplicației, în funcție de conținutul fișierelor din directorul cu downloadurile parțiale se încearcă conectarea la hosturile care conțin fișierele respective și downloadarea acelor fișiere.

Aplicația GDownloader oferă posibilitatea de a opri un anumit transfer cu ajutorul opțiunii ‘Stop’ din meniul contextual asociat listei de transferuri, iar apoi de a-l reporni cu ajutorul opțiunii ‘Start’ din același meniu contextual. Totodată se poate anula definitiv (cancel) un anumit transfer cu ajutorul butonului ‘Cancel Download’ sau cu ajutorul opțiunii ‘Cancel’ din meniul contextual asociat listei de transferuri. Cu ajutorul butonului ‘Clear Completed’ se pot elimina toate downlodurile care au fost terminate (completate) .Aplicația GDownloader oferă utilizatorilor și posibilitatea de a executa local fișierele care au fost transferate și chiar fișierele de transfer parțial. Executarea fișierelor se poate face fie apăsând butonul ‘Run File’ fie cu ajutorul opțiunii ‘Run File’ din meniul contextual asociat listei de transferuri de fișiere.

Dacă se doresc mai multe informații în legătură cu un anumit download se poate afișa, cu ajutorul opțiuni ‘Properties’ din meniul contextual, fereastra de proprietăți a fiecărui fișier care se transfera.

Figura 4.16 : Fereastra de Proprietăți ale unui Download

În fereastra de proprietăți ale unui download sunt specificate: numele complet al fișierului care se transferă, dimensiunea acestuia, informația de hashing al acestuia (obținută cu SHA și care identifică același fișier pe mai multe host-uri), numărul de surse active care este numărul de surse de la care se transferă momentan, calea unde este salvat fișierul. Această cale este calea spre fișierul din directorul de downloaduri parțiale dacă transferul respectivului fișier nu s-a terminat, iar dacă transferul s-a terminat va fi calea spre fișierul din directorul unde se salvează downloadurile terminate. Această cale indică ce fișier va fi executat în cazul în care se apasă butonul ‘Run File’ din fereastra de transferuri (Traffic).

În cadrul acestei ferestre mai sunt afișate și numărul de host-uri pe care a fost găsit fișierul respectiv și o listă cu aceste host-uri, listă care conține următoarele informații :

Host – adresa de IP a host-ului respectiv.

Port – port-ul acelui host.

Speed – viteza de transfer specificata de acel nod, în Kilo Bytes per secunda.

Status – reprezintă starea transferului fișierului respectiv vis a vis de acea sursa.

Client – numele aplicației care rulează pe host-ul respectiv .

4.6. Browser-ul de Web

Aplicația Gdownloader suportă pe lângă căutarea de fișiere în rețeaua Gnutella și căutarea de informații pe web, căutare care se face cu ajutorul motorului de căutare Google [14]. Aplicația dispune de un browser de web propriu pentru a afișa rezultatele căutării cu motorul Google.

Figura 4.17 : Browser-ul de Web

Browser-ul de web al aplicației GDownloader a fost implementat cu ajutorul controlului COM (Component Object Model) pentru browsere, pus la dispoziție de Microsoft, acest control COM putând fi inserat cu ușurință și în aplicațiile .NET.

În cadrul acestui browser la implementarea căutării Google se folosește DHTML-ul (Dynamic HTML) pentru accesarea elementelor conținute de pagina motorului de căutare Google.

Dynamic HTML (DHTML) [15, 16] este un set de caracteristici inovatoare care da posibilitatea dezvoltatorilor de pagini web să modifice dinamic conținutul și modul de afișare al unui document. Totodată DHTM-ul oferă posibilitatea autorilor de pagini web de a crea documente HTML (Hyper Text Markup Language) excepționale din punct de vedere vizual care să interacționeze cu utilizatorul. Aceasta interacțiune cu utilizatorul făcându-se doar cu o singura încărcare a paginii nefiind nevoie de o comunicație complicata cu scripturile de pe server sau folosirea unui set complicat de pagini HTML pentru atingerea anumitor efecte vizuale. Dynamic HTML nu este încă un standard al World Wide Web Consortium (W3C), el fiind deocamdată doar un ‘termen de marketing’ care este folosit de companiile Microsoft și Netscape pentru a descrie noile tehnologi pe care browserele de generația 4.x le suporta. DHTML este o combinație de tehnologi care fac paginile web să fie dinamice putând fi descris ca o combinație între : HTML 4.0, Style Sheets și JavaScript. Cu ajutorul DHTML-ului se poate foarte simplu : să se ascundă texte și imagini într-un document, să se animeze texte și imagini putând a muta independent orice element de la un punct de plecare la un punct de oprire urmărind o anumita traictorie, să se creeze un ceas (cronometru) care să facă automat o actualizare a paginii după un anumit interval de timp, să creeze un form și apoi să citească și să proceseze datele pe care utilizatorul le introduce în acel form, toate acestea doar cu o singura încărcare a paginii de web. DHTML-ul creează aceste efecte modificând documentul curent, iar apoi reformatându-l dinamic și afișând documentul pentru a observă schimbările. Folosind DHTML-ul nu este necesar a se reîncărca documentul sau să se încarce un document nou sau un server de la distanta să genereze un document nou, în loc folosind puterea de calcul locala pentru a calcula și a efectua schimbările. Mai mult DHTML-ul nu necesita suportul adițional al unor aplicații sau a anumitor controale pentru a efectua schimbările, el fiind de sine stătător folosind ‘stilurile’ (styles) și scripturile pentru procesarea ‘intrărilor’ utilizatorului și pentru manipularea directa a tag-urilor HTML, a atributelor, a stilurilor și a textelor într-un document.

Cu ajutorul librărie mshtml pusa la dispoziție de Microsoft, care oferă suport pentru DHTML, putem să accesăm și să modificam în mod dinamic conținutul unui document (pagina web) dintr-o aplicație .NET. în acest mod putând accesa elementele, cum ar fi butoanele și căsuțele de editare ale unei pagini web. Aruncând o privire succinta la codul sursa al paginii web de la google scoate la iveala elementele :

<input maxLength="256" size="55" name="q">

<input type=submit value="Google Search" name=btnG>

Astfel aceste 2 elemente vor fi accesate dinamic din aplicația Gdownloader, primul element numindu-se “q” și fiind căsuța de editare unde se introduce textul ce se dorește a fi căutat, iar cel de-al 2 lea element ‘btnG’ fiind chiar butonul de căutare ‘Google Search’, prin apăsarea căruia se pornește căutarea Google pe web. Foarte important de reținut este faptul ca accesarea dinamica a elementelor unei pagini web se poate face numai după ce aceasta pagina web a fost complet încărcata.

4.7. Fereastra de Preferințe (Preferences)

În aceasta secțiune se permite vizualizarea și setarea opțiunilor și preferințelor pentru aplicația GDownloader. La începutul fiecărei rulări a aplicației se încarcă fișierul de configurări ‘GDownloader.ini’ în care sunt salvate preferitele utilizatorului în legătura cu configurația aplicației. Astfel în acest fișier se salvează următoarele informații : id-ul clientului, care este un identificator unic ; dacă aplicația poate sau nu să devină super-nod ; dacă este după un firewall ; numărul minim și numărul maxim de conectări pe care aplicația să i-l mențină ; calea unde se vor salva fișierele download-ate ; calea unde se vor salva fișierele de download parțial ; numărul maxim de download-uri simultane ; dacă permite sau nu transferul simultan de la mai multe surse (multi-source download-ing) ; limitări în legătura cu rata de transfer.

Figura 4.18 : Fereastra de Preferințe (Prefernces)

Fereastra de preferințe conține 3 ‘tab-uri’: ‘Connection’, ‘Traffic’ și ‘Bandwidth’, unde pot fi vizualizate sau setate proprietăți în legătura cu conectarea, transferul și lățimea de banda.

În tab-ul ‘Connection’ se pot seta date în legătura cu posibilitatea aplicației de deveni ultrapeer, iar în cazul în care aceasta opțiune este validata trebuie introdus numărul maxim de noduri frunza care se pot conecta la acest nod. Numărul maxim de noduri frunza permis este de 1500 de noduri. Tot în acest tab se specifica numărul minim de conexiuni pe care aplicația să le tina când este în mod ultrapeer sau când este în mod frunza și numărul maxim de conexiuni la alte noduri ultrapeer pe care să le păstreze. Dacă aplicația s-a conectat la rețeaua Gnutella dar la un număr mai mic de noduri decât cel specificat în aceasta secțiune de configurare a aplicației la numărul minim de conexiuni, atunci respectivul utilizator nu poate face interoperări (căutări, transferuri) în rețeaua Gnutella până când numărul nodurilor la care aplicația a reușit să se conecteze este mai mare sau cel puțin egal cu cel specificat.

În tab-ul de ‘Traffic’ sunt prezentate entitățile care trebuie configurate pentru procesul de transfer de fișiere. Astfel trebuie specificate caile spre directoarele unde vor fi salvate download-urile finale și download-urile parțiale. Cele 2 butoane ‘Browse’ afișează un dialog de unde pot fi selectate cu ușurință directoarele unde se dorește a fi salvate fișierele care sunt transferate. Tot în acest tab se poate specifica numărul maxim de transferuri care se pot face simultan, dar și dezactivarea suportului pentru transferul de la surse multiple a unui fișier (multi-source download-ing), acest lucru fiind recomandat pentru sistemele care nu au o conexiune foarte buna la rețeaua Internet, cum ar fi spre exemplu calculatoarele conectate prin modem-uri.

Tab-ul de ‘Bandwidth’ conține specificații în legătura cu lățimea de banda. Astfel se poate introduce o limitare de transfer la download-ul de fișiere, dar totodată se poate specifica și o rata minima de transfer al fișierelor, renunțându-se la download-area fișierelor care au rata de transfer mai mica decât cea specificata.

4.8. Fereastra de Ajutor (Help)

În aceasta fereastra sunt prezentate informații despre program, versiunea aplicației, modul de distribuire al aplicației, data când a fost creata aplicația, dar și numele și adresa de e-mail a autorului pentru eventualele sugestii și informații cu privire la aplicația Gdownloader.

Figura 4.19 : Fereastra de Ajutor.

Fereastra de ajutor poate fi apelata din meniul ‘Help’ al aplicației prin selectarea opțiunii ‘About’ sau prin simpla apăsare a butonului ‘Help’ care se afla pe principalele ferestre de dialog din aplicația Gdownloader. Dacă utilizatorul va face click pe adresa de e-mail a autorului, atunci aplicația de mail care este configurata ca și default pe sistemul respectiv va porni și va crea un mesaj nou de e-mail cu adresa destinație specificata și cu subiectul ‘GDownloader’. Acest lucru se realizează prin pornirea unui nou proces și apelarea secvenței ‘mailto :’.

5. Punerea în Funcțiune și Rezultate Experimentale

5.1. Manual de Utilizare al Aplicației

Pentru pornirea aplicației se lansează programul ‘GDownloader.exe’ . Aceasta aplicație este configurata pe conectare automata (auto-connect), adică o data cu pornirea aplicației se va încerca conectarea la diferite noduri din rețeaua Gnutella. Dacă nu se dorește pe moment conectarea la rețeaua Gnutella, din meniul ‘File’ se poate selecta opțiunea de ‘Disconnect’ care realizează deconectarea aplicației de la rețea (în cazul în care s-a conectat) și oprește încercarea aplicației de a se conecta la alte noduri din rețea. Când se dorește reconectarea aplicației se poate selecta opțiunea ‘Connect’ din același meniu ‘File’ al aplicației.

În cazul în care aplicația s-a conectat la cel puțin un nod din rețeaua Gnutella se activează butonul de căutări (Search) de pe macheta de conexiuni (Connections) oferindu-se posibilitatea de a fi afișata fereastra de dialog aferenta procesului de căutare. în aceasta fereastra de dialog sunt disponibile 2 tipuri de căutări, căutare în rețeaua Gnutella și căutare Google pe web. în cazul în care se generează o căutarea în rețeaua Gnutella sunt afișate tot în cadrul acestei ferestre și rezultatele găsite la interogarea introdusa. Sunt oferite totodată posibilități de a transfera (download-a) fișierele găsite sau de vizualiza proprietățile acestor fișiere. Căutarea în rețeaua Gnutella se face după numele fișierelor sau după cuvinte care sunt conținute în numele acestor fișiere, oferindu-se și posibilitatea unei căutări mai avansate, după tipul fișierelor sau dimensiunea acestora. în cazul în care se dorește o căutare Google pe web se lansează browser-ul propriu de web al aplicației GDownloader afișând cu ajutorul motorului de căutare Google rezultatele la interogarea introdusa.

Aplicația oferă suport și pentru mangementul transferurilor de fișiere, acest management fiind accesibil prin apăsarea butonului ‘Traffic’, buton care se afla pe principalele ferestre de dialog din cadrul aplicației. Acest management al transferurilor oferă suport pentru oprirea și repornirea de transferuri de fișiere, executarea locala a fișierelor care se transfera și vizualizarea proprietăților acestor transferuri.

Pentru o funcționare optima a aplicației este necesar ca în directorul în care se afla aplicația să existe un fișier ‘WebCache.ini’ care să conțină adresele nodurilor din rețeaua Gnutella la care aplicația va încerca să se conecteze. Tot în acest director se afla și fișierul ‘GDownloader.ini’ în care sunt salvate preferințele aplicației GDownloader și unde sunt specificate informații de genul: numărul minim și numărul maxim de noduri la care aplicația să se conecteze și directoarele de download și dowanload parțial unde să salveze transferurile finale și cele parțiale de fișiere din rețeaua Gnutella.

5.2. Analiza Căutărilor în Rețeaua Gnutella

Analiza căutărilor în rețeaua Gnutella se face, cu ajutorul aplicației GDownloader, prin introducerea unor interogări și contabilizarea numărului de rezultate găsite pe parcursul a 20 de secunde. în funcție de tipul interogărilor folosite aceasta analiza cuprinde 5 cazuri :

căutare după 1 cuvânt ;

căutare după 2 cuvinte ;

căutare după 3 cuvinte ;

căutare după 3 cuvinte și tipul aplicației ;

căutare după 3 cuvinte, tipul aplicației și dimensiunea fișierelor.

Ca finalitate analiza căutărilor în rețeaua Gnutella are prezentarea unor grafice care au ca abscisa timpul măsurat în secunde și ca ordonata numărul de rezultate găsite la o anumită interogare.

5.2.1. Căutare după 1 Cuvânt

În Figura 5.1 este prezentat graficul căutării după cuvântul “Beethoven”. Numărul maxim de rezultate găsite în 20 de secunde în acest caz a fost de 1104 rezultate.

Figura 5.1: Căutare după “Beethoven”

5.2.2. Căutare după 2 Cuvinte

În Figura 5.2 este prezentat graficul căutării după cuvintele “Beethoven Moonlight”. Numărul maxim de rezultate găsite în 20 de secunde în acest caz a fost de 464 de rezultate.

Figura 5.2: Căutare după “Beethoven Moonlight”

5.2.3. Căutare după 3 Cuvinte

Figura 5.3 prezintă graficul căutării după “Beethoven Moonlight Sonata”. în acest caz în 20 de secunde au fost găsite un număr de 415 rezultate la interogarea introdusă.

Figura 5.3 : Căutare după ‘Beethoven Moonlight Sonata’

5.2.4. Căutare după 3 Cuvinte și tipul aplicației

În următoare figura, Figura 5.4, se prezintă cazul căutării după cuvintele “Beethoven Moonlight Sonata”, dar se pune și condiția ca tipul fișierelor găsite să fie audio. Fișierele audio includ extensiile : mp2, mp3, wav și wma. Numărul de rezultate găsite folosind acest tip de interogare în 20 de secunde a fost de 386.

Figura 5.4 : Căutare după ‘Beethoven Moolight Soanta’, fișiere de tip Audio

5.2.5. Căutare după 3 Cuvinte, tipul aplicației și dimensiunea fișierului

În Figura 5.5 este prezentat cazul căutării după ‘Beethoven Moonlight Sonata’, punându-se condițiile ca fișierul să fie de tip audio și dimensiunea acestuia să fie mai mare de 10 Mega Bytes.

Figura 5.5 : Căutare după ‘Beethoven Moonlight Sonata’, fișier de tip audio, dimensiune > 10 MB

Pentru un mai bun studiu comparativ și o relevanta cât mai mare a acestei analize a căutărilor în rețeaua Gnutella, în Figura 5.6, sunt prezentate toate tipurile de căutări în cadrul unui singur grafic.

Prin studierea acestui grafic se pot pune în evidenta 2 caracteristici de baza ale rețelei Gnutella :

timpul de răspuns al rețelei Gnutella este foarte bun, marea majoritate a rezultatelor, în toate cele 5 cazuri, fiind primite în primele 10 secunde de la inițierea interogării.

cu cât timpul de căutare este mai mare cu atât rezultatele unei interogări sunt mai relevante. Astfel în primele 11 secunde interogarea aferenta cazului 3, în care se face căutarea după 3 cuvinte a primit mai puține rezultate decât interogarea aferenta cazului 4 în care căutarea se face după 3 cuvinte și tipul aplicației. Doar după 11 secunde interogarea aferenta cazului 3 are mai multe rezultate decât interogarea aferenta cazului 4.

Aceste mici fluctuații a numerelor de rezultate găsite se datorează, în special, caracterului foarte dinamic al rețelei Gnutella, în care utilizatorii pot să între și să iese în orice moment.

Figura 5.6 : Grafic – Căutări

6. Concluzii

Multe din problemele ce pot să apară la partajarea datelor în rețelele P2P sunt legate de mecanismele de căutare și mecanismele se securitate. Problemele care pot să apară în mecanismul de căutare pot fi rezolvate prin furnizarea unei expresivități, și unei autonomi maxime cu cea mai buna eficiența, calitate a serviciilor și robustețe posibilă. Cheia în ce privește securitatea rețelelor P2P se afla în proiectarea unui mecanism care să asigure disponibilitatea, autentificarea informațiilor precum și acces la aceste informații.

În aceasta lucrare s-a prezentat o vedere generală în legătura cu principalele caracteristici ale rețelelor distribuite P2P (peer-to-peer) și în special al rețelei Gnutella, analizându-se cu precădere metodele de căutare și de rutare ale interogărilor în aceste rețele.

Așa cum a fost enunțat și în partea introductiva a acestei lucrări, scopul declarat a fost găsirea unei metode cât mai eficiente pentru procesarea și rutarea interogărilor într-o rețea distribuita P2P.

Alt scop al acestei lucrări a fost de a crea un client al rețelei P2P Gnutella, care să permită conectarea la noduri declarate ultrapeer și de căutarea de fișiere în aceasta rețea. Aplicația creata îi oferă totodată utilizatorului și posibilitatea de a transfera (download-a) din rețea fișierele găsite ca și rezultat la interogarea introdusa.

Cu ajutorul aplicației create s-au analizat apoi parametrii rețelei Gnutella studiindu-se timpii de răspuns ai acestei rețele la diferite interogări introduse.

Ca și perspectivă de dezvoltare a prezentului proiect poate fi specificată căutarea fișierelor nu numai după numele lor ci și după conținut sau meta-date. Genul acesta de aplicație este foarte actual în domeniul Semantic Web.

10. Anexe. Cod Sursa C#

About.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for About.

/// </summary>

public class About : System.Windows.Forms.Form

{

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.Label label4;

private PinkieControls.ButtonXP Ok;

private System.Windows.Forms.LinkLabel Email;

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Label label5;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public About()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(About));

this.label1 = new System.Windows.Forms.Label();

this.Ok = new PinkieControls.ButtonXP();

this.label2 = new System.Windows.Forms.Label();

this.label3 = new System.Windows.Forms.Label();

this.label4 = new System.Windows.Forms.Label();

this.Email = new System.Windows.Forms.LinkLabel();

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.label5 = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// label1

//

this.label1.Font = new System.Drawing.Font("Times New Roman", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label1.ForeColor = System.Drawing.Color.Red;

this.label1.Location = new System.Drawing.Point(154, 8);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(161, 24);

this.label1.TabIndex = 0;

this.label1.Text = "GDownloader";

this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter;

//

// Ok

//

this.Ok.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Ok.DefaultScheme = true;

this.Ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.Ok.Hint = "Ok Button";

this.Ok.Image = ((System.Drawing.Image)(resources.GetObject("Ok.Image")));

this.Ok.Location = new System.Drawing.Point(210, 152);

this.Ok.Name = "Ok";

this.Ok.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Ok.Size = new System.Drawing.Size(95, 30);

this.Ok.TabIndex = 1;

this.Ok.Text = "&Ok";

this.Ok.Click += new System.EventHandler(this.Ok_Click);

//

// label2

//

this.label2.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label2.Location = new System.Drawing.Point(80, 48);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(328, 24);

this.label2.TabIndex = 2;

this.label2.Text = "Designed and created by Bogdan Turlea.";

//

// label3

//

this.label3.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label3.Location = new System.Drawing.Point(80, 80);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(344, 23);

this.label3.TabIndex = 3;

this.label3.Text = "Copyright (c) 2004. All rights reserved.";

//

// label4

//

this.label4.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label4.Location = new System.Drawing.Point(80, 112);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(264, 23);

this.label4.TabIndex = 4;

this.label4.Text = "For informațion or suggestions: ";

//

// Email

//

this.Email.Font = new System.Drawing.Font("Times New Roman", 12.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.Email.Location = new System.Drawing.Point(320, 112);

this.Email.Name = "Email";

this.Email.Size = new System.Drawing.Size(224, 23);

this.Email.TabIndex = 5;

this.Email.TabStop = true;

this.Email.Text = "[anonimizat]";

this.Email.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.Email_LinkClicked);

//

// pictureBox1

//

this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));

this.pictureBox1.Location = new System.Drawing.Point(0, 56);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(72, 80);

this.pictureBox1.TabIndex = 6;

this.pictureBox1.TabStop = false;

//

// label5

//

this.label5.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label5.Location = new System.Drawing.Point(305, 16);

this.label5.Name = "label5";

this.label5.Size = new System.Drawing.Size(56, 16);

this.label5.TabIndex = 7;

this.label5.Text = "v. 1.0";

this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;

//

// About

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.Ok;

this.ClientSize = new System.Drawing.Size(514, 191);

this.Controls.Add(this.label5);

this.Controls.Add(this.pictureBox1);

this.Controls.Add(this.Email);

this.Controls.Add(this.label4);

this.Controls.Add(this.label3);

this.Controls.Add(this.label2);

this.Controls.Add(this.Ok);

this.Controls.Add(this.label1);

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MaximizeBox = false;

this.Name = "About";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;

this.Text = "About GDowloader";

this.ResumeLayout(false);

}

#endregion

private void Ok_Click(object sender, System.EventArgs e)

{

Dispose();

}

private void Email_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)

{

Email.LinkVisited = true;

System.Diagnostics.Process.Start("mailto:[anonimizat]?subject=GDownloader");

}

}

}

AddNode.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for AddNode.

/// </summary>

public class AddNode : System.Windows.Forms.Form

{

private bool button = false;

private System.Windows.Forms.GroupBox groupBox1;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.TextBox textBox2;

private PinkieControls.ButtonXP buttonNo;

private PinkieControls.ButtonXP buttonYes;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public AddNode()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(AddNode));

this.groupBox1 = new System.Windows.Forms.GroupBox();

this.textBox2 = new System.Windows.Forms.TextBox();

this.textBox1 = new System.Windows.Forms.TextBox();

this.label2 = new System.Windows.Forms.Label();

this.label1 = new System.Windows.Forms.Label();

this.buttonNo = new PinkieControls.ButtonXP();

this.buttonYes = new PinkieControls.ButtonXP();

this.groupBox1.SuspendLayout();

this.SuspendLayout();

//

// groupBox1

//

this.groupBox1.Controls.Add(this.textBox2);

this.groupBox1.Controls.Add(this.textBox1);

this.groupBox1.Controls.Add(this.label2);

this.groupBox1.Controls.Add(this.label1);

this.groupBox1.Location = new System.Drawing.Point(27, 24);

this.groupBox1.Name = "groupBox1";

this.groupBox1.Size = new System.Drawing.Size(206, 120);

this.groupBox1.TabIndex = 0;

this.groupBox1.TabStop = false;

this.groupBox1.Text = "Add Node To Connect";

//

// textBox2

//

this.textBox2.Location = new System.Drawing.Point(72, 73);

this.textBox2.Name = "textBox2";

this.textBox2.Size = new System.Drawing.Size(120, 20);

this.textBox2.TabIndex = 3;

this.textBox2.Text = "";

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(72, 33);

this.textBox1.Name = "textBox1";

this.textBox1.Size = new System.Drawing.Size(120, 20);

this.textBox1.TabIndex = 2;

this.textBox1.Text = "";

//

// label2

//

this.label2.Location = new System.Drawing.Point(24, 72);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(40, 23);

this.label2.TabIndex = 1;

this.label2.Text = "Port:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label1

//

this.label1.Location = new System.Drawing.Point(8, 32);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(56, 23);

this.label1.TabIndex = 0;

this.label1.Text = "Address:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// buttonNo

//

this.buttonNo.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonNo.DefaultScheme = true;

this.buttonNo.DialogResult = System.Windows.Forms.DialogResult.No;

this.buttonNo.Hint = "No button";

this.buttonNo.Image = ((System.Drawing.Image)(resources.GetObject("buttonNo.Image")));

this.buttonNo.Location = new System.Drawing.Point(25, 160);

this.buttonNo.Name = "buttonNo";

this.buttonNo.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonNo.Size = new System.Drawing.Size(95, 30);

this.buttonNo.TabIndex = 2;

this.buttonNo.Text = "&No";

this.buttonNo.Click += new System.EventHandler(this.buttonNo_Click);

//

// buttonYes

//

this.buttonYes.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonYes.DefaultScheme = true;

this.buttonYes.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonYes.Hint = "Yes button";

this.buttonYes.Image = ((System.Drawing.Image)(resources.GetObject("buttonYes.Image")));

this.buttonYes.Location = new System.Drawing.Point(137, 160);

this.buttonYes.Name = "buttonYes";

this.buttonYes.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonYes.Size = new System.Drawing.Size(95, 30);

this.buttonYes.TabIndex = 3;

this.buttonYes.Text = "&Yes";

this.buttonYes.Click += new System.EventHandler(this.buttonYes_Click);

//

// AddNode

//

this.AcceptButton = this.buttonYes;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.buttonNo;

this.ClientSize = new System.Drawing.Size(258, 215);

this.Controls.Add(this.buttonNo);

this.Controls.Add(this.buttonYes);

this.Controls.Add(this.groupBox1);

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MaximizeBox = false;

this.Name = "AddNode";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "GDownloader";

this.groupBox1.ResumeLayout(false);

this.ResumeLayout(false);

}

#endregion

private void buttonYes_Click(object sender, System.EventArgs e)

{

if (textBox1.Text == null || textBox1.Text.Trim().Equals(""))

{

MessageBox.Show(this, "Address field can not be empty!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

try

{

Int32.Parse(textBox2.Text);

}

catch (Exception ex)

{

MessageBox.Show(this, "Port must be a number!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

ex.GetType();

return;

}

button = true;

this.Close();

}

private void buttonNo_Click(object sender, System.EventArgs e)

{

button = false;

}

public bool getButton()

{

return button;

}

public String Address

{

get

{

return textBox1.Text;

}

}

public int Port

{

get

{

return Int32.Parse(textBox2.Text);

}

}

}

}

ApplicationType.cs

using System;

using System.Collections;

namespace GDownloader

{

/// <summary>

///

/// </summary>

public class ApplicationType

{

private ArrayList Audio;

private ArrayList Video;

private ArrayList Picture;

private ArrayList Document;

private ArrayList Compressed ;

public ApplicationType()

{

InițializeExtensionsLists();

}

private void InițializeExtensionsLists()

{

Audio = new ArrayList();

Audio.Add("mp2");

Audio.Add("mp3");

Audio.Add("wav");

Audio.Add("wma");

Video = new ArrayList();

Video.Add("asf");

Video.Add("avi");

Video.Add("divx");

Video.Add("m1v");

Video.Add("m2v");

Video.Add("mov");

Video.Add("mpe");

Video.Add("mpeg");

Video.Add("mpg");

Video.Add("mp2v");

Video.Add("mpv2");

Video.Add("qt");

Video.Add("wmv");

Picture = new ArrayList();

Picture.Add("bmp");

Picture.Add("gif");

Picture.Add("iff");

Picture.Add("jpeg");

Picture.Add("jpg");

Picture.Add("pcx");

Picture.Add("png");

Picture.Add("psd");

Picture.Add("ras");

Picture.Add("rsb");

Picture.Add("sgi");

Picture.Add("tga");

Picture.Add("tiff");

Document = new ArrayList();

Document.Add("chm");

Document.Add("doc");

Document.Add("pdf");

Document.Add("ppt");

Document.Add("rtf");

Document.Add("txt");

Compressed = new ArrayList();

Compressed.Add("ace");

Compressed.Add("arj");

Compressed.Add("bz2");

Compressed.Add("cab");

Compressed.Add("gz");

Compressed.Add("lha");

Compressed.Add("rar");

Compressed.Add("tar");

Compressed.Add("uha");

Compressed.Add("zip");

}

public ArrayList getAudioExtensionsSupported()

{

return Audio;

}

public ArrayList getVideoExtensionsSupported()

{

return Video;

}

public ArrayList getPictureExtensionsSupported()

{

return Picture;

}

public ArrayList getDocumentExtensionsSupported()

{

return Document;

}

public ArrayList getCompressedExtensionsSupported()

{

return Compressed;

}

// checks if ext string is contained in the known extensions supported by the application

public string getMedia(String ext)

{

if (Audio.Contains(ext))

return "Audio";

if (Video.Contains(ext))

return "Video";

if (Picture.Contains(ext))

return "Picture";

if (Document.Contains(ext))

return "Document";

if (Compressed.Contains(ext))

return "Compressed";

if (ext.Equals("exe") || ext.Equals("com") || ext.Equals("bat"))

return "Executable";

return "-";

}

}

}

Confirm.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for Confirm.

/// </summary>

public class Confirm : System.Windows.Forms.Form

{

private PinkieControls.ButtonXP buttonYes;

private PinkieControls.ButtonXP buttonNo;

private System.Windows.Forms.Label label1;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private bool button;

public Confirm()

{

button = false;

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Confirm));

this.buttonYes = new PinkieControls.ButtonXP();

this.buttonNo = new PinkieControls.ButtonXP();

this.label1 = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// buttonYes

//

this.buttonYes.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonYes.DefaultScheme = true;

this.buttonYes.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonYes.Hint = "Yes button";

this.buttonYes.Image = ((System.Drawing.Image)(resources.GetObject("buttonYes.Image")));

this.buttonYes.Location = new System.Drawing.Point(189, 88);

this.buttonYes.Name = "buttonYes";

this.buttonYes.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonYes.Size = new System.Drawing.Size(95, 30);

this.buttonYes.TabIndex = 1;

this.buttonYes.Text = "&Yes";

this.buttonYes.Click += new System.EventHandler(this.buttonYes_Click);

//

// buttonNo

//

this.buttonNo.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonNo.DefaultScheme = true;

this.buttonNo.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.buttonNo.Hint = "No button";

this.buttonNo.Image = ((System.Drawing.Image)(resources.GetObject("buttonNo.Image")));

this.buttonNo.Location = new System.Drawing.Point(77, 88);

this.buttonNo.Name = "buttonNo";

this.buttonNo.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonNo.Size = new System.Drawing.Size(95, 30);

this.buttonNo.TabIndex = 0;

this.buttonNo.Text = "&No";

//

// label1

//

this.label1.Font = new System.Drawing.Font("Times New Roman", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label1.Location = new System.Drawing.Point(16, 32);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(328, 23);

this.label1.TabIndex = 2;

this.label1.Text = "Are you sure you want to quit GDownloader?";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;

//

// Confirm

//

this.AcceptButton = this.buttonYes;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.buttonNo;

this.ClientSize = new System.Drawing.Size(360, 125);

this.Controls.Add(this.label1);

this.Controls.Add(this.buttonNo);

this.Controls.Add(this.buttonYes);

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MaximizeBox = false;

this.Name = "Confirm";

this.ShowInTaskbar = false;

this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;

this.Text = "GDownloader";

this.ResumeLayout(false);

}

#endregion

private void buttonYes_Click(object sender, System.EventArgs e)

{

button = true;

this.Close();

}

public bool getButton()

{

return button;

}

}

}

Connections.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Net;

namespace GDownloader

{

/// <summary>

/// Summary description for Connections.

/// </summary>

public class Connections : System.Windows.Forms.Form

{

private bool ascending;

public MainForm parent;

private GnucDNA.Network DnaNet;

private Hashtable nodeHash;

private Hashtable nodeList;

private AddNode addNodeDlg;

private About aboutDlg;

private Confirm confirmDlg;

private NodeProperties propertiesDlg;

private System.Windows.Forms.Label label1;

private PinkieControls.ButtonXP buttonHelp;

private PinkieControls.ButtonXP Remove;

private PinkieControls.ButtonXP buttonExit;

private PinkieControls.ButtonXP buttonTraffic;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.ListView listViewConnecting;

private System.Windows.Forms.ColumnHeader Node;

private System.Windows.Forms.ColumnHeader Status;

private System.Windows.Forms.ListView listViewConnected;

private System.Windows.Forms.ColumnHeader columnHeader1;

private System.Windows.Forms.ColumnHeader columnHeader2;

private System.Windows.Forms.ColumnHeader columnHeader3;

private System.Windows.Forms.ColumnHeader columnHeader4;

private System.Windows.Forms.ColumnHeader columnHeader5;

private System.Windows.Forms.ColumnHeader columnHeader6;

private System.Windows.Forms.Timer timer1;

private PinkieControls.ButtonXP Search;

private PinkieControls.ButtonXP buttonConnections;

private System.Windows.Forms.ContextMenu contextMenu1;

private System.Windows.Forms.MenuItem menuRemoveNode;

private System.Windows.Forms.MenuItem menuItem1;

private System.Windows.Forms.ColumnHeader Port;

private System.Windows.Forms.ColumnHeader columnHeader7;

private PinkieControls.ButtonXP buttonXP1;

private PinkieControls.ButtonXP buttonXP2;

private PinkieControls.ButtonXP buttonAdd;

private System.ComponentModel.IContainer components;

public Connections()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

ascending = true;

nodeHash = new Hashtable();

nodeList = new Hashtable();

}

public void InițializeConnection()

{

DnaNet = parent.getDnaNetwork();

DnaNet.OnChange += new GnucDNA._INetworkEvent_OnChangeEventHandler(DnaNet_OnChange);

DnaNet.ForceUltrapeer(false);

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

this.components = new System.ComponentModel.Container();

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Connections));

this.label1 = new System.Windows.Forms.Label();

this.buttonHelp = new PinkieControls.ButtonXP();

this.Remove = new PinkieControls.ButtonXP();

this.buttonExit = new PinkieControls.ButtonXP();

this.buttonTraffic = new PinkieControls.ButtonXP();

this.Search = new PinkieControls.ButtonXP();

this.label2 = new System.Windows.Forms.Label();

this.label3 = new System.Windows.Forms.Label();

this.listViewConnecting = new System.Windows.Forms.ListView();

this.Node = new System.Windows.Forms.ColumnHeader();

this.Port = new System.Windows.Forms.ColumnHeader();

this.Status = new System.Windows.Forms.ColumnHeader();

this.listViewConnected = new System.Windows.Forms.ListView();

this.columnHeader1 = new System.Windows.Forms.ColumnHeader();

this.columnHeader7 = new System.Windows.Forms.ColumnHeader();

this.columnHeader2 = new System.Windows.Forms.ColumnHeader();

this.columnHeader3 = new System.Windows.Forms.ColumnHeader();

this.columnHeader4 = new System.Windows.Forms.ColumnHeader();

this.columnHeader5 = new System.Windows.Forms.ColumnHeader();

this.columnHeader6 = new System.Windows.Forms.ColumnHeader();

this.contextMenu1 = new System.Windows.Forms.ContextMenu();

this.menuRemoveNode = new System.Windows.Forms.MenuItem();

this.menuItem1 = new System.Windows.Forms.MenuItem();

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.buttonConnections = new PinkieControls.ButtonXP();

this.buttonXP1 = new PinkieControls.ButtonXP();

this.buttonXP2 = new PinkieControls.ButtonXP();

this.buttonAdd = new PinkieControls.ButtonXP();

this.SuspendLayout();

//

// label1

//

this.label1.BackColor = System.Drawing.SystemColors.Control;

this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label1.Location = new System.Drawing.Point(16, 16);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(352, 32);

this.label1.TabIndex = 12;

this.label1.Text = "Connecting to Gnutella";

//

// buttonHelp

//

this.buttonHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonHelp.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonHelp.DefaultScheme = false;

this.buttonHelp.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonHelp.Hint = "GDownloader Help";

this.buttonHelp.Image = ((System.Drawing.Image)(resources.GetObject("buttonHelp.Image")));

this.buttonHelp.Location = new System.Drawing.Point(608, 618);

this.buttonHelp.Name = "buttonHelp";

this.buttonHelp.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonHelp.Size = new System.Drawing.Size(95, 30);

this.buttonHelp.TabIndex = 12;

this.buttonHelp.Text = "&Help";

this.buttonHelp.Click += new System.EventHandler(this.buttonHelp_Click);

//

// Remove

//

this.Remove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.Remove.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Remove.DefaultScheme = false;

this.Remove.DialogResult = System.Windows.Forms.DialogResult.None;

this.Remove.Enabled = false;

this.Remove.Hint = "Removes the selected nodes from the connected nodes list";

this.Remove.Location = new System.Drawing.Point(264, 562);

this.Remove.Name = "Remove";

this.Remove.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Remove.Size = new System.Drawing.Size(95, 30);

this.Remove.TabIndex = 10;

this.Remove.Text = "&Remove Node";

this.Remove.Click += new System.EventHandler(this.Remove_Click);

//

// buttonExit

//

this.buttonExit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonExit.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonExit.DefaultScheme = false;

this.buttonExit.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.buttonExit.Hint = "Exit GDownloader";

this.buttonExit.Image = ((System.Drawing.Image)(resources.GetObject("buttonExit.Image")));

this.buttonExit.Location = new System.Drawing.Point(732, 618);

this.buttonExit.Name = "buttonExit";

this.buttonExit.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonExit.Size = new System.Drawing.Size(95, 30);

this.buttonExit.TabIndex = 11;

this.buttonExit.Text = "&Exit";

this.buttonExit.Click += new System.EventHandler(this.buttonExit_Click);

//

// buttonTraffic

//

this.buttonTraffic.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonTraffic.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonTraffic.DefaultScheme = false;

this.buttonTraffic.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonTraffic.Enabled = false;

this.buttonTraffic.Hint = "Shows Traffic Dialog";

this.buttonTraffic.Image = ((System.Drawing.Image)(resources.GetObject("buttonTraffic.Image")));

this.buttonTraffic.Location = new System.Drawing.Point(264, 618);

this.buttonTraffic.Name = "buttonTraffic";

this.buttonTraffic.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonTraffic.Size = new System.Drawing.Size(95, 30);

this.buttonTraffic.TabIndex = 14;

this.buttonTraffic.Text = "&Traffic";

this.buttonTraffic.Click += new System.EventHandler(this.buttonTraffic_Click);

//

// Search

//

this.Search.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;

this.Search.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.Search.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Search.DefaultScheme = true;

this.Search.DialogResult = System.Windows.Forms.DialogResult.None;

this.Search.Enabled = false;

this.Search.Hint = "Shows Search Dialog";

this.Search.Image = ((System.Drawing.Image)(resources.GetObject("Search.Image")));

this.Search.Location = new System.Drawing.Point(140, 618);

this.Search.Name = "Search";

this.Search.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Search.Size = new System.Drawing.Size(95, 30);

this.Search.TabIndex = 13;

this.Search.Text = "&Search";

this.Search.Click += new System.EventHandler(this.Search_Click);

//

// label2

//

this.label2.Location = new System.Drawing.Point(264, 56);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(128, 16);

this.label2.TabIndex = 6;

this.label2.Text = "Connected Nodes:";

//

// label3

//

this.label3.Location = new System.Drawing.Point(16, 56);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(100, 16);

this.label3.TabIndex = 7;

this.label3.Text = "Trying To Connect:";

//

// listViewConnecting

//

this.listViewConnecting.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)));

this.listViewConnecting.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;

this.listViewConnecting.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {

this.Node,

this.Port,

this.Status});

this.listViewConnecting.FullRowSelect = true;

this.listViewConnecting.Location = new System.Drawing.Point(16, 80);

this.listViewConnecting.Name = "listViewConnecting";

this.listViewConnecting.Size = new System.Drawing.Size(224, 474);

this.listViewConnecting.TabIndex = 3;

this.listViewConnecting.View = System.Windows.Forms.View.Details;

//

// Node

//

this.Node.Text = "Node";

this.Node.Width = 90;

//

// Port

//

this.Port.Text = "Port";

this.Port.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Port.Width = 50;

//

// Status

//

this.Status.Text = "Status";

this.Status.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Status.Width = 80;

//

// listViewConnected

//

this.listViewConnected.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.listViewConnected.BackColor = System.Drawing.SystemColors.ActiveCaptionText;

this.listViewConnected.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;

this.listViewConnected.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {

this.columnHeader1,

this.columnHeader7,

this.columnHeader2,

this.columnHeader3,

this.columnHeader4,

this.columnHeader5,

this.columnHeader6});

this.listViewConnected.ContextMenu = this.contextMenu1;

this.listViewConnected.FullRowSelect = true;

this.listViewConnected.Location = new System.Drawing.Point(264, 80);

this.listViewConnected.Name = "listViewConnected";

this.listViewConnected.Size = new System.Drawing.Size(568, 474);

this.listViewConnected.TabIndex = 4;

this.listViewConnected.View = System.Windows.Forms.View.Details;

this.listViewConnected.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listViewConnected_KeyDown);

this.listViewConnected.DoubleClick += new System.EventHandler(this.listViewConnected_DoubleClick);

this.listViewConnected.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewConnected_ColumnClick);

//

// columnHeader1

//

this.columnHeader1.Text = "Node";

this.columnHeader1.Width = 160;

//

// columnHeader7

//

this.columnHeader7.Text = "Port";

this.columnHeader7.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

//

// columnHeader2

//

this.columnHeader2.Text = "Type";

this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader2.Width = 100;

//

// columnHeader3

//

this.columnHeader3.Text = "Bandwidth";

this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader3.Width = 115;

//

// columnHeader4

//

this.columnHeader4.Text = "Client";

this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader4.Width = 160;

//

// columnHeader5

//

this.columnHeader5.Text = "Up Time";

this.columnHeader5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader5.Width = 113;

//

// columnHeader6

//

this.columnHeader6.Text = "Efficiency";

this.columnHeader6.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader6.Width = 103;

//

// contextMenu1

//

this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.menuRemoveNode,

this.menuItem1});

//

// menuRemoveNode

//

this.menuRemoveNode.Index = 0;

this.menuRemoveNode.Text = "Remove Node";

this.menuRemoveNode.Click += new System.EventHandler(this.menuRemoveNode_Click);

//

// menuItem1

//

this.menuItem1.Index = 1;

this.menuItem1.Text = "Properties";

this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);

//

// timer1

//

this.timer1.Enabled = true;

this.timer1.Interval = 1000;

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

//

// buttonConnections

//

this.buttonConnections.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonConnections.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonConnections.DefaultScheme = false;

this.buttonConnections.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonConnections.Enabled = false;

this.buttonConnections.Hint = "Shows Connections Dialog";

this.buttonConnections.Image = ((System.Drawing.Image)(resources.GetObject("buttonConnections.Image")));

this.buttonConnections.Location = new System.Drawing.Point(16, 618);

this.buttonConnections.Name = "buttonConnections";

this.buttonConnections.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonConnections.Size = new System.Drawing.Size(95, 30);

this.buttonConnections.TabIndex = 17;

this.buttonConnections.Text = "&Connections";

//

// buttonXP1

//

this.buttonXP1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonXP1.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonXP1.DefaultScheme = false;

this.buttonXP1.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonXP1.Enabled = false;

this.buttonXP1.Hint = "Removes the selected nodes from the connected nodes list";

this.buttonXP1.Location = new System.Drawing.Point(264, 562);

this.buttonXP1.Name = "buttonXP1";

this.buttonXP1.Scheme = PinkieControls.ButtonXP.Schemes.Blue;

this.buttonXP1.Size = new System.Drawing.Size(95, 30);

this.buttonXP1.TabIndex = 10;

this.buttonXP1.Text = "&Remove Node";

//

// buttonXP2

//

this.buttonXP2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonXP2.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonXP2.DefaultScheme = false;

this.buttonXP2.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonXP2.Enabled = false;

this.buttonXP2.Hint = "Shows Connections Dialog";

this.buttonXP2.Image = ((System.Drawing.Image)(resources.GetObject("buttonXP2.Image")));

this.buttonXP2.Location = new System.Drawing.Point(16, 618);

this.buttonXP2.Name = "buttonXP2";

this.buttonXP2.Scheme = PinkieControls.ButtonXP.Schemes.Blue;

this.buttonXP2.Size = new System.Drawing.Size(95, 30);

this.buttonXP2.TabIndex = 17;

this.buttonXP2.Text = "&Connections";

//

// buttonAdd

//

this.buttonAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonAdd.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonAdd.DefaultScheme = false;

this.buttonAdd.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonAdd.Hint = "Adds a node to connect to";

this.buttonAdd.Image = ((System.Drawing.Image)(resources.GetObject("buttonAdd.Image")));

this.buttonAdd.Location = new System.Drawing.Point(140, 562);

this.buttonAdd.Name = "buttonAdd";

this.buttonAdd.RightToLeft = System.Windows.Forms.RightToLeft.No;

this.buttonAdd.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonAdd.Size = new System.Drawing.Size(95, 30);

this.buttonAdd.TabIndex = 23;

this.buttonAdd.Text = "&Add Node";

this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);

//

// Connections

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(848, 663);

this.Controls.Add(this.buttonAdd);

this.Controls.Add(this.buttonConnections);

this.Controls.Add(this.label1);

this.Controls.Add(this.buttonHelp);

this.Controls.Add(this.listViewConnected);

this.Controls.Add(this.listViewConnecting);

this.Controls.Add(this.label3);

this.Controls.Add(this.buttonExit);

this.Controls.Add(this.Remove);

this.Controls.Add(this.Search);

this.Controls.Add(this.label2);

this.Controls.Add(this.buttonTraffic);

this.Controls.Add(this.buttonXP1);

this.Controls.Add(this.buttonXP2);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(630, 300);

this.Name = "Connections";

this.Text = "Connections";

this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

this.Closing += new System.ComponentModel.CancelEventHandler(this.Connections_Closing);

this.ResumeLayout(false);

}

#endregion

#region User Interface

private void Search_Click(object sender, System.EventArgs e)

{

parent.showSearchDlg();

}

private void Remove_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewConnected.SelectedItems.GetEnumerator();

ListViewItem item1 = null;

bool hasElements = false;

while (enumerator.MoveNext())

{

hasElements = true;

item1 = (ListViewItem)enumerator.Current;

DnaNet.RemoveNode((int)item1.Tag);

nodeList.Remove(item1.Tag);

item1.Remove();

}

if (!hasElements)

MessageBox.Show(this, "You must first select a node from the Connected Nodes list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

private void buttonExit_Click(object sender, System.EventArgs e)

{

confirmDlg = new Confirm();

confirmDlg.ShowDialog(this);

if (confirmDlg.getButton())

{

Application.Exit();

}

}

private void buttonHelp_Click(object sender, System.EventArgs e)

{

aboutDlg = new About();

aboutDlg.ShowDialog();

}

private void buttonTraffic_Click(object sender, System.EventArgs e)

{

parent.showTrafficDlg();

}

private void listViewConnected_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)

{

ascending = !ascending;

listViewConnected.ListViewItemSorter = new ListViewItemComparer(e.Column, ascending, false);

listViewConnected.Sort();

}

private void listViewConnected_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

if (e.KeyValue == 46)

Remove_Click(null, null);

}

// Remove Node clicked from the context menu associated with Connected Nodes List

private void menuRemoveNode_Click(object sender, System.EventArgs e)

{

Remove_Click(null, null);

}

private void listViewConnected_DoubleClick(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewConnected.SelectedItems.GetEnumerator();

ListViewItem item1 = null;

bool hasElements = false;

if (enumerator.MoveNext())

{

item1 = (ListViewItem)enumerator.Current;

IPAddress ipaddr = new IPAddress(DnaNet.GetNodeIP((int)item1.Tag));

String hostName = "";

int mode = DnaNet.GetNodeMode((int)item1.Tag);

string nodeType = "";

switch ( mode )

{

case 1:

nodeType = "Normal";

break;

case 2:

nodeType = "Ultrapeer";

break;

case 3:

nodeType = "Leaf";

break;

default:

nodeType = "Unknown";

break;

}

try

{

hostName = Dns.GetHostByAddress(ipaddr).HostName;

}

catch (Exception ex)

{

hostName = "Unable to resolve the host name. " + ex.Message;

}

propertiesDlg = new NodeProperties();

propertiesDlg.IP = ipaddr.ToString();

propertiesDlg.Port = DnaNet.GetNodePort((int)item1.Tag).ToString();

propertiesDlg.Host = hostName;

propertiesDlg.Type = nodeType;

propertiesDlg.TimeConnected = DnaNet.GetNodeConnectTime((int)item1.Tag).ToString();

propertiesDlg.HandShake = DnaNet.GetNodeHandshake((int)item1.Tag);

propertiesDlg.ShowDialog();

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a node from the Connected Nodes list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

// Properties clicked from the context menu associated with Connected Nodes List

private void menuItem1_Click(object sender, System.EventArgs e)

{

listViewConnected_DoubleClick(null, null);

}

// button Add Node clicked

private void buttonAdd_Click(object sender, System.EventArgs e)

{

addNodeDlg = new AddNode();

addNodeDlg.ShowDialog();

if (addNodeDlg.getButton())

{

// adds a node to connect to

DnaNet.ConnectNode2(addNodeDlg.Address, addNodeDlg.Port, 1);

}

}

#endregion

#region INetwork Events

private void DnaNet_OnChange(int NodeId)

{

string nodeState;

string nodeType;

ListViewItem item1;

ListViewItem item2;

long nbrNodes = DnaNet.GetNormalConnectedCount();

long state = DnaNet.GetNodeState(NodeId);

long port = DnaNet.GetNodePort(NodeId);

long ip = DnaNet.GetNodeIP(NodeId);

long mode = DnaNet.GetNodeMode(NodeId);

if ( ip == 0 || port == 0 )

return;

IPAddress ipaddr = new IPAddress(ip);

// string host = ipaddr.ToString() + ":" + port.ToString();

string host = ipaddr.ToString();

switch ( state )

{

case 0:

nodeState = "Unknown";

break;

case 1:

nodeState = "Connecting…";

break;

case 2:

nodeState = "Connected";

break;

case 3:

nodeState = "Disconnected";

break;

default:

nodeState = "?";

break;

}

switch ( mode )

{

case 1:

nodeType = "Normal";

break;

case 2:

nodeType = "Ultrapeer";

break;

case 3:

nodeType = "Leaf";

break;

default:

nodeType = "Unknown";

break;

}

if ( nodeList.Contains(NodeId) )

{

item1 = (ListViewItem)nodeList[NodeId];

if ( state == 3 )

{

item1.Remove();

for (int i = 0; i<listViewConnected.Items.Count; i++)

if (listViewConnected.Items[i].Tag.Equals(NodeId))

listViewConnected.Items.RemoveAt(i);

nodeList.Remove(NodeId);

}

if ( state == 2 && mode == 2)

{

double bw = (double)(DnaNet.GetNodeBytesUp(NodeId) + DnaNet.GetNodeBytesDown(NodeId)) / 1024;

string msg = bw.ToString("F") + " KB/s";

DateTime dt = DnaNet.GetNodeConnectTime(NodeId);

TimeSpan up = DateTime.Now.Subtract(dt);

string uptime = "";

int good = 0, total = 0;

float efficiency = 0;

if ( up.Days > 0 )

uptime = up.Days + "d " + up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Hours > 0 )

uptime = up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Minutes > 0 )

uptime = up.Minutes + "m " + up.Seconds + "s";

else

uptime = up.Seconds + "s";

DnaNet.GetNodePacketsTotal(NodeId, ref good, ref total);

if (total != 0)

efficiency = ((float)good / total) * 100 ;

item1.Remove();

item2 = new ListViewItem(host);

item2.Tag = NodeId;

item2.SubItems.Add(port.ToString());

item2.SubItems.Add(nodeType);

item2.SubItems.Add(msg);

item2.SubItems.Add(DnaNet.GetNodeAgent(NodeId));

item2.SubItems.Add(uptime);

item2.SubItems.Add(efficiency.ToString("n") + "%");

listViewConnected.Items.Add(item2);

}

}

else

{

if ( state < 2 )

{

item1 = new ListViewItem(host);

item1.Tag = NodeId;

item1.SubItems.Add(port.ToString());

item1.SubItems.Add(nodeState);

listViewConnecting.Items.Add(item1);

nodeList.Add(NodeId,item1);

}

if ( state == 2 && mode == 2)

{

double bw = (double)(DnaNet.GetNodeBytesUp(NodeId) + DnaNet.GetNodeBytesDown(NodeId)) / 1024;

string msg = bw.ToString("F") + " KB/s";

DateTime dt = DnaNet.GetNodeConnectTime(NodeId);

TimeSpan up = DateTime.Now.Subtract(dt);

string uptime = "";

int good = 0, total = 0;

float efficiency = 0;

if ( up.Days > 0 )

uptime = up.Days + "d " + up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Hours > 0 )

uptime = up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Minutes > 0 )

uptime = up.Minutes + "m " + up.Seconds + "s";

else

uptime = up.Seconds + "s";

DnaNet.GetNodePacketsTotal(NodeId, ref good, ref total);

if (total != 0)

efficiency = ((float)good / total) * 100 ;

item2 = new ListViewItem(host);

item2.Tag = NodeId;

item2.SubItems.Add(port.ToString());

item2.SubItems.Add(nodeType);

item2.SubItems.Add(msg);

item2.SubItems.Add(DnaNet.GetNodeAgent(NodeId));

item2.SubItems.Add(uptime);

item2.SubItems.Add(efficiency.ToString("n") + "%");

listViewConnected.Items.Add(item2);

nodeList.Add(NodeId,item2);

}

}

}

#endregion

public void Disconnect()

{

nodeList.Clear();

listViewConnected.Items.Clear();

}

private void timer1_Tick(object sender, System.EventArgs e)

{

long nbrNodes = 0;

if (DnaNet != null)

nbrNodes = DnaNet.GetNormalConnectedCount();

else

return;

if ( parent.getDnaCore().IsConnecting() && nbrNodes == 0 )

{

label1.Text = "Connecting to Gnutella";

// dealing with Remove button

Remove.Enabled = false;

}

else

if ( parent.getDnaCore().IsConnecting() )

{

label1.Text = "Connected to Gnutella Network";

// dealing with Remove button

Remove.Enabled = true;

}

else

{

// when Disconnect was clicked and is not trying to connect

// dealing Remove button

Remove.Enabled = false;

}

if ( parent.connectedReady )

{

// dealing with Search and Traffic buttons

Search.Enabled = true;

buttonTraffic.Enabled = true;

}

else

{

// dealing with Search and Traffic buttons

Search.Enabled = false;

buttonTraffic.Enabled = false;

}

int NodeId;

int state;

string msg;

DateTime dt;

TimeSpan up;

double bw;

string uptime = "";

int good = 0, total = 0;

float efficiency = 0;

for ( int i = 0; i < listViewConnected.Items.Count; i++ )

{

NodeId = (int)listViewConnected.Items[i].Tag;

state = DnaNet.GetNodeState(NodeId);

if ( state == 2 )

{

bw = (double)(DnaNet.GetNodeBytesUp(NodeId) + DnaNet.GetNodeBytesDown(NodeId)) / 1024;

msg = bw.ToString("F") + " KB/s";

dt = DnaNet.GetNodeConnectTime(NodeId);

up = DateTime.Now.Subtract(dt);

uptime = "";

if ( up.Days > 0 )

uptime = up.Days + "d " + up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Hours > 0 )

uptime = up.Hours + "h " + up.Minutes + "m " + up.Seconds + "s";

else if ( up.Minutes > 0 )

uptime = up.Minutes + "m " + up.Seconds + "s";

else

uptime = up.Seconds + "s";

DnaNet.GetNodePacketsTotal(NodeId, ref good, ref total);

if (total != 0)

efficiency = ((float)good / total) * 100 ;

listViewConnected.Items[i].SubItems[3].Text = msg;

listViewConnected.Items[i].SubItems[4].Text = DnaNet.GetNodeAgent(NodeId);

listViewConnected.Items[i].SubItems[5].Text = uptime;

listViewConnected.Items[i].SubItems[6].Text = efficiency.ToString("n") + "%";

}

}

}

private void Connections_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

if (parent.searchResultDlg != null)

parent.searchResultDlg.Close();

if (parent.trafficDlg != null)

parent.trafficDlg.Close();

parent.getDnaCore().Disconnect();

parent.searchResultDlg = null;

parent.connectionsDlg = null;

DnaNet.OnChange -= new GnucDNA._INetworkEvent_OnChangeEventHandler(DnaNet_OnChange);

DnaNet = null;

}

}

}

FileProperties.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Net;

namespace GDownloader

{

/// <summary>

/// Summary description for FileProperties.

/// </summary>

public class FileProperties : System.Windows.Forms.Form

{

public GnucDNA.Search DnaSearch;

public int currentSearchId;

public int resultId;

private Service service;

private PinkieControls.ButtonXP Ok;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.Label label4;

private System.Windows.Forms.ColumnHeader Host;

private System.Windows.Forms.ColumnHeader Port;

private System.Windows.Forms.ColumnHeader Speed;

private System.Windows.Forms.ColumnHeader Hops;

private System.Windows.Forms.ColumnHeader Properties;

private System.Windows.Forms.ColumnHeader Client;

private System.Windows.Forms.ListView listViewHosts;

private System.Windows.Forms.ColumnHeader Stable;

private System.Windows.Forms.ColumnHeader FreeSlots;

private System.Windows.Forms.Label labelName;

private System.Windows.Forms.Label labelSize;

private System.Windows.Forms.Label labelHash;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public FileProperties()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

service = new Service();

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(FileProperties));

this.Ok = new PinkieControls.ButtonXP();

this.label1 = new System.Windows.Forms.Label();

this.label2 = new System.Windows.Forms.Label();

this.label3 = new System.Windows.Forms.Label();

this.label4 = new System.Windows.Forms.Label();

this.listViewHosts = new System.Windows.Forms.ListView();

this.Host = new System.Windows.Forms.ColumnHeader();

this.Port = new System.Windows.Forms.ColumnHeader();

this.Hops = new System.Windows.Forms.ColumnHeader();

this.Speed = new System.Windows.Forms.ColumnHeader();

this.FreeSlots = new System.Windows.Forms.ColumnHeader();

this.Stable = new System.Windows.Forms.ColumnHeader();

this.Properties = new System.Windows.Forms.ColumnHeader();

this.Client = new System.Windows.Forms.ColumnHeader();

this.labelName = new System.Windows.Forms.Label();

this.labelSize = new System.Windows.Forms.Label();

this.labelHash = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// Ok

//

this.Ok.Anchor = System.Windows.Forms.AnchorStyles.Bottom;

this.Ok.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Ok.DefaultScheme = true;

this.Ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.Ok.Hint = "Ok Button";

this.Ok.Image = ((System.Drawing.Image)(resources.GetObject("Ok.Image")));

this.Ok.Location = new System.Drawing.Point(228, 344);

this.Ok.Name = "Ok";

this.Ok.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Ok.Size = new System.Drawing.Size(95, 30);

this.Ok.TabIndex = 7;

this.Ok.Text = "&Ok";

//

// label1

//

this.label1.Location = new System.Drawing.Point(20, 24);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(40, 23);

this.label1.TabIndex = 8;

this.label1.Text = "Name:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label2

//

this.label2.Location = new System.Drawing.Point(20, 51);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(32, 23);

this.label2.TabIndex = 9;

this.label2.Text = "Size:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label3

//

this.label3.Location = new System.Drawing.Point(20, 78);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(40, 23);

this.label3.TabIndex = 10;

this.label3.Text = "Hash:";

this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label4

//

this.label4.Location = new System.Drawing.Point(20, 105);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(200, 23);

this.label4.TabIndex = 14;

this.label4.Text = "Found ";

this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// listViewHosts

//

this.listViewHosts.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.listViewHosts.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {

this.Host,

this.Port,

this.Hops,

this.Speed,

this.FreeSlots,

this.Stable,

this.Properties,

this.Client});

this.listViewHosts.FullRowSelect = true;

this.listViewHosts.Location = new System.Drawing.Point(20, 129);

this.listViewHosts.Name = "listViewHosts";

this.listViewHosts.Size = new System.Drawing.Size(520, 199);

this.listViewHosts.TabIndex = 15;

this.listViewHosts.View = System.Windows.Forms.View.Details;

//

// Host

//

this.Host.Text = "Host";

this.Host.Width = 100;

//

// Port

//

this.Port.Text = "Port";

this.Port.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

//

// Hops

//

this.Hops.Text = "Hops";

this.Hops.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

//

// Speed

//

this.Speed.Text = "Speed";

this.Speed.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

//

// FreeSlots

//

this.FreeSlots.Text = "Free Slots";

this.FreeSlots.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.FreeSlots.Width = 80;

//

// Stable

//

this.Stable.Text = "Stable";

this.Stable.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

//

// Properties

//

this.Properties.Text = "Properties";

this.Properties.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Properties.Width = 100;

//

// Client

//

this.Client.Text = "Client";

this.Client.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Client.Width = 100;

//

// labelName

//

this.labelName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelName.Location = new System.Drawing.Point(60, 24);

this.labelName.Name = "labelName";

this.labelName.Size = new System.Drawing.Size(464, 23);

this.labelName.TabIndex = 16;

this.labelName.Text = "labelName";

this.labelName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelSize

//

this.labelSize.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelSize.Location = new System.Drawing.Point(60, 51);

this.labelSize.Name = "labelSize";

this.labelSize.Size = new System.Drawing.Size(464, 23);

this.labelSize.TabIndex = 17;

this.labelSize.Text = "labelSize";

this.labelSize.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelHash

//

this.labelHash.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelHash.Location = new System.Drawing.Point(60, 78);

this.labelHash.Name = "labelHash";

this.labelHash.Size = new System.Drawing.Size(464, 23);

this.labelHash.TabIndex = 18;

this.labelHash.Text = "labelHash";

this.labelHash.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// FileProperties

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(560, 389);

this.Controls.Add(this.labelHash);

this.Controls.Add(this.labelSize);

this.Controls.Add(this.labelName);

this.Controls.Add(this.listViewHosts);

this.Controls.Add(this.label4);

this.Controls.Add(this.label3);

this.Controls.Add(this.label2);

this.Controls.Add(this.label1);

this.Controls.Add(this.Ok);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(250, 300);

this.Name = "FileProperties";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "File Properties";

this.ResumeLayout(false);

}

#endregion

public void inițializeItemValues()

{

labelName.Text = DnaSearch.GetResultName(currentSearchId, resultId);

labelSize.Text = service.formatSize(DnaSearch.GetResultSize(currentSearchId, resultId));

labelHash.Text = DnaSearch.GetResultHash(currentSearchId, resultId, 0);

int[] hostId = (int[])DnaSearch.GetHostIDs(currentSearchId, resultId);

label4.Text = "Found on " + hostId.Length +" Host(s)";

IPAddress ipaddr = null;

ListViewItem item1 = null;

for (int i = 0; i < hostId.Length; i++)

{

ipaddr = new IPAddress(DnaSearch.GetHostIP(currentSearchId, resultId, hostId[i]));

item1 = new ListViewItem(ipaddr.ToString());

item1.Tag = hostId[i];

item1.SubItems.Add(DnaSearch.GetHostPort(currentSearchId, resultId, hostId[i]).ToString());

item1.SubItems.Add(DnaSearch.GetHostDistance(currentSearchId, resultId, hostId[i]).ToString());

item1.SubItems.Add(DnaSearch.GetHostSpeed(currentSearchId, resultId, hostId[i]).ToString() + "KB/s");

if ( DnaSearch.GetHostBusy(currentSearchId, resultId, hostId[i]) )

{

item1.SubItems.Add("No");

}

else

{

item1.SubItems.Add("Yes");

}

if ( DnaSearch.GetHostStable(currentSearchId, resultId, hostId[i]) )

{

item1.SubItems.Add("Yes");

}

else

{

item1.SubItems.Add("No");

}

if ( DnaSearch.GetHostFirewall(currentSearchId, resultId, hostId[i]) )

{

item1.SubItems.Add("Firewall");

}

else

{

item1.SubItems.Add("");

}

item1.SubItems.Add(DnaSearch.GetHostVendor(currentSearchId, resultId, hostId[i]));

listViewHosts.Items.Add(item1);

}

}

}

}

FilePropertiesTraffic.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Net;

namespace GDownloader

{

/// <summary>

/// Summary description for FilePropertiesTrafficcs.

/// </summary>

public class FilePropertiesTraffic : System.Windows.Forms.Form

{

public GnucDNA.Download DnaDownload;

public int downloadId;

private Hashtable sourceNodes;

private Service service;

private PinkieControls.ButtonXP Ok;

private System.Windows.Forms.Label labelHash;

private System.Windows.Forms.Label labelSize;

private System.Windows.Forms.Label labelName;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.ColumnHeader Host;

private System.Windows.Forms.ColumnHeader Port;

private System.Windows.Forms.ColumnHeader Speed;

private System.Windows.Forms.ColumnHeader Client;

private System.Windows.Forms.Label label4;

private System.Windows.Forms.Label label5;

private System.Windows.Forms.Label label6;

private System.Windows.Forms.Label labelActiveSources;

private System.Windows.Forms.Label labelFilePath;

private System.Windows.Forms.ColumnHeader Status;

private System.Windows.Forms.ListView listViewSources;

private System.Windows.Forms.Timer timer1;

private System.ComponentModel.IContainer components;

public FilePropertiesTraffic()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

service = new Service();

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

this.components = new System.ComponentModel.Container();

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(FilePropertiesTraffic));

this.Ok = new PinkieControls.ButtonXP();

this.labelHash = new System.Windows.Forms.Label();

this.labelSize = new System.Windows.Forms.Label();

this.labelName = new System.Windows.Forms.Label();

this.label3 = new System.Windows.Forms.Label();

this.label2 = new System.Windows.Forms.Label();

this.label1 = new System.Windows.Forms.Label();

this.listViewSources = new System.Windows.Forms.ListView();

this.Host = new System.Windows.Forms.ColumnHeader();

this.Port = new System.Windows.Forms.ColumnHeader();

this.Speed = new System.Windows.Forms.ColumnHeader();

this.Status = new System.Windows.Forms.ColumnHeader();

this.Client = new System.Windows.Forms.ColumnHeader();

this.label4 = new System.Windows.Forms.Label();

this.label5 = new System.Windows.Forms.Label();

this.label6 = new System.Windows.Forms.Label();

this.labelActiveSources = new System.Windows.Forms.Label();

this.labelFilePath = new System.Windows.Forms.Label();

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.SuspendLayout();

//

// Ok

//

this.Ok.Anchor = System.Windows.Forms.AnchorStyles.Bottom;

this.Ok.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Ok.DefaultScheme = true;

this.Ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.Ok.Hint = "Ok Button";

this.Ok.Image = ((System.Drawing.Image)(resources.GetObject("Ok.Image")));

this.Ok.Location = new System.Drawing.Point(233, 384);

this.Ok.Name = "Ok";

this.Ok.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Ok.Size = new System.Drawing.Size(95, 30);

this.Ok.TabIndex = 8;

this.Ok.Text = "&Ok";

//

// labelHash

//

this.labelHash.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelHash.Location = new System.Drawing.Point(56, 72);

this.labelHash.Name = "labelHash";

this.labelHash.Size = new System.Drawing.Size(488, 23);

this.labelHash.TabIndex = 24;

this.labelHash.Text = "labelHash";

this.labelHash.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelSize

//

this.labelSize.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelSize.Location = new System.Drawing.Point(56, 48);

this.labelSize.Name = "labelSize";

this.labelSize.Size = new System.Drawing.Size(488, 23);

this.labelSize.TabIndex = 23;

this.labelSize.Text = "labelSize";

this.labelSize.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelName

//

this.labelName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelName.Location = new System.Drawing.Point(56, 24);

this.labelName.Name = "labelName";

this.labelName.Size = new System.Drawing.Size(488, 23);

this.labelName.TabIndex = 22;

this.labelName.Text = "labelName";

this.labelName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label3

//

this.label3.Location = new System.Drawing.Point(16, 72);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(40, 23);

this.label3.TabIndex = 21;

this.label3.Text = "Hash:";

this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label2

//

this.label2.Location = new System.Drawing.Point(16, 48);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(32, 23);

this.label2.TabIndex = 20;

this.label2.Text = "Size:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label1

//

this.label1.Location = new System.Drawing.Point(16, 24);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(40, 23);

this.label1.TabIndex = 19;

this.label1.Text = "Name:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// listViewSources

//

this.listViewSources.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.listViewSources.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {

this.Host,

this.Port,

this.Speed,

this.Status,

this.Client});

this.listViewSources.FullRowSelect = true;

this.listViewSources.Location = new System.Drawing.Point(16, 168);

this.listViewSources.Name = "listViewSources";

this.listViewSources.Size = new System.Drawing.Size(520, 192);

this.listViewSources.TabIndex = 26;

this.listViewSources.View = System.Windows.Forms.View.Details;

//

// Host

//

this.Host.Text = "Host";

this.Host.Width = 120;

//

// Port

//

this.Port.Text = "Port";

this.Port.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Port.Width = 70;

//

// Speed

//

this.Speed.Text = "Speed";

this.Speed.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Speed.Width = 70;

//

// Status

//

this.Status.Text = "Status";

this.Status.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Status.Width = 160;

//

// Client

//

this.Client.Text = "Client";

this.Client.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.Client.Width = 120;

//

// label4

//

this.label4.Location = new System.Drawing.Point(16, 144);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(200, 23);

this.label4.TabIndex = 25;

this.label4.Text = "Found ";

this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label5

//

this.label5.Location = new System.Drawing.Point(16, 96);

this.label5.Name = "label5";

this.label5.Size = new System.Drawing.Size(88, 23);

this.label5.TabIndex = 27;

this.label5.Text = "Active sources:";

this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// label6

//

this.label6.Location = new System.Drawing.Point(16, 120);

this.label6.Name = "label6";

this.label6.Size = new System.Drawing.Size(56, 23);

this.label6.TabIndex = 28;

this.label6.Text = "File path:";

this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelActiveSources

//

this.labelActiveSources.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelActiveSources.Location = new System.Drawing.Point(96, 96);

this.labelActiveSources.Name = "labelActiveSources";

this.labelActiveSources.Size = new System.Drawing.Size(448, 23);

this.labelActiveSources.TabIndex = 29;

this.labelActiveSources.Text = "labelActiveSources";

this.labelActiveSources.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// labelFilePath

//

this.labelFilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.labelFilePath.Location = new System.Drawing.Point(72, 120);

this.labelFilePath.Name = "labelFilePath";

this.labelFilePath.Size = new System.Drawing.Size(472, 23);

this.labelFilePath.TabIndex = 30;

this.labelFilePath.Text = "labelFilePath";

this.labelFilePath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// timer1

//

this.timer1.Enabled = true;

this.timer1.Interval = 1000;

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

//

// FilePropertiesTraffic

//

this.AcceptButton = this.Ok;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.Ok;

this.ClientSize = new System.Drawing.Size(560, 429);

this.Controls.Add(this.labelFilePath);

this.Controls.Add(this.labelActiveSources);

this.Controls.Add(this.label6);

this.Controls.Add(this.label5);

this.Controls.Add(this.listViewSources);

this.Controls.Add(this.label4);

this.Controls.Add(this.labelHash);

this.Controls.Add(this.labelSize);

this.Controls.Add(this.labelName);

this.Controls.Add(this.label3);

this.Controls.Add(this.label2);

this.Controls.Add(this.label1);

this.Controls.Add(this.Ok);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(250, 300);

this.Name = "FilePropertiesTraffic";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "File Properties";

this.Closing += new System.ComponentModel.CancelEventHandler(this.FilePropertiesTraffic_Closing);

this.ResumeLayout(false);

}

#endregion

public void inițializeItemValues()

{

sourceNodes = new Hashtable();

labelName.Text = DnaDownload.GetName(downloadId);

labelSize.Text = service.formatSize(DnaDownload.GetFileLength(downloadId));

labelHash.Text = DnaDownload.GetHash(downloadId, 0);

labelActiveSources.Text = DnaDownload.GetActiveSourceCount(downloadId).ToString();

labelFilePath.Text = DnaDownload.GetFilePath(downloadId);

int[] sourceId = (int[])DnaDownload.GetSourceIDs(downloadId);

label4.Text = "Found on " + sourceId.Length +" Host(s)";

IPAddress ipaddr = null;

ListViewItem item1 = null;

for (int i = 0; i < sourceId.Length; i++)

{

ipaddr = new IPAddress(DnaDownload.GetSourceIP(downloadId, sourceId[i]));

item1 = new ListViewItem(ipaddr.ToString());

item1.Tag = sourceId[i];

item1.SubItems.Add(DnaDownload.GetSourcePort(downloadId, sourceId[i]).ToString());

item1.SubItems.Add(DnaDownload.GetSourceSpeed(downloadId, sourceId[i]).ToString() + "KB/s");

item1.SubItems.Add(DnaDownload.GetSourceStatusStr(downloadId, sourceId[i]));

item1.SubItems.Add(DnaDownload.GetSourceVendor(downloadId, sourceId[i]));

listViewSources.Items.Add(item1);

sourceNodes.Add(item1.Tag, item1);

}

}

public void updateItemValues()

{

if (DnaDownload == null)

{

return;

}

labelActiveSources.Text = DnaDownload.GetActiveSourceCount(downloadId).ToString();

int[] sourceId = (int[])DnaDownload.GetSourceIDs(downloadId);

label4.Text = "Found on " + sourceId.Length +" Host(s)";

IPAddress ipaddr = null;

ListViewItem item1 = null;

for (int i = 0; i < sourceId.Length; i++)

{

if (sourceNodes.ContainsKey(sourceId[i]))

{

item1 = (ListViewItem)sourceNodes[sourceId[i]];

item1.SubItems[3].Text = DnaDownload.GetSourceStatusStr(downloadId, sourceId[i]);

}

else

{

ipaddr = new IPAddress(DnaDownload.GetSourceIP(downloadId, sourceId[i]));

item1 = new ListViewItem(ipaddr.ToString());

item1.Tag = sourceId[i];

item1.SubItems.Add(DnaDownload.GetSourcePort(downloadId, sourceId[i]).ToString());

item1.SubItems.Add(DnaDownload.GetSourceSpeed(downloadId, sourceId[i]).ToString() + "KB/s");

item1.SubItems.Add(DnaDownload.GetSourceStatusStr(downloadId, sourceId[i]));

item1.SubItems.Add(DnaDownload.GetSourceVendor(downloadId, sourceId[i]));

listViewSources.Items.Add(item1);

sourceNodes.Add(item1.Tag, item1);

}

}

}

private void timer1_Tick(object sender, System.EventArgs e)

{

updateItemValues();

}

private void FilePropertiesTraffic_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

DnaDownload = null;

timer1.Enabled = false;

}

}

}

ListViewComparer.cs

using System;

using System.Windows.Forms;

using System.Collections;

namespace GDownloader

{

/// <summary>

///

/// </summary>

class ListViewItemComparer : IComparer

{

private int col;

private bool ascending;

private bool number;

public ListViewItemComparer()

{

col=0;

ascending = true;

number = false;

}

public ListViewItemComparer(int column, bool ascending, bool number)

{

col=column;

this.ascending = ascending;

this.number = number;

}

public int Compare(object x, object y)

{

string textX = ((ListViewItem)x).SubItems[col].Text;

string textY = ((ListViewItem)y).SubItems[col].Text;

if (number)

if (ascending)

return Int32.Parse(textX).CompareTo(Int32.Parse(textY));

else

return Int32.Parse(textY).CompareTo(Int32.Parse(textX));

if (ascending)

return String.Compare(textX, textY);

return String.Compare(textY, textX);

}

}

}

MainForm.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Diagnostics;

using System.Runtime.InteropServices;

using GnucDNA;

using PinkieControls;

using System.IO;

namespace GDownloader

{

/// <summary>

/// Summary description for MainForm.

/// </summary>

public class MainForm : System.Windows.Forms.Form

{

public SearchResult searchResultDlg;

public Connections connectionsDlg;

public Traffic trafficDlg;

private Preferences prefDlg;

private About aboutDlg;

private Confirm confirmDlg;

public bool connected;

public bool connectedReady;

private GnucDNA.Core DnaCore;

private GnucDNA.Cache DnaCache;

private GnucDNA.Prefs DnaPrefs;

private GnucDNA.Network DnaNet;

private GnucDNA.Search DnaSearch;

private GnucDNA.Download DnaDownload;

private System.Windows.Forms.MainMenu mainMenu1;

private System.Windows.Forms.MenuItem File;

private System.Windows.Forms.MenuItem Help;

private System.Windows.Forms.MenuItem About;

private System.Windows.Forms.MenuItem Exit;

private System.Windows.Forms.Timer timer1;

private System.Windows.Forms.StatusBar statusBar1;

private System.Windows.Forms.StatusBarPanel statusBarPanel1;

private System.Windows.Forms.StatusBarPanel statusBarPanel2;

private System.Windows.Forms.StatusBarPanel statusBarPanel3;

private System.Windows.Forms.MenuItem menuItem1;

private System.Windows.Forms.MenuItem menuItem2;

private System.Windows.Forms.MenuItem menuItem3;

private System.Windows.Forms.MenuItem menuItem4;

private System.Windows.Forms.MenuItem menuItem5;

private System.Windows.Forms.MenuItem menuItem8;

private System.Windows.Forms.MenuItem menuItem6;

private System.Windows.Forms.MenuItem menuItem7;

private System.ComponentModel.IContainer components;

public MainForm()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

DnaCore = new GnucDNA.Core();

DnaPrefs = (GnucDNA.Prefs)DnaCore.GetIPrefs();

DnaCache = (GnucDNA.Cache)DnaCore.GetICache();

DnaNet = (GnucDNA.Network)DnaCore.GetINetwork();

DnaSearch = (GnucDNA.Search)DnaCore.GetISearch();

DnaDownload = (GnucDNA.Download)DnaCore.GetIDownload();

string version = DnaCore.GetCoreVersion();

int intver = System.Convert.ToInt32(version.Replace(".",""));

if ( intver < 906 )

{

MessageBox.Show("Wrong version (" + version + ") of GnucDNA found!","GnucDNA Version Error. Please update your GnucDNA!");

Application.Exit();

}

DnaCore.ClientCode = "GD";

DnaCore.ClientName = "GDownloader";

DnaCore.ClientVersion = "1.0";

if ( System.IO.File.Exists(Application.StartupPath + "\\GDownloader.ini") )

{

DnaPrefs.LoadConfig(Application.StartupPath + "\\GDownloader.ini");

}

else

{

MessageBox.Show(DnaPrefs.DownloadPath);

DnaPrefs.SuperNodeAble = true;

DnaPrefs.LeafModeConnects = 1;

DnaPrefs.MinConnects = 1;

DnaPrefs.MaxConnects = 20;

int index = DnaPrefs.PartialsDir.LastIndexOf("\\Partials");

if (DnaPrefs.PartialsDir[index – 1] == '\\')

{

DnaPrefs.PartialsDir = DnaPrefs.PartialsDir.Remove(index – 1, 1);

}

index = DnaPrefs.DownloadPath.LastIndexOf("\\Downloads");

if (DnaPrefs.DownloadPath[index – 1] == '\\')

{

DnaPrefs.DownloadPath = DnaPrefs.DownloadPath.Remove(index – 1, 1);

}

MessageBox.Show(DnaPrefs.DownloadPath);

}

if ( System.IO.File.Exists(Application.StartupPath + "\\WebCache.ini") )

{

DnaCache.LoadWebCache(Application.StartupPath + "\\WebCache.ini");

}

if ( DnaCache.GetWebCacheSize() == 0 )

{

DnaCache.AddWebCache("http://www.gnucleus.net/gcache/gcache.php");

DnaCache.AddWebCache("http://gwebcache.jonatkins.com/cgi-bin/gwebcache.cgi");

DnaCache.AddWebCache("http://corky.net/gcache/gcache.php");

}

DnaCore.Connect();

searchResultDlg = null;

// opens the Connections dialog

connectionsDlg = new Connections();

connectionsDlg.MdiParent = this;

connectionsDlg.parent = this;

connectionsDlg.InițializeConnection();

connectionsDlg.Show();

connected = false;

connectedReady = false;

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

this.components = new System.ComponentModel.Container();

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(MainForm));

this.mainMenu1 = new System.Windows.Forms.MainMenu();

this.File = new System.Windows.Forms.MenuItem();

this.menuItem6 = new System.Windows.Forms.MenuItem();

this.menuItem5 = new System.Windows.Forms.MenuItem();

this.menuItem7 = new System.Windows.Forms.MenuItem();

this.Exit = new System.Windows.Forms.MenuItem();

this.menuItem1 = new System.Windows.Forms.MenuItem();

this.menuItem2 = new System.Windows.Forms.MenuItem();

this.menuItem3 = new System.Windows.Forms.MenuItem();

this.menuItem4 = new System.Windows.Forms.MenuItem();

this.menuItem8 = new System.Windows.Forms.MenuItem();

this.Help = new System.Windows.Forms.MenuItem();

this.About = new System.Windows.Forms.MenuItem();

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.statusBar1 = new System.Windows.Forms.StatusBar();

this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();

this.statusBarPanel2 = new System.Windows.Forms.StatusBarPanel();

this.statusBarPanel3 = new System.Windows.Forms.StatusBarPanel();

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel1)).BeginInit();

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel2)).BeginInit();

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel3)).BeginInit();

this.SuspendLayout();

//

// mainMenu1

//

this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.File,

this.menuItem1,

this.menuItem8,

this.Help});

//

// File

//

this.File.Index = 0;

this.File.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.menuItem6,

this.menuItem5,

this.menuItem7,

this.Exit});

this.File.Text = "&File";

//

// menuItem6

//

this.menuItem6.Index = 0;

this.menuItem6.Text = "Connect";

this.menuItem6.Click += new System.EventHandler(this.menuItem6_Click);

//

// menuItem5

//

this.menuItem5.Index = 1;

this.menuItem5.Text = "Disconnect";

this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);

//

// menuItem7

//

this.menuItem7.Index = 2;

this.menuItem7.Text = "Preferences";

this.menuItem7.Click += new System.EventHandler(this.menuItem7_Click);

//

// Exit

//

this.Exit.Index = 3;

this.Exit.Text = "&Exit";

this.Exit.Click += new System.EventHandler(this.Exit_Click);

//

// menuItem1

//

this.menuItem1.Index = 1;

this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.menuItem2,

this.menuItem3,

this.menuItem4});

this.menuItem1.Text = "&View";

//

// menuItem2

//

this.menuItem2.Index = 0;

this.menuItem2.Text = "&Connections";

this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);

//

// menuItem3

//

this.menuItem3.Index = 1;

this.menuItem3.Text = "&Search";

this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);

//

// menuItem4

//

this.menuItem4.Index = 2;

this.menuItem4.Text = "&Traffic";

this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);

//

// menuItem8

//

this.menuItem8.Index = 2;

this.menuItem8.MdiList = true;

this.menuItem8.Text = "&Window";

//

// Help

//

this.Help.Index = 3;

this.Help.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.About});

this.Help.Text = "&Help";

//

// About

//

this.About.Index = 0;

this.About.Text = "&About";

this.About.Click += new System.EventHandler(this.About_Click);

//

// timer1

//

this.timer1.Enabled = true;

this.timer1.Interval = 1000;

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

//

// statusBar1

//

this.statusBar1.Location = new System.Drawing.Point(0, 675);

this.statusBar1.Name = "statusBar1";

this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {

this.statusBarPanel1,

this.statusBarPanel2,

this.statusBarPanel3});

this.statusBar1.ShowPanels = true;

this.statusBar1.Size = new System.Drawing.Size(870, 24);

this.statusBar1.TabIndex = 5;

this.statusBar1.Text = "statusBar1";

//

// statusBarPanel1

//

this.statusBarPanel1.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;

this.statusBarPanel1.Text = "statusBarPanel1";

this.statusBarPanel1.Width = 454;

//

// statusBarPanel2

//

this.statusBarPanel2.Alignment = System.Windows.Forms.HorizontalAlignment.Center;

this.statusBarPanel2.Text = "statusBarPanel2";

this.statusBarPanel2.Width = 200;

//

// statusBarPanel3

//

this.statusBarPanel3.Alignment = System.Windows.Forms.HorizontalAlignment.Center;

this.statusBarPanel3.Text = "statusBarPanel3";

this.statusBarPanel3.Width = 200;

//

// MainForm

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.SystemColors.HighlightText;

this.ClientSize = new System.Drawing.Size(870, 699);

this.Controls.Add(this.statusBar1);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.IsMdiContainer = true;

this.Menu = this.mainMenu1;

this.MinimumSize = new System.Drawing.Size(620, 350);

this.Name = "MainForm";

this.Text = "GDowloader by Bogdan Turlea";

this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing);

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel1)).EndInit();

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel2)).EndInit();

((System.ComponentModel.ISupportInițialize)(this.statusBarPanel3)).EndInit();

this.ResumeLayout(false);

}

#endregion

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.Run(new MainForm());

}

#region User Interface

private void Exit_Click(object sender, System.EventArgs e)

{

confirmDlg = new Confirm();

confirmDlg.ShowDialog(this);

if (confirmDlg.getButton())

Application.Exit();

}

private void About_Click(object sender, System.EventArgs e)

{

aboutDlg = new About();

aboutDlg.ShowDialog();

}

// Disconnect clicked from File menu

private void menuItem5_Click(object sender, System.EventArgs e)

{

DnaCore.Disconnect();

if (searchResultDlg != null)

{

searchResultDlg.Disconnect();

}

if (connectionsDlg != null)

{

connectionsDlg.Disconnect();

}

statusBar1.Panels[0].Text = "Disconnected";

statusBar1.Panels[1].Text = "Receive Rate: 0.00 KB/s";

statusBar1.Panels[2].Text = "Send Rate: 0.00 KB/s";

// dealig with Disconnect from File menu

menuItem5.Enabled = false;

// dealig with Connect from File menu

menuItem6.Enabled = true;

// dealig with Connections from View menu

menuItem2.Enabled = false;

// dealig with Search from View menu

menuItem3.Enabled = false;

// dealig with Traffic from View menu

menuItem4.Enabled = false;

connected = false;

}

// Connect clicked from File menu

private void menuItem6_Click(object sender, System.EventArgs e)

{

if (connectionsDlg == null)

{

connectionsDlg = new Connections();

connectionsDlg.MdiParent = this;

connectionsDlg.parent = this;

connectionsDlg.InițializeConnection();

connectionsDlg.Show();

}

DnaCore.Connect();

}

// Connections clicked from View menu

private void menuItem2_Click(object sender, System.EventArgs e)

{

showConnectionsDlg();

}

// Search clicked from View menu

private void menuItem3_Click(object sender, System.EventArgs e)

{

showSearchDlg();

}

// Traffic clicked from View menu

private void menuItem4_Click(object sender, System.EventArgs e)

{

showTrafficDlg();

}

// Preferences clicked from File menu

private void menuItem7_Click(object sender, System.EventArgs e)

{

prefDlg = new Preferences();

prefDlg.parent = this;

prefDlg.inițializeItemValues();

prefDlg.ShowDialog();

}

#endregion

private void timer1_Tick(object sender, System.EventArgs e)

{

double ul;

double dl;

long nbrNodes = 0;

nbrNodes = DnaNet.GetNormalConnectedCount();

ul = (double)DnaCore.GetBytesPerSecUp() / 1024;

dl = (double)DnaCore.GetBytesPerSecDown() / 1024;

if ( DnaNet.ClientMode2(1) == 2)

{

//client mode = ultrapper

if ( nbrNodes >= DnaPrefs.MinConnects )

{

connectedReady = true;

}

else

{

connectedReady = false;

}

}

else

{

//client mode = leaf

if ( nbrNodes >= DnaPrefs.LeafModeConnects )

{

connectedReady = true;

}

else

{

connectedReady = false;

}

}

if (connectedReady)

{

// dealing with Search from View menu

menuItem3.Enabled = true;

// dealing with Traffic from View menu

menuItem4.Enabled = true;

}

else

{

// dealing with Search from View menu

menuItem3.Enabled = false;

// dealing with Traffic from View menu

menuItem4.Enabled = false;

}

if (connectionsDlg == null)

{

statusBar1.Panels[0].Text = "Disconnected";

statusBar1.Panels[1].Text = "Receive Rate: 0.00 KB/s";

statusBar1.Panels[2].Text = "Send Rate: 0.00 KB/s";

// dealing with Connections from View menu

menuItem2.Enabled = false;

// dealing with Disconnect from File menu

menuItem5.Enabled = false;

// dealing with Connect from File menu

menuItem6.Enabled = true;

connected = false;

return;

}

if ( DnaCore.IsConnecting() && nbrNodes == 0 )

{

statusBar1.Panels[0].Text = "Connecting…";

// dealing with Connections from View menu

menuItem2.Enabled = true;

// dealing with Disconnect from File menu

menuItem5.Enabled = false;

// dealing with Connect from File menu

menuItem6.Enabled = false;

connected = false;

}

else if ( DnaCore.IsConnecting() )

{

statusBar1.Panels[0].Text ="Connected to " + nbrNodes + " Nodes";

// dealing with Connections from View menu

menuItem2.Enabled = true;

// dealing with Disconnect from File menu

menuItem5.Enabled = true;

// dealing with Connect from File menu

menuItem6.Enabled = false;

connected = true;

}

statusBar1.Panels[1].Text = "Receive Rate: " + dl.ToString("F") + " KB/s";

statusBar1.Panels[2].Text = "Send Rate: " + ul.ToString("F") + " KB/s";

}

private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

DnaCore.Disconnect();

DnaPrefs.SaveConfig(Application.StartupPath + "\\GDownloader.ini");

//DnaCache.SaveWebCache(Application.StartupPath + "\\WebCache.ini");

Marshal.ReleaseComObject(DnaCore);

DnaCore = null;

}

public GnucDNA.Core getDnaCore()

{

return DnaCore;

}

public GnucDNA.Network getDnaNetwork()

{

return DnaNet;

}

public GnucDNA.Search getDnaSearch()

{

return DnaSearch;

}

public GnucDNA.Download getDnaDownload()

{

return DnaDownload;

}

public GnucDNA.Prefs getDnaPrefs()

{

return DnaPrefs;

}

public void showConnectionsDlg()

{

connectionsDlg.Focus();

}

public void showSearchDlg()

{

if (searchResultDlg == null)

{

searchResultDlg = new SearchResult();

searchResultDlg.MdiParent = this;

searchResultDlg.parent = this;

searchResultDlg.InițializeSearch();

searchResultDlg.Show();

}

searchResultDlg.Focus();

}

public void showTrafficDlg()

{

if (trafficDlg == null)

{

trafficDlg = new Traffic();

trafficDlg.MdiParent = this;

trafficDlg.parent = this;

trafficDlg.InițializeDownload();

trafficDlg.Show();

}

trafficDlg.Focus();

}

}

}

MyProgressBar.cs

using System;

using System.Collections;

using System.ComponentModel;

using System.Drawing;

using System.Data;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for UserControl1.

/// </summary>

public class MyProgressBar : System.Windows.Forms.UserControl

{

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

private int min = 0; // Minimum value for progress range

private int max = 100; // Maximum value for progress range

private int val = 0; // Current progress

private Color BarColor = Color.Blue; // Color of progress meter

private Color textColor = Color.Black; // Color of the percent text

public MyProgressBar()

{

// This call is required by the Windows.Forms Form Designer.

InițializeComponent();

// TODO: Add any inițialization after the InitComponent call

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if( components != null )

components.Dispose();

}

base.Dispose( disposing );

}

#region Component Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

components = new System.ComponentModel.Container();

}

#endregion

protected override void OnResize(EventArgs e)

{

// Invalidate the control to get a repaint.

this.Invalidate();

}

protected override void OnPaint(PaintEventArgs e)

{

Graphics g = e.Graphics;

SolidBrush brush = new SolidBrush(BarColor);

float percent = (float)(val – min) / (float)(max – min);

Rectangle rect = this.ClientRectangle;

// Calculate area for drawing the progress.

rect.Width = (int)((float)rect.Width * percent);

// Draw the progress meter.

g.FillRectangle(brush, rect);

// dysplay percent string

string percentText = (percent*100).ToString() + "%";

g.DrawString(percentText, new Font("Microsoft Sans Serif", 8), new SolidBrush(textColor), (this.ClientRectangle.Left+this.ClientRectangle.Right)/2 – 13, (this.ClientRectangle.Top+this.ClientRectangle.Bottom)/2 – 7);

// Draw a three-dimensional border around the control.

Draw3DBorder(g);

// Clean up.

brush.Dispose();

g.Dispose();

}

public int Minimum

{

get

{

return min;

}

set

{

// Prevent a negative value.

if (value < 0)

{

min = 0;

}

// Make sure that the minimum value is never set higher than the maximum value.

if (value > max)

{

min = value;

min = value;

}

// Ensure value is still in range

if (val < min)

{

val = min;

}

// Invalidate the control to get a repaint.

this.Invalidate();

}

}

public Color TextColor

{

get

{

return textColor;

}

set

{

textColor = value;

}

}

public int Maximum

{

get

{

return max;

}

set

{

// Make sure that the maximum value is never set lower than the minimum value.

if (value < min)

{

min = value;

}

max = value;

// Make sure that value is still in range.

if (val > max)

{

val = max;

}

// Invalidate the control to get a repaint.

this.Invalidate();

}

}

public int Value

{

get

{

return val;

}

set

{

int oldValue = val;

// Make sure that the value does not stray outside the valid range.

if (value < min)

{

val = min;

}

else if (value > max)

{

val = max;

}

else

{

val = value;

}

this.Invalidate();

}

}

public Color ProgressBarColor

{

get

{

return BarColor;

}

set

{

BarColor = value;

// Invalidate the control to get a repaint.

this.Invalidate();

}

}

private void Draw3DBorder(Graphics g)

{

int PenWidth = (int)Pens.White.Width;

g.DrawLine(Pens.Black,

new Point(this.ClientRectangle.Left, this.ClientRectangle.Top),

new Point(this.ClientRectangle.Width – PenWidth, this.ClientRectangle.Top));

g.DrawLine(Pens.Black,

new Point(this.ClientRectangle.Left, this.ClientRectangle.Top),

new Point(this.ClientRectangle.Left, this.ClientRectangle.Height – PenWidth));

g.DrawLine(Pens.Black,

new Point(this.ClientRectangle.Left, this.ClientRectangle.Height – PenWidth),

new Point(this.ClientRectangle.Width – PenWidth, this.ClientRectangle.Height – PenWidth));

g.DrawLine(Pens.Black,

new Point(this.ClientRectangle.Width – PenWidth, this.ClientRectangle.Top),

new Point(this.ClientRectangle.Width – PenWidth, this.ClientRectangle.Height – PenWidth));

g.DrawLine(Pens.DarkGray,

new Point(this.ClientRectangle.Left + 1, this.ClientRectangle.Top + 1),

new Point(this.ClientRectangle.Width – PenWidth – 1, this.ClientRectangle.Top + 1));

g.DrawLine(Pens.DarkGray,

new Point(this.ClientRectangle.Left + 1, this.ClientRectangle.Top + 1),

new Point(this.ClientRectangle.Left + 1, this.ClientRectangle.Height – PenWidth – 1));

g.DrawLine(Pens.White,

new Point(this.ClientRectangle.Left + 1, this.ClientRectangle.Height – PenWidth – 1),

new Point(this.ClientRectangle.Width – PenWidth -1, this.ClientRectangle.Height – PenWidth – 1));

g.DrawLine(Pens.White,

new Point(this.ClientRectangle.Width – PenWidth – 1, this.ClientRectangle.Top + 1),

new Point(this.ClientRectangle.Width – PenWidth – 1, this.ClientRectangle.Height – PenWidth – 1));

}

}

}

NodeProperties.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for NodeProperties.

/// </summary>

public class NodeProperties : System.Windows.Forms.Form

{

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label3;

private PinkieControls.ButtonXP Ok;

private System.Windows.Forms.Label label4;

private System.Windows.Forms.Label label5;

private System.Windows.Forms.TextBox textBoxIP;

private System.Windows.Forms.TextBox textBoxPort;

private System.Windows.Forms.TextBox textBoxHost;

private System.Windows.Forms.TextBox textBoxTimeConnected;

private System.Windows.Forms.TextBox textBoxHandShake;

private System.Windows.Forms.Label label6;

private System.Windows.Forms.TextBox textBoxType;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public NodeProperties()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(NodeProperties));

this.label1 = new System.Windows.Forms.Label();

this.label2 = new System.Windows.Forms.Label();

this.label3 = new System.Windows.Forms.Label();

this.Ok = new PinkieControls.ButtonXP();

this.label4 = new System.Windows.Forms.Label();

this.label5 = new System.Windows.Forms.Label();

this.textBoxIP = new System.Windows.Forms.TextBox();

this.textBoxPort = new System.Windows.Forms.TextBox();

this.textBoxHost = new System.Windows.Forms.TextBox();

this.textBoxTimeConnected = new System.Windows.Forms.TextBox();

this.textBoxHandShake = new System.Windows.Forms.TextBox();

this.label6 = new System.Windows.Forms.Label();

this.textBoxType = new System.Windows.Forms.TextBox();

this.SuspendLayout();

//

// label1

//

this.label1.Location = new System.Drawing.Point(40, 15);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(56, 23);

this.label1.TabIndex = 0;

this.label1.Text = "IP:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label2

//

this.label2.Location = new System.Drawing.Point(24, 95);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(72, 23);

this.label2.TabIndex = 1;

this.label2.Text = "Host:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label3

//

this.label3.Location = new System.Drawing.Point(0, 175);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(96, 23);

this.label3.TabIndex = 2;

this.label3.Text = "Time Connected:";

this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// Ok

//

this.Ok.Anchor = System.Windows.Forms.AnchorStyles.Bottom;

this.Ok.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Ok.DefaultScheme = true;

this.Ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.Ok.Hint = "Ok Button";

this.Ok.Image = ((System.Drawing.Image)(resources.GetObject("Ok.Image")));

this.Ok.Location = new System.Drawing.Point(143, 448);

this.Ok.Name = "Ok";

this.Ok.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Ok.Size = new System.Drawing.Size(95, 30);

this.Ok.TabIndex = 6;

this.Ok.Text = "&Ok";

//

// label4

//

this.label4.Location = new System.Drawing.Point(16, 55);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(80, 23);

this.label4.TabIndex = 7;

this.label4.Text = "Port:";

this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label5

//

this.label5.Location = new System.Drawing.Point(24, 216);

this.label5.Name = "label5";

this.label5.Size = new System.Drawing.Size(72, 23);

this.label5.TabIndex = 9;

this.label5.Text = "HandShake:";

this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// textBoxIP

//

this.textBoxIP.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxIP.Location = new System.Drawing.Point(104, 16);

this.textBoxIP.Name = "textBoxIP";

this.textBoxIP.ReadOnly = true;

this.textBoxIP.Size = new System.Drawing.Size(260, 20);

this.textBoxIP.TabIndex = 10;

this.textBoxIP.Text = "textBox1";

//

// textBoxPort

//

this.textBoxPort.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxPort.Location = new System.Drawing.Point(104, 56);

this.textBoxPort.Name = "textBoxPort";

this.textBoxPort.ReadOnly = true;

this.textBoxPort.Size = new System.Drawing.Size(260, 20);

this.textBoxPort.TabIndex = 11;

this.textBoxPort.Text = "textBox2";

//

// textBoxHost

//

this.textBoxHost.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxHost.Location = new System.Drawing.Point(104, 96);

this.textBoxHost.Multiline = true;

this.textBoxHost.Name = "textBoxHost";

this.textBoxHost.ReadOnly = true;

this.textBoxHost.Size = new System.Drawing.Size(260, 20);

this.textBoxHost.TabIndex = 12;

this.textBoxHost.Text = "textBox3";

//

// textBoxTimeConnected

//

this.textBoxTimeConnected.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxTimeConnected.Location = new System.Drawing.Point(104, 176);

this.textBoxTimeConnected.Name = "textBoxTimeConnected";

this.textBoxTimeConnected.ReadOnly = true;

this.textBoxTimeConnected.Size = new System.Drawing.Size(260, 20);

this.textBoxTimeConnected.TabIndex = 13;

this.textBoxTimeConnected.Text = "textBox4";

//

// textBoxHandShake

//

this.textBoxHandShake.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxHandShake.Location = new System.Drawing.Point(104, 216);

this.textBoxHandShake.Multiline = true;

this.textBoxHandShake.Name = "textBoxHandShake";

this.textBoxHandShake.ReadOnly = true;

this.textBoxHandShake.ScrollBars = System.Windows.Forms.ScrollBars.Both;

this.textBoxHandShake.Size = new System.Drawing.Size(260, 216);

this.textBoxHandShake.TabIndex = 14;

this.textBoxHandShake.Text = "textBox5";

//

// label6

//

this.label6.Location = new System.Drawing.Point(32, 135);

this.label6.Name = "label6";

this.label6.Size = new System.Drawing.Size(64, 23);

this.label6.TabIndex = 15;

this.label6.Text = "Type:";

this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// textBoxType

//

this.textBoxType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.textBoxType.Location = new System.Drawing.Point(104, 136);

this.textBoxType.Name = "textBoxType";

this.textBoxType.ReadOnly = true;

this.textBoxType.Size = new System.Drawing.Size(260, 20);

this.textBoxType.TabIndex = 16;

this.textBoxType.Text = "textBox1";

//

// NodeProperties

//

this.AcceptButton = this.Ok;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.Ok;

this.ClientSize = new System.Drawing.Size(380, 487);

this.Controls.Add(this.textBoxType);

this.Controls.Add(this.textBoxHandShake);

this.Controls.Add(this.textBoxTimeConnected);

this.Controls.Add(this.textBoxHost);

this.Controls.Add(this.textBoxPort);

this.Controls.Add(this.textBoxIP);

this.Controls.Add(this.label6);

this.Controls.Add(this.label5);

this.Controls.Add(this.label4);

this.Controls.Add(this.Ok);

this.Controls.Add(this.label3);

this.Controls.Add(this.label2);

this.Controls.Add(this.label1);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(230, 330);

this.Name = "NodeProperties";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "Node Properties";

this.ResumeLayout(false);

}

#endregion

public String IP

{

set

{

textBoxIP.Text = value;

}

}

public String Port

{

set

{

textBoxPort.Text = value;

}

}

public String Host

{

set

{

textBoxHost.Text = value;

}

}

public String Type

{

set

{

textBoxType.Text = value;

}

}

public String TimeConnected

{

set

{

textBoxTimeConnected.Text = value;

}

}

public String HandShake

{

set

{

textBoxHandShake.Text = value;

}

}

}

}

Preferences.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

namespace GDownloader

{

/// <summary>

/// Summary description for Preferences.

/// </summary>

public class Preferences : System.Windows.Forms.Form

{

private GnucDNA.Prefs DnaPrefs;

public MainForm parent;

private PinkieControls.ButtonXP buttonCancel;

private PinkieControls.ButtonXP buttonOk;

private System.Windows.Forms.TabControl tabControl1;

private System.Windows.Forms.TabPage Traffic;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.TextBox textBox2;

private PinkieControls.ButtonXP buttonBrowse1;

private PinkieControls.ButtonXP buttonBrowse2;

private System.Windows.Forms.CheckBox checkBox1;

private System.Windows.Forms.TextBox textBox3;

private System.Windows.Forms.CheckBox checkBox2;

private System.Windows.Forms.TabPage Connection;

private System.Windows.Forms.TabPage Bandwidth;

private System.Windows.Forms.GroupBox groupBox1;

private System.Windows.Forms.GroupBox groupBox2;

private System.Windows.Forms.CheckBox checkBox3;

private System.Windows.Forms.CheckBox checkBox4;

private System.Windows.Forms.TextBox textBox4;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.TextBox textBox5;

private System.Windows.Forms.Label label4;

private System.Windows.Forms.GroupBox groupBox3;

private System.Windows.Forms.CheckBox checkBox5;

private System.Windows.Forms.Label label5;

private System.Windows.Forms.TextBox textBox6;

private System.Windows.Forms.Label label6;

private System.Windows.Forms.GroupBox groupBox4;

private System.Windows.Forms.CheckBox checkBox6;

private System.Windows.Forms.CheckBox checkBox7;

private System.Windows.Forms.TextBox textBox7;

private System.Windows.Forms.TextBox textBox8;

private System.Windows.Forms.TextBox textBox9;

private System.Windows.Forms.CheckBox checkBox8;

private PinkieControls.ButtonXP buttonApply;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public Preferences()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Preferences));

this.buttonCancel = new PinkieControls.ButtonXP();

this.buttonOk = new PinkieControls.ButtonXP();

this.tabControl1 = new System.Windows.Forms.TabControl();

this.Connection = new System.Windows.Forms.TabPage();

this.groupBox4 = new System.Windows.Forms.GroupBox();

this.checkBox8 = new System.Windows.Forms.CheckBox();

this.textBox9 = new System.Windows.Forms.TextBox();

this.textBox8 = new System.Windows.Forms.TextBox();

this.textBox7 = new System.Windows.Forms.TextBox();

this.checkBox7 = new System.Windows.Forms.CheckBox();

this.checkBox6 = new System.Windows.Forms.CheckBox();

this.groupBox3 = new System.Windows.Forms.GroupBox();

this.label6 = new System.Windows.Forms.Label();

this.textBox6 = new System.Windows.Forms.TextBox();

this.label5 = new System.Windows.Forms.Label();

this.checkBox5 = new System.Windows.Forms.CheckBox();

this.Traffic = new System.Windows.Forms.TabPage();

this.checkBox2 = new System.Windows.Forms.CheckBox();

this.textBox3 = new System.Windows.Forms.TextBox();

this.checkBox1 = new System.Windows.Forms.CheckBox();

this.buttonBrowse2 = new PinkieControls.ButtonXP();

this.textBox2 = new System.Windows.Forms.TextBox();

this.textBox1 = new System.Windows.Forms.TextBox();

this.label2 = new System.Windows.Forms.Label();

this.label1 = new System.Windows.Forms.Label();

this.buttonBrowse1 = new PinkieControls.ButtonXP();

this.Bandwidth = new System.Windows.Forms.TabPage();

this.groupBox2 = new System.Windows.Forms.GroupBox();

this.label4 = new System.Windows.Forms.Label();

this.textBox5 = new System.Windows.Forms.TextBox();

this.checkBox4 = new System.Windows.Forms.CheckBox();

this.groupBox1 = new System.Windows.Forms.GroupBox();

this.label3 = new System.Windows.Forms.Label();

this.textBox4 = new System.Windows.Forms.TextBox();

this.checkBox3 = new System.Windows.Forms.CheckBox();

this.buttonApply = new PinkieControls.ButtonXP();

this.tabControl1.SuspendLayout();

this.Connection.SuspendLayout();

this.groupBox4.SuspendLayout();

this.groupBox3.SuspendLayout();

this.Traffic.SuspendLayout();

this.Bandwidth.SuspendLayout();

this.groupBox2.SuspendLayout();

this.groupBox1.SuspendLayout();

this.SuspendLayout();

//

// buttonCancel

//

this.buttonCancel.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonCancel.DefaultScheme = true;

this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.buttonCancel.Hint = "Cancel button";

this.buttonCancel.Image = ((System.Drawing.Image)(resources.GetObject("buttonCancel.Image")));

this.buttonCancel.Location = new System.Drawing.Point(246, 352);

this.buttonCancel.Name = "buttonCancel";

this.buttonCancel.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonCancel.Size = new System.Drawing.Size(95, 30);

this.buttonCancel.TabIndex = 2;

this.buttonCancel.Text = "&Cancel";

//

// buttonOk

//

this.buttonOk.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonOk.DefaultScheme = true;

this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonOk.Hint = "Ok button";

this.buttonOk.Image = ((System.Drawing.Image)(resources.GetObject("buttonOk.Image")));

this.buttonOk.Location = new System.Drawing.Point(358, 352);

this.buttonOk.Name = "buttonOk";

this.buttonOk.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonOk.Size = new System.Drawing.Size(95, 30);

this.buttonOk.TabIndex = 3;

this.buttonOk.Text = "&Ok";

this.buttonOk.Click += new System.EventHandler(this.buttonOk_Click);

//

// tabControl1

//

this.tabControl1.Controls.Add(this.Connection);

this.tabControl1.Controls.Add(this.Traffic);

this.tabControl1.Controls.Add(this.Bandwidth);

this.tabControl1.HotTrack = true;

this.tabControl1.Location = new System.Drawing.Point(17, 24);

this.tabControl1.Name = "tabControl1";

this.tabControl1.SelectedIndex = 0;

this.tabControl1.Size = new System.Drawing.Size(552, 304);

this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;

this.tabControl1.TabIndex = 4;

//

// Connection

//

this.Connection.Controls.Add(this.groupBox4);

this.Connection.Controls.Add(this.groupBox3);

this.Connection.Location = new System.Drawing.Point(4, 22);

this.Connection.Name = "Connection";

this.Connection.Size = new System.Drawing.Size(544, 278);

this.Connection.TabIndex = 1;

this.Connection.Text = "Connection";

//

// groupBox4

//

this.groupBox4.Controls.Add(this.checkBox8);

this.groupBox4.Controls.Add(this.textBox9);

this.groupBox4.Controls.Add(this.textBox8);

this.groupBox4.Controls.Add(this.textBox7);

this.groupBox4.Controls.Add(this.checkBox7);

this.groupBox4.Controls.Add(this.checkBox6);

this.groupBox4.Location = new System.Drawing.Point(28, 112);

this.groupBox4.Name = "groupBox4";

this.groupBox4.Size = new System.Drawing.Size(488, 152);

this.groupBox4.TabIndex = 1;

this.groupBox4.TabStop = false;

this.groupBox4.Text = "Node Management";

//

// checkBox8

//

this.checkBox8.Location = new System.Drawing.Point(32, 22);

this.checkBox8.Name = "checkBox8";

this.checkBox8.Size = new System.Drawing.Size(280, 24);

this.checkBox8.TabIndex = 7;

this.checkBox8.Text = "Minimum connections to keep, when in leaf mode:";

this.checkBox8.CheckedChanged += new System.EventHandler(this.checkBox8_CheckedChanged);

//

// textBox9

//

this.textBox9.Location = new System.Drawing.Point(312, 24);

this.textBox9.Name = "textBox9";

this.textBox9.Size = new System.Drawing.Size(64, 20);

this.textBox9.TabIndex = 6;

this.textBox9.Text = "";

this.textBox9.TextChanged += new System.EventHandler(this.textBox9_TextChanged);

//

// textBox8

//

this.textBox8.Location = new System.Drawing.Point(216, 122);

this.textBox8.Name = "textBox8";

this.textBox8.Size = new System.Drawing.Size(64, 20);

this.textBox8.TabIndex = 5;

this.textBox8.Text = "";

this.textBox8.TextChanged += new System.EventHandler(this.textBox8_TextChanged);

//

// textBox7

//

this.textBox7.Location = new System.Drawing.Point(336, 72);

this.textBox7.Name = "textBox7";

this.textBox7.Size = new System.Drawing.Size(64, 20);

this.textBox7.TabIndex = 4;

this.textBox7.Text = "";

this.textBox7.TextChanged += new System.EventHandler(this.textBox7_TextChanged);

//

// checkBox7

//

this.checkBox7.Location = new System.Drawing.Point(32, 70);

this.checkBox7.Name = "checkBox7";

this.checkBox7.Size = new System.Drawing.Size(304, 24);

this.checkBox7.TabIndex = 3;

this.checkBox7.Text = "Minimum connections to keep, when in ultrapeer mode:";

this.checkBox7.CheckedChanged += new System.EventHandler(this.checkBox7_CheckedChanged);

//

// checkBox6

//

this.checkBox6.Location = new System.Drawing.Point(32, 120);

this.checkBox6.Name = "checkBox6";

this.checkBox6.Size = new System.Drawing.Size(184, 24);

this.checkBox6.TabIndex = 2;

this.checkBox6.Text = "Maximum connections to keep:";

this.checkBox6.CheckedChanged += new System.EventHandler(this.checkBox6_CheckedChanged);

//

// groupBox3

//

this.groupBox3.Controls.Add(this.label6);

this.groupBox3.Controls.Add(this.textBox6);

this.groupBox3.Controls.Add(this.label5);

this.groupBox3.Controls.Add(this.checkBox5);

this.groupBox3.Location = new System.Drawing.Point(28, 16);

this.groupBox3.Name = "groupBox3";

this.groupBox3.Size = new System.Drawing.Size(488, 88);

this.groupBox3.TabIndex = 0;

this.groupBox3.TabStop = false;

this.groupBox3.Text = "Ultrapeer Settings";

//

// label6

//

this.label6.Location = new System.Drawing.Point(200, 56);

this.label6.Name = "label6";

this.label6.Size = new System.Drawing.Size(136, 23);

this.label6.TabIndex = 3;

this.label6.Text = "leaf nodes (1500 limit)";

this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// textBox6

//

this.textBox6.Location = new System.Drawing.Point(136, 57);

this.textBox6.Name = "textBox6";

this.textBox6.Size = new System.Drawing.Size(56, 20);

this.textBox6.TabIndex = 2;

this.textBox6.Text = "";

this.textBox6.TextChanged += new System.EventHandler(this.textBox6_TextChanged);

//

// label5

//

this.label5.Location = new System.Drawing.Point(32, 56);

this.label5.Name = "label5";

this.label5.Size = new System.Drawing.Size(112, 23);

this.label5.TabIndex = 1;

this.label5.Text = "Host a maximum of:";

this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// checkBox5

//

this.checkBox5.Location = new System.Drawing.Point(32, 24);

this.checkBox5.Name = "checkBox5";

this.checkBox5.Size = new System.Drawing.Size(168, 24);

this.checkBox5.TabIndex = 0;

this.checkBox5.Text = "Able to become an Ultrapeer";

this.checkBox5.CheckedChanged += new System.EventHandler(this.checkBox5_CheckedChanged);

//

// Traffic

//

this.Traffic.Controls.Add(this.checkBox2);

this.Traffic.Controls.Add(this.textBox3);

this.Traffic.Controls.Add(this.checkBox1);

this.Traffic.Controls.Add(this.buttonBrowse2);

this.Traffic.Controls.Add(this.textBox2);

this.Traffic.Controls.Add(this.textBox1);

this.Traffic.Controls.Add(this.label2);

this.Traffic.Controls.Add(this.label1);

this.Traffic.Controls.Add(this.buttonBrowse1);

this.Traffic.Location = new System.Drawing.Point(4, 22);

this.Traffic.Name = "Traffic";

this.Traffic.Size = new System.Drawing.Size(544, 278);

this.Traffic.TabIndex = 0;

this.Traffic.Text = "Traffic";

//

// checkBox2

//

this.checkBox2.Location = new System.Drawing.Point(24, 224);

this.checkBox2.Name = "checkBox2";

this.checkBox2.Size = new System.Drawing.Size(416, 24);

this.checkBox2.TabIndex = 9;

this.checkBox2.Text = "Disable downloading simultaneously from multiple hosts (for modem users)";

this.checkBox2.CheckedChanged += new System.EventHandler(this.checkBox2_CheckedChanged);

//

// textBox3

//

this.textBox3.Location = new System.Drawing.Point(216, 176);

this.textBox3.Name = "textBox3";

this.textBox3.Size = new System.Drawing.Size(64, 20);

this.textBox3.TabIndex = 8;

this.textBox3.Text = "";

this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);

//

// checkBox1

//

this.checkBox1.Location = new System.Drawing.Point(24, 176);

this.checkBox1.Name = "checkBox1";

this.checkBox1.Size = new System.Drawing.Size(192, 24);

this.checkBox1.TabIndex = 7;

this.checkBox1.Text = "Maximum concurrent downloads: ";

this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);

//

// buttonBrowse2

//

this.buttonBrowse2.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonBrowse2.DefaultScheme = true;

this.buttonBrowse2.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonBrowse2.Hint = "Browse button";

this.buttonBrowse2.Location = new System.Drawing.Point(432, 101);

this.buttonBrowse2.Name = "buttonBrowse2";

this.buttonBrowse2.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonBrowse2.Size = new System.Drawing.Size(95, 28);

this.buttonBrowse2.TabIndex = 6;

this.buttonBrowse2.Text = "Browse";

this.buttonBrowse2.Click += new System.EventHandler(this.buttonBrowse2_Click);

//

// textBox2

//

this.textBox2.Location = new System.Drawing.Point(152, 105);

this.textBox2.Name = "textBox2";

this.textBox2.Size = new System.Drawing.Size(272, 20);

this.textBox2.TabIndex = 3;

this.textBox2.Text = "";

this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(152, 57);

this.textBox1.Name = "textBox1";

this.textBox1.Size = new System.Drawing.Size(272, 20);

this.textBox1.TabIndex = 2;

this.textBox1.Text = "";

this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);

//

// label2

//

this.label2.Location = new System.Drawing.Point(8, 104);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(144, 23);

this.label2.TabIndex = 1;

this.label2.Text = "Save partial downloads to:";

this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// label1

//

this.label1.Location = new System.Drawing.Point(48, 56);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(104, 23);

this.label1.TabIndex = 0;

this.label1.Text = "Save downloads to:";

this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// buttonBrowse1

//

this.buttonBrowse1.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonBrowse1.DefaultScheme = true;

this.buttonBrowse1.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonBrowse1.Hint = "Browse button";

this.buttonBrowse1.Location = new System.Drawing.Point(432, 53);

this.buttonBrowse1.Name = "buttonBrowse1";

this.buttonBrowse1.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonBrowse1.Size = new System.Drawing.Size(95, 28);

this.buttonBrowse1.TabIndex = 5;

this.buttonBrowse1.Text = "Browse";

this.buttonBrowse1.Click += new System.EventHandler(this.buttonBrowse1_Click);

//

// Bandwidth

//

this.Bandwidth.Controls.Add(this.groupBox2);

this.Bandwidth.Controls.Add(this.groupBox1);

this.Bandwidth.Location = new System.Drawing.Point(4, 22);

this.Bandwidth.Name = "Bandwidth";

this.Bandwidth.Size = new System.Drawing.Size(544, 278);

this.Bandwidth.TabIndex = 2;

this.Bandwidth.Text = "Bandwidth";

//

// groupBox2

//

this.groupBox2.Controls.Add(this.label4);

this.groupBox2.Controls.Add(this.textBox5);

this.groupBox2.Controls.Add(this.checkBox4);

this.groupBox2.Location = new System.Drawing.Point(52, 144);

this.groupBox2.Name = "groupBox2";

this.groupBox2.Size = new System.Drawing.Size(440, 80);

this.groupBox2.TabIndex = 1;

this.groupBox2.TabStop = false;

this.groupBox2.Text = "Traffic Limit";

//

// label4

//

this.label4.Location = new System.Drawing.Point(304, 32);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(40, 23);

this.label4.TabIndex = 3;

this.label4.Text = "KB/s";

this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// textBox5

//

this.textBox5.Location = new System.Drawing.Point(232, 34);

this.textBox5.Name = "textBox5";

this.textBox5.Size = new System.Drawing.Size(64, 20);

this.textBox5.TabIndex = 1;

this.textBox5.Text = "";

this.textBox5.TextChanged += new System.EventHandler(this.textBox5_TextChanged);

//

// checkBox4

//

this.checkBox4.Location = new System.Drawing.Point(24, 32);

this.checkBox4.Name = "checkBox4";

this.checkBox4.Size = new System.Drawing.Size(200, 24);

this.checkBox4.TabIndex = 0;

this.checkBox4.Text = "Drop downloads transfering under:";

this.checkBox4.CheckedChanged += new System.EventHandler(this.checkBox4_CheckedChanged);

//

// groupBox1

//

this.groupBox1.Controls.Add(this.label3);

this.groupBox1.Controls.Add(this.textBox4);

this.groupBox1.Controls.Add(this.checkBox3);

this.groupBox1.Location = new System.Drawing.Point(52, 32);

this.groupBox1.Name = "groupBox1";

this.groupBox1.Size = new System.Drawing.Size(440, 80);

this.groupBox1.TabIndex = 0;

this.groupBox1.TabStop = false;

this.groupBox1.Text = "Bandwidth Limit";

//

// label3

//

this.label3.Location = new System.Drawing.Point(272, 32);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(40, 23);

this.label3.TabIndex = 2;

this.label3.Text = "KB/s";

this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;

//

// textBox4

//

this.textBox4.Location = new System.Drawing.Point(200, 34);

this.textBox4.Name = "textBox4";

this.textBox4.Size = new System.Drawing.Size(64, 20);

this.textBox4.TabIndex = 1;

this.textBox4.Text = "";

this.textBox4.TextChanged += new System.EventHandler(this.textBox4_TextChanged);

//

// checkBox3

//

this.checkBox3.Location = new System.Drawing.Point(24, 32);

this.checkBox3.Name = "checkBox3";

this.checkBox3.Size = new System.Drawing.Size(176, 24);

this.checkBox3.TabIndex = 0;

this.checkBox3.Text = "Limit download bandwidth to:";

this.checkBox3.CheckedChanged += new System.EventHandler(this.checkBox3_CheckedChanged);

//

// buttonApply

//

this.buttonApply.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonApply.DefaultScheme = true;

this.buttonApply.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonApply.Enabled = false;

this.buttonApply.Hint = "Apply button";

this.buttonApply.Image = ((System.Drawing.Image)(resources.GetObject("buttonApply.Image")));

this.buttonApply.Location = new System.Drawing.Point(134, 352);

this.buttonApply.Name = "buttonApply";

this.buttonApply.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonApply.Size = new System.Drawing.Size(95, 30);

this.buttonApply.TabIndex = 5;

this.buttonApply.Text = "&Apply";

this.buttonApply.Click += new System.EventHandler(this.buttonApply_Click);

//

// Preferences

//

this.AcceptButton = this.buttonOk;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.CancelButton = this.buttonCancel;

this.ClientSize = new System.Drawing.Size(586, 399);

this.Controls.Add(this.buttonApply);

this.Controls.Add(this.tabControl1);

this.Controls.Add(this.buttonCancel);

this.Controls.Add(this.buttonOk);

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MaximizeBox = false;

this.Name = "Preferences";

this.ShowInTaskbar = false;

this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "GDownloader Preferences";

this.tabControl1.ResumeLayout(false);

this.Connection.ResumeLayout(false);

this.groupBox4.ResumeLayout(false);

this.groupBox3.ResumeLayout(false);

this.Traffic.ResumeLayout(false);

this.Bandwidth.ResumeLayout(false);

this.groupBox2.ResumeLayout(false);

this.groupBox1.ResumeLayout(false);

this.ResumeLayout(false);

}

#endregion

public void inițializeItemValues()

{

DnaPrefs = parent.getDnaPrefs();

checkBox5.Checked = DnaPrefs.SuperNodeAble;

textBox6.Enabled = checkBox5.Checked;

textBox6.Text = DnaPrefs.MaxLeaves.ToString();

if (DnaPrefs.MinConnects == -1)

{

textBox7.Enabled = false;

}

else

{

checkBox7.Checked = true;

textBox7.Text = DnaPrefs.MinConnects.ToString();

}

if (DnaPrefs.MaxConnects == -1)

{

textBox8.Enabled = false;

}

else

{

checkBox6.Checked = true;

textBox8.Text = DnaPrefs.MaxConnects.ToString();

}

if (DnaPrefs.LeafModeConnects == -1)

{

textBox9.Enabled = false;

}

else

{

checkBox8.Checked = true;

textBox9.Text = DnaPrefs.LeafModeConnects.ToString();

}

textBox1.Text = DnaPrefs.DownloadPath;

textBox2.Text = DnaPrefs.PartialsDir;

if (DnaPrefs.MaxDownloads == 0)

{

textBox3.Enabled = false;

}

else

{

checkBox1.Checked = true;

textBox3.Text = DnaPrefs.MaxDownloads.ToString();

}

checkBox2.Checked = !DnaPrefs.Multisource;

if (DnaPrefs.BandwidthDown == 0)

{

textBox4.Enabled = false;

}

else

{

checkBox3.Checked = true;

textBox4.Text = DnaPrefs.BandwidthDown.ToString();

}

if (DnaPrefs.MinDownSpeed == 0)

{

textBox5.Enabled = false;

}

else

{

checkBox4.Checked = true;

textBox5.Text = DnaPrefs.MinDownSpeed.ToString();

}

buttonApply.Enabled = false;

}

#region User Interface

private void buttonOk_Click(object sender, System.EventArgs e)

{

if ( savePreferences() )

this.Dispose();

}

private void buttonBrowse1_Click(object sender, System.EventArgs e)

{

FolderBrowserDialog dlg = new FolderBrowserDialog();

dlg.Description = "Save downloads to…";

if ( dlg.ShowDialog(this) == DialogResult.OK)

{

textBox1.Text = dlg.SelectedPath;

buttonApply.Enabled = true;

}

}

private void buttonBrowse2_Click(object sender, System.EventArgs e)

{

FolderBrowserDialog dlg = new FolderBrowserDialog();

dlg.Description = "Save partial downloads to…";

if ( dlg.ShowDialog(this) == DialogResult.OK )

{

textBox2.Text = dlg.SelectedPath;

buttonApply.Enabled = true;

}

}

// "Able to become an Ultrapeer" CheckBox form the Connections Tab

private void checkBox5_CheckedChanged(object sender, System.EventArgs e)

{

textBox6.Enabled = checkBox5.Checked;

buttonApply.Enabled = true;

}

// "Minimum connections to keep, when in leaf mode" CheckBox form the Connections Tab

private void checkBox8_CheckedChanged(object sender, System.EventArgs e)

{

textBox9.Enabled = checkBox8.Checked;

buttonApply.Enabled = true;

}

// Minimum connections to keep, when in ultrapeer mode" CheckBox form the Connections Tab

private void checkBox7_CheckedChanged(object sender, System.EventArgs e)

{

textBox7.Enabled = checkBox7.Checked;

buttonApply.Enabled = true;

}

// "Maximum connections to keep" CheckBox form the Connections Tab

private void checkBox6_CheckedChanged(object sender, System.EventArgs e)

{

textBox8.Enabled = checkBox6.Checked;

buttonApply.Enabled = true;

}

// "Maximum concurrent downloads" CheckBox form the Traffic Tab

private void checkBox1_CheckedChanged(object sender, System.EventArgs e)

{

textBox3.Enabled = checkBox1.Checked;

buttonApply.Enabled = true;

}

// "Disable downloading simultaneously from multiple hosts (for modem users)" CheckBox form the Traffic Tab

private void checkBox2_CheckedChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

// "Limit download bandwidth to" CheckBox form the Bandwidth Tab

private void checkBox3_CheckedChanged(object sender, System.EventArgs e)

{

textBox4.Enabled = checkBox3.Checked;

buttonApply.Enabled = true;

}

// "Drop downloads transfering under" CheckBox form the Bandwidth Tab

private void checkBox4_CheckedChanged(object sender, System.EventArgs e)

{

textBox5.Enabled = checkBox4.Checked;

buttonApply.Enabled = true;

}

private void buttonApply_Click(object sender, System.EventArgs e)

{

if ( savePreferences() )

{

buttonApply.Enabled = false;

}

}

private void textBox6_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox9_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox7_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox8_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox1_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox2_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox3_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox4_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

private void textBox5_TextChanged(object sender, System.EventArgs e)

{

buttonApply.Enabled = true;

}

#endregion

private bool savePreferences()

{

try

{

DnaPrefs.SuperNodeAble = checkBox5.Checked;

DnaPrefs.MaxLeaves = Int32.Parse(textBox6.Text);

if ( !checkBox7.Checked )

{

DnaPrefs.MinConnects = -1;

}

else

{

DnaPrefs.MinConnects = Int32.Parse(textBox7.Text);

}

if ( !checkBox6.Checked )

{

DnaPrefs.MaxConnects = -1;

}

else

{

DnaPrefs.MaxConnects = Int32.Parse(textBox8.Text);

}

if ( !checkBox8.Checked )

{

DnaPrefs.LeafModeConnects = -1;

}

else

{

DnaPrefs.LeafModeConnects = Int32.Parse(textBox9.Text);

}

DnaPrefs.DownloadPath = textBox1.Text;

DnaPrefs.PartialsDir = textBox2.Text;

if ( !checkBox1.Checked )

{

DnaPrefs.MaxDownloads = 0;

}

else

{

DnaPrefs.MaxDownloads = Int32.Parse(textBox3.Text);

}

DnaPrefs.Multisource = !checkBox2.Checked;

if ( !checkBox3.Checked )

{

DnaPrefs.BandwidthDown = 0;

}

else

{

DnaPrefs.BandwidthDown = Int32.Parse(textBox4.Text);

}

if ( !checkBox4.Checked )

{

DnaPrefs.MinDownSpeed = 0;

}

else

{

DnaPrefs.MinDownSpeed = Int32.Parse(textBox5.Text);

}

}

catch (Exception e)

{

MessageBox.Show(this, e.Message, "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return false;

}

DnaPrefs.SaveConfig(Application.StartupPath + "\\GDownloader.ini");

return true;

}

}

}

SearchResult.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.IO;

using GlacialComponents.Controls;

namespace GDownloader

{

/// <summary>

/// Summary description for SearchResult.

/// </summary>

public class SearchResult : System.Windows.Forms.Form

{

// time for search (in seconds)

private const int SEARCH_TIME = 20;

private bool ascending;

private ArrayList trafficList;

public MainForm parent;

private ApplicationType knownExtensions;

private int currentSearchId;

private string currentSearchText;

private DateTime searchTime;

private Hashtable searchHash;

private GnucDNA.Search DnaSearch;

private bool googleSearch;

private Service service;

private FileProperties propertiesDlg;

private About aboutDlg;

private Confirm confirmDlg;

private WebBrowser webBrowser;

private System.Windows.Forms.ListView listSearch;

private System.Windows.Forms.ColumnHeader columnHeader7;

private System.Windows.Forms.ColumnHeader columnHeader8;

private System.Windows.Forms.ColumnHeader columnHeader9;

private System.Windows.Forms.ColumnHeader columnHeader10;

private System.Windows.Forms.ColumnHeader columnHeader11;

private System.Windows.Forms.ColumnHeader columnHeader12;

private System.Windows.Forms.ComboBox comboBoxSearch;

private System.Windows.Forms.GroupBox groupBoxSearch;

private System.Windows.Forms.Label label1;

private PinkieControls.ButtonXP Search;

private PinkieControls.ButtonXP buttonEndSearch;

private System.Windows.Forms.Label label2;

private System.Windows.Forms.Label label3;

private System.Windows.Forms.Label label4;

private System.Windows.Forms.Timer timer1;

private PinkieControls.ButtonXP buttonHelp;

private PinkieControls.ButtonXP buttonExit;

private PinkieControls.ButtonXP buttonDownload;

private System.Windows.Forms.CheckBox checkBoxAnything;

private System.Windows.Forms.CheckBox checkBoxAudio;

private System.Windows.Forms.CheckBox checkBoxVideo;

private System.Windows.Forms.CheckBox checkBoxDocument;

private System.Windows.Forms.CheckBox checkBoxCompressed;

private System.Windows.Forms.TextBox textBox1;

private System.Windows.Forms.TextBox textBox2;

private System.Windows.Forms.ComboBox comboBox1;

private System.Windows.Forms.CheckBox checkBoxPicture;

private System.Windows.Forms.ColumnHeader columnHeader1;

private PinkieControls.ButtonXP buttonTraffic;

private PinkieControls.ButtonXP buttonConnections;

private PinkieControls.ButtonXP buttonXP1;

private System.Windows.Forms.ImageList imageList;

private System.Windows.Forms.ContextMenu contextMenu1;

private System.Windows.Forms.MenuItem menuItem1;

private System.Windows.Forms.MenuItem menuItem2;

private System.Windows.Forms.ToolTip toolTip1;

private System.Windows.Forms.MenuItem menuItem3;

private System.Windows.Forms.Label label5;

private System.Windows.Forms.GroupBox groupBox1;

private PinkieControls.ButtonXP buttonGoogleSearch;

private System.Windows.Forms.ComboBox comboBoxSearchGoogle;

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Label label6;

private System.Windows.Forms.Button buttonDefault;

private System.ComponentModel.IContainer components;

public SearchResult()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

ascending = true;

currentSearchId = 0;

currentSearchText = "";

searchHash = new Hashtable();

googleSearch = false;

knownExtensions = new ApplicationType();

service = new Service();

}

public void InițializeSearch()

{

DnaSearch = parent.getDnaSearch();

DnaSearch.OnRefresh += new GnucDNA._ISearchEvent_OnRefreshEventHandler(DnaSearch_OnRefresh);

DnaSearch.OnResult += new GnucDNA._ISearchEvent_OnResultEventHandler(DnaSearch_OnResult);

DnaSearch.OnUpdate += new GnucDNA._ISearchEvent_OnUpdateEventHandler(DnaSearch_OnUpdate);

SearchResult_Activated(null, null);

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

this.components = new System.ComponentModel.Container();

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(SearchResult));

this.listSearch = new System.Windows.Forms.ListView();

this.columnHeader7 = new System.Windows.Forms.ColumnHeader();

this.columnHeader8 = new System.Windows.Forms.ColumnHeader();

this.columnHeader1 = new System.Windows.Forms.ColumnHeader();

this.columnHeader9 = new System.Windows.Forms.ColumnHeader();

this.columnHeader10 = new System.Windows.Forms.ColumnHeader();

this.columnHeader11 = new System.Windows.Forms.ColumnHeader();

this.columnHeader12 = new System.Windows.Forms.ColumnHeader();

this.contextMenu1 = new System.Windows.Forms.ContextMenu();

this.menuItem1 = new System.Windows.Forms.MenuItem();

this.menuItem2 = new System.Windows.Forms.MenuItem();

this.menuItem3 = new System.Windows.Forms.MenuItem();

this.imageList = new System.Windows.Forms.ImageList(this.components);

this.comboBoxSearch = new System.Windows.Forms.ComboBox();

this.buttonEndSearch = new PinkieControls.ButtonXP();

this.Search = new PinkieControls.ButtonXP();

this.groupBoxSearch = new System.Windows.Forms.GroupBox();

this.comboBox1 = new System.Windows.Forms.ComboBox();

this.label4 = new System.Windows.Forms.Label();

this.textBox2 = new System.Windows.Forms.TextBox();

this.textBox1 = new System.Windows.Forms.TextBox();

this.label3 = new System.Windows.Forms.Label();

this.checkBoxCompressed = new System.Windows.Forms.CheckBox();

this.checkBoxDocument = new System.Windows.Forms.CheckBox();

this.checkBoxPicture = new System.Windows.Forms.CheckBox();

this.checkBoxVideo = new System.Windows.Forms.CheckBox();

this.checkBoxAudio = new System.Windows.Forms.CheckBox();

this.checkBoxAnything = new System.Windows.Forms.CheckBox();

this.label1 = new System.Windows.Forms.Label();

this.label2 = new System.Windows.Forms.Label();

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.buttonHelp = new PinkieControls.ButtonXP();

this.buttonExit = new PinkieControls.ButtonXP();

this.buttonDownload = new PinkieControls.ButtonXP();

this.buttonConnections = new PinkieControls.ButtonXP();

this.buttonTraffic = new PinkieControls.ButtonXP();

this.buttonXP1 = new PinkieControls.ButtonXP();

this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);

this.comboBoxSearchGoogle = new System.Windows.Forms.ComboBox();

this.label5 = new System.Windows.Forms.Label();

this.groupBox1 = new System.Windows.Forms.GroupBox();

this.label6 = new System.Windows.Forms.Label();

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.buttonGoogleSearch = new PinkieControls.ButtonXP();

this.buttonDefault = new System.Windows.Forms.Button();

this.groupBoxSearch.SuspendLayout();

this.groupBox1.SuspendLayout();

this.SuspendLayout();

//

// listSearch

//

this.listSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.listSearch.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {

this.columnHeader7,

this.columnHeader8,

this.columnHeader1,

this.columnHeader9,

this.columnHeader10,

this.columnHeader11,

this.columnHeader12});

this.listSearch.ContextMenu = this.contextMenu1;

this.listSearch.FullRowSelect = true;

this.listSearch.Location = new System.Drawing.Point(264, 80);

this.listSearch.Name = "listSearch";

this.listSearch.Size = new System.Drawing.Size(568, 474);

this.listSearch.SmallImageList = this.imageList;

this.listSearch.TabIndex = 2;

this.listSearch.View = System.Windows.Forms.View.Details;

this.listSearch.DoubleClick += new System.EventHandler(this.listSearch_DoubleClick);

this.listSearch.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listSearch_ColumnClick);

//

// columnHeader7

//

this.columnHeader7.Text = "File";

this.columnHeader7.Width = 265;

//

// columnHeader8

//

this.columnHeader8.Text = "Type";

this.columnHeader8.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader8.Width = 91;

//

// columnHeader1

//

this.columnHeader1.Text = "Media";

this.columnHeader1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader1.Width = 88;

//

// columnHeader9

//

this.columnHeader9.Text = "Size";

this.columnHeader9.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader9.Width = 111;

//

// columnHeader10

//

this.columnHeader10.Text = "Hashed";

this.columnHeader10.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader10.Width = 73;

//

// columnHeader11

//

this.columnHeader11.Text = "Hosts";

this.columnHeader11.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader11.Width = 66;

//

// columnHeader12

//

this.columnHeader12.Text = "Speed";

this.columnHeader12.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

this.columnHeader12.Width = 96;

//

// contextMenu1

//

this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.menuItem1,

this.menuItem2,

this.menuItem3});

//

// menuItem1

//

this.menuItem1.Index = 0;

this.menuItem1.Text = "Download";

this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);

//

// menuItem2

//

this.menuItem2.Index = 1;

this.menuItem2.Text = "Cancel Download";

this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);

//

// menuItem3

//

this.menuItem3.Index = 2;

this.menuItem3.Text = "Properties";

this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);

//

// imageList

//

this.imageList.ImageSize = new System.Drawing.Size(16, 16);

this.imageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList.ImageStream")));

this.imageList.TransparentColor = System.Drawing.Color.Transparent;

//

// comboBoxSearch

//

this.comboBoxSearch.AccessibleRole = System.Windows.Forms.AccessibleRole.ComboBox;

this.comboBoxSearch.Location = new System.Drawing.Point(10, 40);

this.comboBoxSearch.Name = "comboBoxSearch";

this.comboBoxSearch.Size = new System.Drawing.Size(200, 21);

this.comboBoxSearch.TabIndex = 16;

this.toolTip1.SetToolTip(this.comboBoxSearch, "Search over the Gnutella network. Type your search here…");

this.comboBoxSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.comboBoxSearch_KeyDown);

this.comboBoxSearch.TextChanged += new System.EventHandler(this.comboBoxSearch_TextChanged);

//

// buttonEndSearch

//

this.buttonEndSearch.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonEndSearch.DefaultScheme = false;

this.buttonEndSearch.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonEndSearch.Enabled = false;

this.buttonEndSearch.Hint = "Ends the current search";

this.buttonEndSearch.Location = new System.Drawing.Point(120, 75);

this.buttonEndSearch.Name = "buttonEndSearch";

this.buttonEndSearch.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonEndSearch.Size = new System.Drawing.Size(90, 30);

this.buttonEndSearch.TabIndex = 17;

this.buttonEndSearch.Text = "&End Search";

this.buttonEndSearch.Click += new System.EventHandler(this.buttonEndSearch_Click);

//

// Search

//

this.Search.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;

this.Search.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Search.DefaultScheme = false;

this.Search.DialogResult = System.Windows.Forms.DialogResult.None;

this.Search.Hint = "Starts a new search over the Gnutella network";

this.Search.Location = new System.Drawing.Point(10, 75);

this.Search.Name = "Search";

this.Search.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Search.Size = new System.Drawing.Size(90, 30);

this.Search.TabIndex = 15;

this.Search.Text = "&Start Search";

this.Search.Click += new System.EventHandler(this.Search_Click);

//

// groupBoxSearch

//

this.groupBoxSearch.Controls.Add(this.comboBox1);

this.groupBoxSearch.Controls.Add(this.label4);

this.groupBoxSearch.Controls.Add(this.textBox2);

this.groupBoxSearch.Controls.Add(this.textBox1);

this.groupBoxSearch.Controls.Add(this.label3);

this.groupBoxSearch.Controls.Add(this.checkBoxCompressed);

this.groupBoxSearch.Controls.Add(this.checkBoxDocument);

this.groupBoxSearch.Controls.Add(this.checkBoxPicture);

this.groupBoxSearch.Controls.Add(this.checkBoxVideo);

this.groupBoxSearch.Controls.Add(this.checkBoxAudio);

this.groupBoxSearch.Controls.Add(this.checkBoxAnything);

this.groupBoxSearch.Controls.Add(this.label1);

this.groupBoxSearch.Controls.Add(this.buttonEndSearch);

this.groupBoxSearch.Controls.Add(this.comboBoxSearch);

this.groupBoxSearch.Controls.Add(this.Search);

this.groupBoxSearch.Location = new System.Drawing.Point(16, 80);

this.groupBoxSearch.Name = "groupBoxSearch";

this.groupBoxSearch.Size = new System.Drawing.Size(224, 355);

this.groupBoxSearch.TabIndex = 17;

this.groupBoxSearch.TabStop = false;

this.groupBoxSearch.Text = "Search Options";

//

// comboBox1

//

this.comboBox1.DisplayMember = "2";

this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;

this.comboBox1.Items.AddRange(new object[] {

"Bytes",

"Kilo Bytes",

"Mega Bytes",

"Giga Bytes"});

this.comboBox1.Location = new System.Drawing.Point(10, 323);

this.comboBox1.Name = "comboBox1";

this.comboBox1.Size = new System.Drawing.Size(200, 21);

this.comboBox1.TabIndex = 2;

this.comboBox1.SelectedIndex = 2;

this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);

//

// label4

//

this.label4.Location = new System.Drawing.Point(96, 293);

this.label4.Name = "label4";

this.label4.Size = new System.Drawing.Size(24, 16);

this.label4.TabIndex = 28;

this.label4.Text = "And";

//

// textBox2

//

this.textBox2.Location = new System.Drawing.Point(130, 289);

this.textBox2.Name = "textBox2";

this.textBox2.Size = new System.Drawing.Size(80, 20);

this.textBox2.TabIndex = 27;

this.textBox2.Text = "1000";

this.textBox2.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;

this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(10, 289);

this.textBox1.Name = "textBox1";

this.textBox1.Size = new System.Drawing.Size(80, 20);

this.textBox1.TabIndex = 26;

this.textBox1.Text = "1";

this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;

this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);

//

// label3

//

this.label3.Location = new System.Drawing.Point(10, 275);

this.label3.Name = "label3";

this.label3.Size = new System.Drawing.Size(100, 16);

this.label3.TabIndex = 25;

this.label3.Text = "File Size Between:";

//

// checkBoxCompressed

//

this.checkBoxCompressed.Checked = true;

this.checkBoxCompressed.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxCompressed.Location = new System.Drawing.Point(10, 216);

this.checkBoxCompressed.Name = "checkBoxCompressed";

this.checkBoxCompressed.TabIndex = 24;

this.checkBoxCompressed.Text = "Compressed";

this.toolTip1.SetToolTip(this.checkBoxCompressed, "Extensions included: ace, arj, bz2, cab, gz, lha, rar, tar, uha, zip");

this.checkBoxCompressed.CheckedChanged += new System.EventHandler(this.checkBoxCompressed_CheckedChanged);

//

// checkBoxDocument

//

this.checkBoxDocument.Checked = true;

this.checkBoxDocument.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxDocument.Location = new System.Drawing.Point(10, 192);

this.checkBoxDocument.Name = "checkBoxDocument";

this.checkBoxDocument.TabIndex = 23;

this.checkBoxDocument.Text = "Document";

this.toolTip1.SetToolTip(this.checkBoxDocument, "Extensions included: chm, doc, pdf, ppt, rtf, txt");

this.checkBoxDocument.CheckedChanged += new System.EventHandler(this.checkBoxDocument_CheckedChanged);

//

// checkBoxPicture

//

this.checkBoxPicture.Checked = true;

this.checkBoxPicture.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxPicture.Location = new System.Drawing.Point(10, 168);

this.checkBoxPicture.Name = "checkBoxPicture";

this.checkBoxPicture.TabIndex = 22;

this.checkBoxPicture.Text = "Picture";

this.toolTip1.SetToolTip(this.checkBoxPicture, "Extensions included: bmp, gif, iff, jpeg, jpg, pcx, png, psd, ras, rsb, sgi, tga," +

" tiff");

this.checkBoxPicture.CheckedChanged += new System.EventHandler(this.checkBoxPicture_CheckedChanged);

//

// checkBoxVideo

//

this.checkBoxVideo.Checked = true;

this.checkBoxVideo.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxVideo.Location = new System.Drawing.Point(10, 144);

this.checkBoxVideo.Name = "checkBoxVideo";

this.checkBoxVideo.TabIndex = 21;

this.checkBoxVideo.Text = "Video";

this.toolTip1.SetToolTip(this.checkBoxVideo, "Extensions included: asf, avi, divx, m1v, m2v, mov, mpe, mpeg, mpg, mp2v, mpv2, q" +

"t, wmv");

this.checkBoxVideo.CheckedChanged += new System.EventHandler(this.checkBoxVideo_CheckedChanged);

//

// checkBoxAudio

//

this.checkBoxAudio.Checked = true;

this.checkBoxAudio.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxAudio.Location = new System.Drawing.Point(10, 120);

this.checkBoxAudio.Name = "checkBoxAudio";

this.checkBoxAudio.TabIndex = 20;

this.checkBoxAudio.Text = "Audio";

this.toolTip1.SetToolTip(this.checkBoxAudio, "Extensions included: mp2, mp3, wav, wma");

this.checkBoxAudio.CheckedChanged += new System.EventHandler(this.checkBoxAudio_CheckedChanged);

//

// checkBoxAnything

//

this.checkBoxAnything.Checked = true;

this.checkBoxAnything.CheckState = System.Windows.Forms.CheckState.Checked;

this.checkBoxAnything.Location = new System.Drawing.Point(10, 240);

this.checkBoxAnything.Name = "checkBoxAnything";

this.checkBoxAnything.Size = new System.Drawing.Size(96, 24);

this.checkBoxAnything.TabIndex = 19;

this.checkBoxAnything.Text = "Anything Else";

this.toolTip1.SetToolTip(this.checkBoxAnything, "All the other files");

this.checkBoxAnything.CheckedChanged += new System.EventHandler(this.checkBoxAnything_CheckedChanged);

//

// label1

//

this.label1.Location = new System.Drawing.Point(10, 24);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(64, 16);

this.label1.TabIndex = 18;

this.label1.Text = "Search For: ";

//

// label2

//

this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.label2.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label2.ForeColor = System.Drawing.SystemColors.WindowText;

this.label2.Location = new System.Drawing.Point(264, 32);

this.label2.Name = "label2";

this.label2.Size = new System.Drawing.Size(416, 24);

this.label2.TabIndex = 18;

//

// timer1

//

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

//

// buttonHelp

//

this.buttonHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonHelp.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonHelp.DefaultScheme = false;

this.buttonHelp.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonHelp.Hint = "GDownloader Help";

this.buttonHelp.Image = ((System.Drawing.Image)(resources.GetObject("buttonHelp.Image")));

this.buttonHelp.Location = new System.Drawing.Point(608, 618);

this.buttonHelp.Name = "buttonHelp";

this.buttonHelp.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonHelp.Size = new System.Drawing.Size(95, 30);

this.buttonHelp.TabIndex = 20;

this.buttonHelp.Text = "&Help";

this.buttonHelp.Click += new System.EventHandler(this.buttonHelp_Click);

//

// buttonExit

//

this.buttonExit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonExit.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonExit.DefaultScheme = false;

this.buttonExit.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.buttonExit.Hint = "Exit GDownloader";

this.buttonExit.Image = ((System.Drawing.Image)(resources.GetObject("buttonExit.Image")));

this.buttonExit.Location = new System.Drawing.Point(732, 618);

this.buttonExit.Name = "buttonExit";

this.buttonExit.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonExit.Size = new System.Drawing.Size(95, 30);

this.buttonExit.TabIndex = 19;

this.buttonExit.Text = "&Exit";

this.buttonExit.Click += new System.EventHandler(this.buttonExit_Click);

//

// buttonDownload

//

this.buttonDownload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonDownload.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonDownload.DefaultScheme = false;

this.buttonDownload.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonDownload.Hint = "Downloads the selected files";

this.buttonDownload.Location = new System.Drawing.Point(264, 562);

this.buttonDownload.Name = "buttonDownload";

this.buttonDownload.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonDownload.Size = new System.Drawing.Size(95, 30);

this.buttonDownload.TabIndex = 21;

this.buttonDownload.Text = "&Download";

this.buttonDownload.Click += new System.EventHandler(this.buttonDownload_Click);

//

// buttonConnections

//

this.buttonConnections.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;

this.buttonConnections.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonConnections.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonConnections.DefaultScheme = false;

this.buttonConnections.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonConnections.Hint = "Shows Connections Dialog";

this.buttonConnections.Image = ((System.Drawing.Image)(resources.GetObject("buttonConnections.Image")));

this.buttonConnections.Location = new System.Drawing.Point(16, 618);

this.buttonConnections.Name = "buttonConnections";

this.buttonConnections.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonConnections.Size = new System.Drawing.Size(95, 30);

this.buttonConnections.TabIndex = 22;

this.buttonConnections.Text = "&Connections";

this.buttonConnections.Click += new System.EventHandler(this.buttonConnections_Click);

//

// buttonTraffic

//

this.buttonTraffic.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonTraffic.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonTraffic.DefaultScheme = false;

this.buttonTraffic.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonTraffic.Hint = "Shows Traffic Dialog";

this.buttonTraffic.Image = ((System.Drawing.Image)(resources.GetObject("buttonTraffic.Image")));

this.buttonTraffic.Location = new System.Drawing.Point(264, 618);

this.buttonTraffic.Name = "buttonTraffic";

this.buttonTraffic.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonTraffic.Size = new System.Drawing.Size(95, 30);

this.buttonTraffic.TabIndex = 23;

this.buttonTraffic.Text = "&Traffic";

this.buttonTraffic.Click += new System.EventHandler(this.buttonTraffic_Click);

//

// buttonXP1

//

this.buttonXP1.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;

this.buttonXP1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonXP1.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonXP1.DefaultScheme = false;

this.buttonXP1.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonXP1.Enabled = false;

this.buttonXP1.Hint = "Shows Search Dialog";

this.buttonXP1.Image = ((System.Drawing.Image)(resources.GetObject("buttonXP1.Image")));

this.buttonXP1.Location = new System.Drawing.Point(140, 618);

this.buttonXP1.Name = "buttonXP1";

this.buttonXP1.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonXP1.Size = new System.Drawing.Size(95, 30);

this.buttonXP1.TabIndex = 24;

this.buttonXP1.Text = "&Search";

//

// comboBoxSearchGoogle

//

this.comboBoxSearchGoogle.Location = new System.Drawing.Point(10, 24);

this.comboBoxSearchGoogle.Name = "comboBoxSearchGoogle";

this.comboBoxSearchGoogle.Size = new System.Drawing.Size(200, 21);

this.comboBoxSearchGoogle.TabIndex = 28;

this.toolTip1.SetToolTip(this.comboBoxSearchGoogle, "Search the Web. Type your search here…");

this.comboBoxSearchGoogle.KeyDown += new System.Windows.Forms.KeyEventHandler(this.comboBoxSearchGoogle_KeyDown);

//

// label5

//

this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));

this.label5.Font = new System.Drawing.Font("Times New Roman", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label5.ForeColor = System.Drawing.SystemColors.ControlText;

this.label5.Location = new System.Drawing.Point(688, 32);

this.label5.Name = "label5";

this.label5.Size = new System.Drawing.Size(144, 24);

this.label5.TabIndex = 25;

this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight;

//

// groupBox1

//

this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)));

this.groupBox1.Controls.Add(this.label6);

this.groupBox1.Controls.Add(this.pictureBox1);

this.groupBox1.Controls.Add(this.comboBoxSearchGoogle);

this.groupBox1.Controls.Add(this.buttonGoogleSearch);

this.groupBox1.Location = new System.Drawing.Point(16, 448);

this.groupBox1.Name = "groupBox1";

this.groupBox1.Size = new System.Drawing.Size(224, 106);

this.groupBox1.TabIndex = 26;

this.groupBox1.TabStop = false;

this.groupBox1.Text = "Search the Web";

//

// label6

//

this.label6.Location = new System.Drawing.Point(128, 48);

this.label6.Name = "label6";

this.label6.Size = new System.Drawing.Size(72, 16);

this.label6.TabIndex = 30;

this.label6.Text = "Powered By:";

this.label6.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;

//

// pictureBox1

//

this.pictureBox1.BackColor = System.Drawing.SystemColors.Control;

this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));

this.pictureBox1.Location = new System.Drawing.Point(112, 56);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(104, 48);

this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;

this.pictureBox1.TabIndex = 29;

this.pictureBox1.TabStop = false;

//

// buttonGoogleSearch

//

this.buttonGoogleSearch.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonGoogleSearch.DefaultScheme = false;

this.buttonGoogleSearch.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonGoogleSearch.Hint = "Search the Web. Powered by Google";

this.buttonGoogleSearch.Location = new System.Drawing.Point(10, 60);

this.buttonGoogleSearch.Name = "buttonGoogleSearch";

this.buttonGoogleSearch.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonGoogleSearch.Size = new System.Drawing.Size(95, 30);

this.buttonGoogleSearch.TabIndex = 27;

this.buttonGoogleSearch.Text = "&Google Search";

this.buttonGoogleSearch.Click += new System.EventHandler(this.buttonGoogleSearch_Click);

//

// buttonDefault

//

this.buttonDefault.Location = new System.Drawing.Point(80, 24);

this.buttonDefault.Name = "buttonDefault";

this.buttonDefault.Size = new System.Drawing.Size(0, 0);

this.buttonDefault.TabIndex = 27;

this.buttonDefault.Text = "buttonDefault";

this.buttonDefault.Click += new System.EventHandler(this.buttonDefault_Click);

//

// SearchResult

//

this.AcceptButton = this.buttonDefault;

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(848, 663);

this.Controls.Add(this.buttonDefault);

this.Controls.Add(this.groupBox1);

this.Controls.Add(this.label5);

this.Controls.Add(this.buttonXP1);

this.Controls.Add(this.buttonConnections);

this.Controls.Add(this.buttonTraffic);

this.Controls.Add(this.buttonDownload);

this.Controls.Add(this.buttonHelp);

this.Controls.Add(this.buttonExit);

this.Controls.Add(this.label2);

this.Controls.Add(this.groupBoxSearch);

this.Controls.Add(this.listSearch);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(630, 680);

this.Name = "SearchResult";

this.Text = "Search";

this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

this.Closing += new System.ComponentModel.CancelEventHandler(this.SearchResult_Closing);

this.Activated += new System.EventHandler(this.SearchResult_Activated);

this.groupBoxSearch.ResumeLayout(false);

this.groupBox1.ResumeLayout(false);

this.ResumeLayout(false);

}

#endregion

#region User Interface

private void Search_Click(object sender, System.EventArgs e)

{

googleSearch = false;

if (!parent.connected)

{

MessageBox.Show(this, "Not connected!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

if (comboBoxSearch.Text.Length < 2)

{

MessageBox.Show(this, "The searched word must be at least 2 letters long!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

try

{

if (Int32.Parse(textBox1.Text) < 0 || Int32.Parse(textBox2.Text) < 0)

{

throw new Exception("File Size must be greater than 0");

}

if (Int32.Parse(textBox2.Text) < Int32.Parse(textBox1.Text))

{

throw new Exception("The first number must be greater than the last one.");

}

}

catch (Exception ex)

{

MessageBox.Show(this,"File size error. " + ex.Message, "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

DnaSearch.EndSearch(currentSearchId);

listSearch.Items.Clear();

searchHash.Clear();

currentSearchId = DnaSearch.StartSearch(comboBoxSearch.Text);

if (!comboBoxSearch.Items.Contains(comboBoxSearch.Text))

{

comboBoxSearch.Items.Add(comboBoxSearch.Text);

}

currentSearchText = comboBoxSearch.Text;

label2.Text = "Search For '" + currentSearchText +"'";

Search.Enabled = false;

buttonEndSearch.Enabled = true;

label5.Text = "";

searchTime = DateTime.Now;

this.timer1.Enabled = true;

this.timer1.Interval = 1000;

// this.timer1.Interval = 1000 * SEARCH_TIME;

}

private void comboBoxSearch_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

googleSearch = false;

Search.Enabled = true;

Search.Text = "&Start Search";

if (e.KeyValue == 13)

{

Search_Click(null, null);

}

}

private void buttonEndSearch_Click(object sender, System.EventArgs e)

{

DnaSearch.EndSearch(currentSearchId);

Search.Enabled = true;

buttonEndSearch.Enabled = false;

this.timer1.Enabled = false;

}

private void buttonExit_Click(object sender, System.EventArgs e)

{

confirmDlg = new Confirm();

confirmDlg.ShowDialog(this);

if (confirmDlg.getButton())

Application.Exit();

}

private void buttonHelp_Click(object sender, System.EventArgs e)

{

aboutDlg = new About();

aboutDlg.ShowDialog();

}

private void buttonTraffic_Click(object sender, System.EventArgs e)

{

if (!parent.connected)

{

MessageBox.Show(this, "Not connected!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

parent.showTrafficDlg();

}

private void buttonConnections_Click(object sender, System.EventArgs e)

{

parent.showConnectionsDlg();

}

private void listSearch_DoubleClick(object sender, System.EventArgs e)

{

buttonDownload_Click(null, null);

}

private void buttonDownload_Click(object sender, System.EventArgs e)

{

if (!parent.connected)

{

MessageBox.Show(this, "Not connected!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

IEnumerator enumerator = listSearch.SelectedItems.GetEnumerator();

ListViewItem item1;

bool hasElements = false;

while (enumerator.MoveNext())

{

item1 = (ListViewItem)enumerator.Current;

item1.ImageIndex = 0;

DnaSearch.DownloadResult(currentSearchId, (int)item1.Tag);

trafficList.Add(DnaSearch.GetResultHash(currentSearchId, (int)item1.Tag, 0));

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

// Download clicked from the Context Menu of the Search list

private void menuItem1_Click(object sender, System.EventArgs e)

{

buttonDownload_Click(null, null);

}

// Cancel Download clicked from the Context Menu of the Search list

private void menuItem2_Click(object sender, System.EventArgs e)

{

if (!parent.connected)

{

MessageBox.Show(this, "Not connected!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

GnucDNA.Download DnaDownload = parent.getDnaDownload();

if (DnaDownload == null)

return;

bool hasElements = false;

IEnumerator enumerator = listSearch.SelectedItems.GetEnumerator();

ListViewItem item1;

IEnumerator enumerator2;

GLItem item2;

while (enumerator.MoveNext())

{

hasElements = true;

item1 = (ListViewItem)enumerator.Current;

item1.ImageIndex = -1;

int[] list = (int[])DnaDownload.GetDownloadIDs();

for (int i = 0; i < list.Length; i++)

{

if (DnaDownload.GetName(list[i]) == item1.Text)

{

if (parent.trafficDlg != null)

{

enumerator2 = parent.trafficDlg.getListViewTraffic().Items.GetEnumerator();

while (enumerator2.MoveNext())

{

item2 = (GLItem)enumerator2.Current;

if (DnaDownload.GetName(list[i]) == item2.Text)

{

parent.trafficDlg.getListViewTraffic().Items.Remove(item2);

parent.trafficDlg.nrFilesInTraffic–;

int nr = parent.trafficDlg.nrFilesInTraffic;

parent.trafficDlg.getLabel1().Text = "Traffic – " + nr.ToString() + " files";

break;

}

}

}

DnaDownload.Remove(list[i]);

break;

}

}

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

else

listSearch.Invalidate();

}

private void listSearch_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)

{

ascending = !ascending;

if (e.Column == 5)

listSearch.ListViewItemSorter = new ListViewItemComparer(e.Column, ascending, true);

else

listSearch.ListViewItemSorter = new ListViewItemComparer(e.Column, ascending, false);

listSearch.Sort();

}

// Properties clicked from the context menu associated with the Search Results List

private void menuItem3_Click(object sender, System.EventArgs e)

{

if (!parent.connected)

{

MessageBox.Show(this, "Not connected!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

return;

}

IEnumerator enumerator = listSearch.SelectedItems.GetEnumerator();

ListViewItem item1 = null;

bool hasElements = false;

if (enumerator.MoveNext())

{

item1 = (ListViewItem)enumerator.Current;

propertiesDlg = new FileProperties();

propertiesDlg.DnaSearch = this.DnaSearch;

propertiesDlg.currentSearchId = this.currentSearchId;

propertiesDlg.resultId = (int) item1.Tag;

propertiesDlg.inițializeItemValues();

propertiesDlg.ShowDialog();

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

private void checkBoxAudio_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void checkBoxVideo_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void checkBoxPicture_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void checkBoxDocument_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void checkBoxCompressed_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void checkBoxAnything_CheckedChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void textBox1_TextChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void textBox2_TextChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void comboBoxSearch_TextChanged(object sender, System.EventArgs e)

{

Search.Enabled = true;

Search.Text = "&Start Search";

}

private void buttonGoogleSearch_Click(object sender, System.EventArgs e)

{

googleSearch = true;

if (!comboBoxSearchGoogle.Items.Contains(comboBoxSearchGoogle.Text))

{

comboBoxSearchGoogle.Items.Add(comboBoxSearchGoogle.Text);

}

webBrowser = new WebBrowser();

webBrowser.Owner = this.parent;

webBrowser.Show();

webBrowser.GoogleSearch(comboBoxSearchGoogle.Text);

// System.Diagnostics.Process.Start("www.google.com/search?q=" + comboBoxSearchGoogle.Text);

}

private void comboBoxSearchGoogle_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

googleSearch = true;

if (e.KeyValue == 13)

{

buttonGoogleSearch_Click(null, null);

}

}

// This event occurs when the Enter key is pressed. This is the default button for the dialog

// but is not visibile

private void buttonDefault_Click(object sender, System.EventArgs e)

{

// decides after the last action which method to call

if (googleSearch)

{

buttonGoogleSearch_Click(null, null);

}

else

{

Search_Click(null, null);

}

}

#endregion

#region ISearch Events

private void DnaSearch_OnRefresh(int SearchId)

{

}

private void DnaSearch_OnResult(int SearchId, int ResultId)

{

string resultName;

String fileExtension;

long size;

string hash;

long hostCount;

int speed;

ListViewItem item1;

resultName = DnaSearch.GetResultName(SearchId, ResultId);

FileInfo fis = new FileInfo(resultName);

fileExtension = fis.Extension.Remove(0, 1).ToLower();

size = DnaSearch.GetResultSize(SearchId, ResultId);

hash = DnaSearch.GetResultHash(SearchId, ResultId, 0);

hostCount = DnaSearch.GetResultHostCount(SearchId, ResultId);

speed = DnaSearch.GetResultSpeed(SearchId, ResultId);

if ( hash == "" )

hash = "No";

else

hash = "Yes";

// checks if the file extesion is in the selected media types

if (!isSelected(fileExtension))

return;

// checks if the file size is in the selected range

if (!service.isFileSizeInRange(size, textBox1.Text, textBox2.Text, comboBox1.SelectedIndex))

return;

if ( searchHash.Contains(ResultId) )

{

item1 = (ListViewItem)searchHash[ResultId];

item1.SubItems[1].Text = fileExtension;

item1.SubItems[2].Text = knownExtensions.getMedia(fileExtension);

item1.SubItems[3].Text = service.formatSize(size);

item1.SubItems[4].Text = hash;

item1.SubItems[5].Text = hostCount.ToString();

item1.SubItems[6].Text = speed.ToString() + " KB/s";

}

else

{

item1 = new ListViewItem(resultName);

item1.Tag = ResultId;

item1.SubItems.Add(fileExtension);

item1.SubItems.Add(knownExtensions.getMedia(fileExtension));

item1.SubItems.Add(service.formatSize(size));

item1.SubItems.Add(hash);

item1.SubItems.Add(hostCount.ToString());

item1.SubItems.Add(speed.ToString() + " KB/s");

if ( trafficList.Contains(DnaSearch.GetResultHash(currentSearchId, ResultId, 0)) )

{

item1.ImageIndex = 0;

}

listSearch.Items.Add(item1);

searchHash.Add(ResultId,item1);

setLabel2Text(searchHash.Count.ToString());

}

}

private void DnaSearch_OnUpdate(int SearchId, int ResultId)

{

if ( searchHash.Contains(ResultId) )

{

ListViewItem item1 = (ListViewItem)searchHash[ResultId];

long size = DnaSearch.GetResultSize(SearchId, ResultId);

string hash = DnaSearch.GetResultHash(SearchId, ResultId, 0);

long hostCount = DnaSearch.GetResultHostCount(SearchId, ResultId);

int speed = DnaSearch.GetResultSpeed(SearchId, ResultId);

FileInfo fis = new FileInfo(item1.Text);

String fileExtension = fis.Extension.Remove(0, 1).ToLower();

if ( hash == "" )

hash = "No";

else

hash = "Yes";

item1.SubItems[1].Text = fileExtension;

item1.SubItems[2].Text = knownExtensions.getMedia(fileExtension);

item1.SubItems[3].Text = service.formatSize(size);

item1.SubItems[4].Text = hash;

item1.SubItems[5].Text = hostCount.ToString();

item1.SubItems[6].Text = speed.ToString() + " KB/s";

}

}

#endregion

public void Disconnect()

{

buttonEndSearch_Click(null, null);

}

private void SearchResult_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

DnaSearch.EndSearch(currentSearchId);

parent.searchResultDlg = null;

DnaSearch.OnRefresh -= new GnucDNA._ISearchEvent_OnRefreshEventHandler(DnaSearch_OnRefresh);

DnaSearch.OnResult -= new GnucDNA._ISearchEvent_OnResultEventHandler(DnaSearch_OnResult);

DnaSearch.OnUpdate -= new GnucDNA._ISearchEvent_OnUpdateEventHandler(DnaSearch_OnUpdate);

}

public void setLabel2Text(string str)

{

label2.Text = "Search For '" + currentSearchText + "' – " + str + " Results Found";

}

private void timer1_Tick(object sender, System.EventArgs e)

{

TimeSpan time = DateTime.Now – searchTime;

String strHours = time.Hours.ToString().Length == 2 ? time.Hours.ToString() : "0" + time.Hours.ToString();

String strMinutes = time.Minutes.ToString().Length == 2 ? time.Minutes.ToString() : "0" + time.Minutes.ToString();

String strSeconds = time.Seconds.ToString().Length == 2 ? time.Seconds.ToString() : "0" + time.Seconds.ToString();

label5.Text = strHours + ":" + strMinutes + ":" + strSeconds;

/* if (time.Seconds < 21 && time.Minutes == 0 && time.Hours == 0)

{

MessageBox.Show(time.Seconds + " – " + searchHash.Count.ToString());

}*/

/* Search.Enabled = true;

buttonEndSearch.Enabled = false;

DnaSearch.EndSearch(currentSearchId);

this.timer1.Enabled = false;*/

}

private bool isSelected(String ext)

{

if (checkBoxAudio.Checked && knownExtensions.getAudioExtensionsSupported().Contains(ext))

{

return true;

}

if (checkBoxVideo.Checked && knownExtensions.getVideoExtensionsSupported().Contains(ext))

{

return true;

}

if (checkBoxPicture.Checked && knownExtensions.getPictureExtensionsSupported().Contains(ext))

{

return true;

}

if (checkBoxDocument.Checked && knownExtensions.getDocumentExtensionsSupported().Contains(ext))

{

return true;

}

if (checkBoxCompressed.Checked && knownExtensions.getCompressedExtensionsSupported().Contains(ext))

{

return true;

}

if (checkBoxAnything.Checked && !knownExtensions.getAudioExtensionsSupported().Contains(ext) && !knownExtensions.getVideoExtensionsSupported().Contains(ext) && !knownExtensions.getPictureExtensionsSupported().Contains(ext) && !knownExtensions.getDocumentExtensionsSupported().Contains(ext) && !knownExtensions.getCompressedExtensionsSupported().Contains(ext))

{

return true;

}

return false;

}

private void SearchResult_Activated(object sender, System.EventArgs e)

{

GnucDNA.Download DnaDownload = parent.getDnaDownload();

if (DnaDownload != null)

{

trafficList = new ArrayList();

int[] downloadsList = (int[])DnaDownload.GetDownloadIDs();

for (int i = 0; i < downloadsList.Length; i++)

{

trafficList.Add( DnaDownload.GetHash(downloadsList[i], 0) );

}

}

}

}

}

Service.cs

using System;

namespace GDownloader

{

/// <summary>

///

/// </summary>

///this class manages all the informațion formating for proper displaying

public class Service

{

public Service()

{

//

// TODO: Add constructor logic here

//

}

public string formatSize(long size)

{

string str = "";

float val = 0 ;

if (size > 1024*1024*1024)

{

val = (float)size/(1024*1024*1024);

str = val.ToString("n") + " GB";

}

else

if (size > 1024*1024)

{

val = (float)size/(1024*1024);

str = val.ToString("n") + " MB";

}

else

if (size > 1024)

{

val = (float)size/1024;

str = val.ToString("n") + " KB";

}

else

str = size.ToString("n") + " B";

return str;

}

// checks if a specified file size is in the entered range

// sizeUnit is the value unit of the file size: giga = 3; mega = 2; kilo = 1; byte = 0;

public bool isFileSizeInRange(long size, string strMinValue, string strMaxValue, int sizeUnit)

{

long min = Convert.ToInt64(strMinValue);

long max = Convert.ToInt64(strMaxValue);

// checks if the size in expressed in Giga Bytes

if (sizeUnit == 3)

{

min *= 1024 * 1024 * 1024;

max *= 1024 * 1024 * 1024;

}

// checks if the size in expressed in Mega Bytes

else

if (sizeUnit == 2)

{

min *= 1024 * 1024;

max *= 1024 * 1024;

}

// checks if the size in expressed in Kilo Bytes

else

if (sizeUnit == 1)

{

min *= 1024;

max *= 1024;

}

if ( (size >= min) && (size <= max))

return true;

return false;

}

// formats for a fine displaying the estimated time for a download completion

// eta the number of seconds

public string formatEta(int eta)

{

string val = "";

if (eta > 3600)

{

int h = eta / 3600;

int min = (eta % 3600) / 60;

int sec = (eta % 3600) % 60;

val = h.ToString() + "h, " + min.ToString() + "min, " + sec.ToString() + "sec";

}

else

{

if (eta > 60)

{

int min = eta / 60;

int sec = eta % 60;

val = min.ToString() + "min, " + sec.ToString() + "sec";

}

else

{

if (eta > 0)

{

val = eta.ToString() + "sec";

}

}

}

return val;

}

}

}

Traffic.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using GlacialComponents.Controls;

namespace GDownloader

{

/// <summary>

/// Summary description for Traffic.

/// </summary>

public class Traffic : System.Windows.Forms.Form

{

private Hashtable downloadHash;

public MainForm parent;

public int nrFilesInTraffic;

private GnucDNA.Download DnaDownload;

private Service service;

private FilePropertiesTraffic propertiesDlg;

private About aboutDlg;

private Confirm confirmDlg;

private PinkieControls.ButtonXP Search;

private PinkieControls.ButtonXP buttonConnections;

private PinkieControls.ButtonXP buttonHelp;

private PinkieControls.ButtonXP buttonExit;

private GlacialComponents.Controls.GlacialList listViewTraffic;

private PinkieControls.ButtonXP buttonTraffic;

private PinkieControls.ButtonXP buttonClearCompleted;

private PinkieControls.ButtonXP buttonCancelDownload;

private System.Windows.Forms.ContextMenu contextMenu1;

private System.Windows.Forms.MenuItem menuItem1;

private System.Windows.Forms.MenuItem menuItem2;

private System.Windows.Forms.MenuItem menuItem3;

private System.Windows.Forms.MenuItem menuItem4;

private PinkieControls.ButtonXP buttonRunFile;

private System.Windows.Forms.Label label1;

private System.Windows.Forms.MenuItem menuItem5;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public Traffic()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

downloadHash = new Hashtable();

nrFilesInTraffic = 0;

label1.Text = "Traffic – " + nrFilesInTraffic.ToString() + " Files";

service = new Service();

}

public void InițializeDownload()

{

DnaDownload = parent.getDnaDownload();

DnaDownload.OnUpdate += new GnucDNA._IDownloadEvent_OnUpdateEventHandler(DnaDownload_OnUpdate);

populateTrafficList();

}

private void populateTrafficList()

{

int[] list = (int[])DnaDownload.GetDownloadIDs();

for (int i = 0; i < list.Length; i++)

{

DnaDownload_OnUpdate(list[i]);

}

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Traffic));

GlacialComponents.Controls.GLColumn glColumn1 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn2 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn3 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn4 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn5 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn6 = new GlacialComponents.Controls.GLColumn();

GlacialComponents.Controls.GLColumn glColumn7 = new GlacialComponents.Controls.GLColumn();

this.Search = new PinkieControls.ButtonXP();

this.buttonConnections = new PinkieControls.ButtonXP();

this.buttonHelp = new PinkieControls.ButtonXP();

this.buttonExit = new PinkieControls.ButtonXP();

this.listViewTraffic = new GlacialComponents.Controls.GlacialList();

this.contextMenu1 = new System.Windows.Forms.ContextMenu();

this.menuItem1 = new System.Windows.Forms.MenuItem();

this.menuItem2 = new System.Windows.Forms.MenuItem();

this.menuItem3 = new System.Windows.Forms.MenuItem();

this.menuItem4 = new System.Windows.Forms.MenuItem();

this.menuItem5 = new System.Windows.Forms.MenuItem();

this.buttonTraffic = new PinkieControls.ButtonXP();

this.buttonClearCompleted = new PinkieControls.ButtonXP();

this.buttonCancelDownload = new PinkieControls.ButtonXP();

this.buttonRunFile = new PinkieControls.ButtonXP();

this.label1 = new System.Windows.Forms.Label();

this.SuspendLayout();

//

// Search

//

this.Search.AccessibleRole = System.Windows.Forms.AccessibleRole.PushButton;

this.Search.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.Search.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.Search.DefaultScheme = true;

this.Search.DialogResult = System.Windows.Forms.DialogResult.None;

this.Search.Hint = "Shows Search Dialog";

this.Search.Image = ((System.Drawing.Image)(resources.GetObject("Search.Image")));

this.Search.Location = new System.Drawing.Point(140, 618);

this.Search.Name = "Search";

this.Search.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.Search.Size = new System.Drawing.Size(95, 30);

this.Search.TabIndex = 15;

this.Search.Text = "&Search";

this.Search.Click += new System.EventHandler(this.Search_Click);

//

// buttonConnections

//

this.buttonConnections.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonConnections.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonConnections.DefaultScheme = true;

this.buttonConnections.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonConnections.Hint = "Shows Connections Dialog";

this.buttonConnections.Image = ((System.Drawing.Image)(resources.GetObject("buttonConnections.Image")));

this.buttonConnections.Location = new System.Drawing.Point(16, 618);

this.buttonConnections.Name = "buttonConnections";

this.buttonConnections.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonConnections.Size = new System.Drawing.Size(95, 30);

this.buttonConnections.TabIndex = 16;

this.buttonConnections.Text = "&Connections";

this.buttonConnections.Click += new System.EventHandler(this.buttonConnections_Click);

//

// buttonHelp

//

this.buttonHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonHelp.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonHelp.DefaultScheme = true;

this.buttonHelp.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonHelp.Hint = "GDownloader Help";

this.buttonHelp.Image = ((System.Drawing.Image)(resources.GetObject("buttonHelp.Image")));

this.buttonHelp.Location = new System.Drawing.Point(608, 618);

this.buttonHelp.Name = "buttonHelp";

this.buttonHelp.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonHelp.Size = new System.Drawing.Size(95, 30);

this.buttonHelp.TabIndex = 18;

this.buttonHelp.Text = "&Help";

this.buttonHelp.Click += new System.EventHandler(this.buttonHelp_Click);

//

// buttonExit

//

this.buttonExit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));

this.buttonExit.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonExit.DefaultScheme = true;

this.buttonExit.DialogResult = System.Windows.Forms.DialogResult.Cancel;

this.buttonExit.Hint = "Exit GDownloader";

this.buttonExit.Image = ((System.Drawing.Image)(resources.GetObject("buttonExit.Image")));

this.buttonExit.Location = new System.Drawing.Point(732, 618);

this.buttonExit.Name = "buttonExit";

this.buttonExit.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonExit.Size = new System.Drawing.Size(95, 30);

this.buttonExit.TabIndex = 17;

this.buttonExit.Text = "&Exit";

this.buttonExit.Click += new System.EventHandler(this.buttonExit_Click);

//

// listViewTraffic

//

this.listViewTraffic.AllowColumnResize = true;

this.listViewTraffic.AllowMultiselect = true;

this.listViewTraffic.AlternateBackground = System.Drawing.Color.DarkGreen;

this.listViewTraffic.AlternatingColors = false;

this.listViewTraffic.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.listViewTraffic.AutoHeight = true;

this.listViewTraffic.BackColor = System.Drawing.SystemColors.Window;

this.listViewTraffic.BackgroundStretchToFit = true;

glColumn1.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn1.CheckBoxes = false;

glColumn1.ImageIndex = -1;

glColumn1.Name = "File";

glColumn1.NumericSort = false;

glColumn1.Text = "File";

glColumn1.TextAlignment = System.Drawing.ContentAlignment.MiddleLeft;

glColumn1.Width = 340;

glColumn2.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn2.CheckBoxes = false;

glColumn2.ImageIndex = -1;

glColumn2.Name = "Status";

glColumn2.NumericSort = false;

glColumn2.Text = "Status";

glColumn2.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn2.Width = 120;

glColumn3.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn3.CheckBoxes = false;

glColumn3.ImageIndex = -1;

glColumn3.Name = "Download";

glColumn3.NumericSort = false;

glColumn3.Text = "Download";

glColumn3.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn3.Width = 200;

glColumn4.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn4.CheckBoxes = false;

glColumn4.ImageIndex = -1;

glColumn4.Name = "Size";

glColumn4.NumericSort = false;

glColumn4.Text = "Size";

glColumn4.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn4.Width = 120;

glColumn5.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn5.CheckBoxes = false;

glColumn5.ImageIndex = -1;

glColumn5.Name = "Completed";

glColumn5.NumericSort = false;

glColumn5.Text = "Completed";

glColumn5.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn5.Width = 100;

glColumn6.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn6.CheckBoxes = false;

glColumn6.ImageIndex = -1;

glColumn6.Name = "Speed";

glColumn6.NumericSort = false;

glColumn6.Text = "Speed";

glColumn6.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn6.Width = 100;

glColumn7.ActivatedEmbeddedType = GlacialComponents.Controls.GLActivatedEmbeddedTypes.None;

glColumn7.CheckBoxes = false;

glColumn7.ImageIndex = -1;

glColumn7.Name = "Estimated_Time";

glColumn7.NumericSort = false;

glColumn7.Text = "Estimated Time";

glColumn7.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;

glColumn7.Width = 110;

this.listViewTraffic.Columns.AddRange(new GlacialComponents.Controls.GLColumn[] {

glColumn1,

glColumn2,

glColumn3,

glColumn4,

glColumn5,

glColumn6,

glColumn7});

this.listViewTraffic.ContextMenu = this.contextMenu1;

this.listViewTraffic.ControlStyle = GlacialComponents.Controls.GLControlStyles.Normal;

this.listViewTraffic.FullRowSelect = true;

this.listViewTraffic.GridColor = System.Drawing.Color.Transparent;

this.listViewTraffic.GridLines = GlacialComponents.Controls.GLGridLines.gridHorizontal;

this.listViewTraffic.GridLineStyle = GlacialComponents.Controls.GLGridLineStyles.gridSolid;

this.listViewTraffic.GridTypes = GlacialComponents.Controls.GLGridTypes.gridOnExists;

this.listViewTraffic.HeaderHeight = 18;

this.listViewTraffic.HeaderVisible = true;

this.listViewTraffic.HeaderWordWrap = false;

this.listViewTraffic.HotColumnTracking = false;

this.listViewTraffic.HotItemTracking = false;

this.listViewTraffic.HotTrackingColor = System.Drawing.Color.LightGray;

this.listViewTraffic.HoverEvents = false;

this.listViewTraffic.HoverTime = 1;

this.listViewTraffic.ImageList = null;

this.listViewTraffic.ItemHeight = 17;

this.listViewTraffic.ItemWordWrap = false;

this.listViewTraffic.Location = new System.Drawing.Point(16, 80);

this.listViewTraffic.Name = "listViewTraffic";

this.listViewTraffic.Selectable = true;

this.listViewTraffic.SelectedTextColor = System.Drawing.Color.White;

this.listViewTraffic.SelectionColor = System.Drawing.Color.MidnightBlue;

this.listViewTraffic.ShowBorder = true;

this.listViewTraffic.ShowFocusRect = false;

this.listViewTraffic.Size = new System.Drawing.Size(816, 474);

this.listViewTraffic.SortType = GlacialComponents.Controls.SortTypes.InsertionSort;

this.listViewTraffic.SuperFlatHeaderColor = System.Drawing.Color.White;

this.listViewTraffic.TabIndex = 19;

this.listViewTraffic.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listViewTraffic_KeyDown);

//

// contextMenu1

//

this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {

this.menuItem1,

this.menuItem2,

this.menuItem3,

this.menuItem4,

this.menuItem5});

//

// menuItem1

//

this.menuItem1.Index = 0;

this.menuItem1.Text = "Cancel Download";

this.menuItem1.Click += new System.EventHandler(this.menuItem1_Click);

//

// menuItem2

//

this.menuItem2.Index = 1;

this.menuItem2.Text = "Start Transfer";

this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);

//

// menuItem3

//

this.menuItem3.Index = 2;

this.menuItem3.Text = "Stop Transfer";

this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);

//

// menuItem4

//

this.menuItem4.Index = 3;

this.menuItem4.Text = "Run File";

this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);

//

// menuItem5

//

this.menuItem5.Index = 4;

this.menuItem5.Text = "Properties";

this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);

//

// buttonTraffic

//

this.buttonTraffic.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonTraffic.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonTraffic.DefaultScheme = true;

this.buttonTraffic.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonTraffic.Enabled = false;

this.buttonTraffic.Hint = "Shows Traffic Dialog";

this.buttonTraffic.Image = ((System.Drawing.Image)(resources.GetObject("buttonTraffic.Image")));

this.buttonTraffic.Location = new System.Drawing.Point(264, 618);

this.buttonTraffic.Name = "buttonTraffic";

this.buttonTraffic.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonTraffic.Size = new System.Drawing.Size(95, 30);

this.buttonTraffic.TabIndex = 20;

this.buttonTraffic.Text = "Traffic";

//

// buttonClearCompleted

//

this.buttonClearCompleted.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonClearCompleted.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonClearCompleted.DefaultScheme = true;

this.buttonClearCompleted.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonClearCompleted.Hint = "Clears all completed downloads";

this.buttonClearCompleted.Location = new System.Drawing.Point(264, 562);

this.buttonClearCompleted.Name = "buttonClearCompleted";

this.buttonClearCompleted.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonClearCompleted.Size = new System.Drawing.Size(95, 30);

this.buttonClearCompleted.TabIndex = 22;

this.buttonClearCompleted.Text = "C&lear Completed";

this.buttonClearCompleted.Click += new System.EventHandler(this.buttonClearCompleted_Click);

//

// buttonCancelDownload

//

this.buttonCancelDownload.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonCancelDownload.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonCancelDownload.DefaultScheme = true;

this.buttonCancelDownload.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonCancelDownload.Hint = "Cancels downloading the selected files";

this.buttonCancelDownload.Location = new System.Drawing.Point(140, 562);

this.buttonCancelDownload.Name = "buttonCancelDownload";

this.buttonCancelDownload.RightToLeft = System.Windows.Forms.RightToLeft.No;

this.buttonCancelDownload.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonCancelDownload.Size = new System.Drawing.Size(95, 30);

this.buttonCancelDownload.TabIndex = 23;

this.buttonCancelDownload.Text = "C&ancel Download";

this.buttonCancelDownload.Click += new System.EventHandler(this.buttonCancelDownload_Click);

//

// buttonRunFile

//

this.buttonRunFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));

this.buttonRunFile.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(0)), ((System.Byte)(212)), ((System.Byte)(208)), ((System.Byte)(200)));

this.buttonRunFile.DefaultScheme = true;

this.buttonRunFile.DialogResult = System.Windows.Forms.DialogResult.None;

this.buttonRunFile.Hint = "Runs the selected file";

this.buttonRunFile.Location = new System.Drawing.Point(16, 562);

this.buttonRunFile.Name = "buttonRunFile";

this.buttonRunFile.Scheme = PinkieControls.ButtonXP.Schemes.Silver;

this.buttonRunFile.Size = new System.Drawing.Size(95, 30);

this.buttonRunFile.TabIndex = 24;

this.buttonRunFile.Text = "&Run File";

this.buttonRunFile.Click += new System.EventHandler(this.buttonRunFile_Click);

//

// label1

//

this.label1.BackColor = System.Drawing.SystemColors.Control;

this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

this.label1.Location = new System.Drawing.Point(16, 28);

this.label1.Name = "label1";

this.label1.Size = new System.Drawing.Size(368, 23);

this.label1.TabIndex = 25;

this.label1.Text = "Traffic – ";

//

// Traffic

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(848, 663);

this.Controls.Add(this.label1);

this.Controls.Add(this.buttonRunFile);

this.Controls.Add(this.buttonCancelDownload);

this.Controls.Add(this.buttonClearCompleted);

this.Controls.Add(this.buttonTraffic);

this.Controls.Add(this.listViewTraffic);

this.Controls.Add(this.buttonHelp);

this.Controls.Add(this.buttonExit);

this.Controls.Add(this.Search);

this.Controls.Add(this.buttonConnections);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(630, 300);

this.Name = "Traffic";

this.Text = "Traffic";

this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

this.Closing += new System.ComponentModel.CancelEventHandler(this.Traffic_Closing);

this.ResumeLayout(false);

}

#endregion

#region User Interface

private void buttonExit_Click(object sender, System.EventArgs e)

{

confirmDlg = new Confirm();

confirmDlg.ShowDialog(this);

if (confirmDlg.getButton())

Application.Exit();

}

private void buttonHelp_Click(object sender, System.EventArgs e)

{

aboutDlg = new About();

aboutDlg.ShowDialog();

}

private void Search_Click(object sender, System.EventArgs e)

{

parent.showSearchDlg();

}

private void buttonConnections_Click(object sender, System.EventArgs e)

{

parent.showConnectionsDlg();

}

private void buttonClearCompleted_Click(object sender, System.EventArgs e)

{

DnaDownload.RemoveCompleted();

}

private void buttonCancelDownload_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewTraffic.SelectedItems.GetEnumerator();

GLItem item1;

bool hasElements = false;

while (enumerator.MoveNext())

{

item1 = (GLItem)enumerator.Current;

item1.SubItems[1].Text = "ss";

downloadHash.Remove(item1.Tag);

DnaDownload.Remove((int)item1.Tag);

listViewTraffic.Items.Remove(item1);

nrFilesInTraffic–;

label1.Text = "Traffic – " + nrFilesInTraffic.ToString() + " Files";

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

private void buttonRunFile_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewTraffic.SelectedItems.GetEnumerator();

GLItem item1;

bool hasElements = false;

while (enumerator.MoveNext())

{

item1 = (GLItem)enumerator.Current;

DnaDownload.RunFile((int)item1.Tag);

// MessageBox.Show(DnaDownload.GetActiveSourceCount((int)item1.Tag).ToString());

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

// Cancel Download clicked from the context menu associated with the Traffic ListView

private void menuItem1_Click(object sender, System.EventArgs e)

{

buttonCancelDownload_Click(null, null);

}

// Start Transfer clicked from the context menu associated with the Traffic ListView

private void menuItem2_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewTraffic.SelectedItems.GetEnumerator();

GLItem item1;

bool hasElements = false;

while (enumerator.MoveNext())

{

item1 = (GLItem)enumerator.Current;

DnaDownload.ForceStart((int)item1.Tag);

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

// Stop Transfer clicked from the context menu associated with the Traffic ListView

private void menuItem3_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewTraffic.SelectedItems.GetEnumerator();

GLItem item1;

bool hasElements = false;

while (enumerator.MoveNext())

{

item1 = (GLItem)enumerator.Current;

DnaDownload.Stop((int)item1.Tag);

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

// Run File clicked from the context menu associated with the Traffic ListView

private void menuItem4_Click(object sender, System.EventArgs e)

{

buttonRunFile_Click(null, null);

}

private void listViewTraffic_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

if (e.KeyValue == 46)

buttonCancelDownload_Click(null, null);

}

// Properties clicked from the context menu associated with the Traffic List

private void menuItem5_Click(object sender, System.EventArgs e)

{

IEnumerator enumerator = listViewTraffic.SelectedItems.GetEnumerator();

GLItem item1;

bool hasElements = false;

if (enumerator.MoveNext())

{

item1 = (GLItem)enumerator.Current;

propertiesDlg = new FilePropertiesTraffic();

propertiesDlg.DnaDownload = this.DnaDownload;

propertiesDlg.downloadId = (int) item1.Tag;

propertiesDlg.inițializeItemValues();

propertiesDlg.ShowDialog();

hasElements = true;

}

if (!hasElements)

MessageBox.Show(this, "You must first select a file from the list!", "GDownloader", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

#endregion

#region IDownload Events

private void DnaDownload_OnUpdate(int DownloadId)

{

string fileName = DnaDownload.GetName(DownloadId);

string status = "";

switch ( DnaDownload.GetStatus(DownloadId) )

{

case 1:

status = "No Sources";

break;

case 2:

status = "Pending";

break;

case 3:

status = "Connecting";

break;

case 4:

status = "Connected";

break;

case 5:

status = "Sending";

break;

case 6:

status = "Receiving";

break;

case 7:

status = "Push";

break;

case 8:

status = "Stoped";

break;

case 9:

status = "Completed";

break;

case 10:

status = "Cooling Down";

break;

case 11:

status = "Queued";

break;

}

int fileLength = DnaDownload.GetFileLength(DownloadId);

int completed = DnaDownload.GetBytesCompleted(DownloadId);

int speed = DnaDownload.GetBytesPerSec(DownloadId);

string strSpeed = "";

if (speed > 0)

{

strSpeed = service.formatSize(speed) + "/s";

}

int eta = DnaDownload.GetSecETA(DownloadId);

float percent = (float)completed/fileLength*100;

MyProgressBar pb = null;

GLItem item1 = null;

if ( downloadHash.Contains(DownloadId) )

{

item1 = (GLItem)downloadHash[DownloadId];

item1.SubItems[1].Text = status;

pb = (MyProgressBar)item1.SubItems[2].Control;

pb.Value = (int)percent;

item1.SubItems[3].Text = service.formatSize(fileLength);

item1.SubItems[4].Text = service.formatSize(completed);

item1.SubItems[5].Text = strSpeed;

item1.SubItems[6].Text = service.formatEta(eta);

}

else

{

pb = new MyProgressBar();

pb.BackColor = System.Drawing.SystemColors.Control;

pb.ProgressBarColor = Color.FromArgb(150, 150 , 255);

pb.TextColor = Color.Black;

pb.Value = (int)percent;

item1 = new GLItem();

item1.Tag = DownloadId;

item1.Text = fileName;

item1.SubItems[1].Text = status;

item1.SubItems[2].Control = pb;

item1.SubItems[3].Text = service.formatSize(fileLength);

item1.SubItems[4].Text = service.formatSize(completed);

item1.SubItems[5].Text = strSpeed;

item1.SubItems[6].Text = service.formatEta(eta);

listViewTraffic.Items.Add(item1);

downloadHash.Add(DownloadId, item1);

nrFilesInTraffic++;

label1.Text = "Traffic – " + nrFilesInTraffic.ToString() + " Files";

}

}

#endregion

private void Traffic_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

parent.trafficDlg = null;

DnaDownload.OnUpdate -= new GnucDNA._IDownloadEvent_OnUpdateEventHandler(DnaDownload_OnUpdate);

}

public GlacialList getListViewTraffic()

{

return listViewTraffic;

}

public Label getLabel1()

{

return label1;

}

}

}

WebBrowser.cs

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using mshtml;

namespace GDownloader

{

/// <summary>

/// Summary description for WebBrowser.

/// </summary>

public class WebBrowser : System.Windows.Forms.Form

{

private bool googleSearch;

private string googleQuery;

private AxSHDocVw.AxWebBrowser axWebBrowser1;

/// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;

public WebBrowser()

{

//

// Required for Windows Form Designer support

//

InițializeComponent();

//

// TODO: Add any constructor code after InițializeComponent call

//

googleSearch = false;

googleQuery = null;

}

/// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if(components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

/// <summary>

/// Required method for Designer support – do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InițializeComponent()

{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(WebBrowser));

this.axWebBrowser1 = new AxSHDocVw.AxWebBrowser();

((System.ComponentModel.ISupportInițialize)(this.axWebBrowser1)).BeginInit();

this.SuspendLayout();

//

// axWebBrowser1

//

this.axWebBrowser1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)

| System.Windows.Forms.AnchorStyles.Left)

| System.Windows.Forms.AnchorStyles.Right)));

this.axWebBrowser1.Enabled = true;

this.axWebBrowser1.Location = new System.Drawing.Point(0, 0);

this.axWebBrowser1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axWebBrowser1.OcxState")));

this.axWebBrowser1.Size = new System.Drawing.Size(832, 608);

this.axWebBrowser1.TabIndex = 0;

this.axWebBrowser1.DocumentComplete += new AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(this.axWebBrowser1_DocumentComplete);

//

// WebBrowser

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(832, 605);

this.Controls.Add(this.axWebBrowser1);

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

this.MinimumSize = new System.Drawing.Size(100, 100);

this.Name = "WebBrowser";

this.ShowInTaskbar = false;

this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;

this.Text = "GDownloader – Web Browser";

((System.ComponentModel.ISupportInițialize)(this.axWebBrowser1)).EndInit();

this.ResumeLayout(false);

}

#endregion

public void Navigate(String address)

{

object loc = address;

object null_obj_str = "";

System.Object null_obj = 0;

this.axWebBrowser1.Navigate2(ref loc , ref null_obj, ref null_obj, ref null_obj_str, ref null_obj_str);

}

public void GoogleSearch(String query)

{

object loc = "www.google.com";

object null_obj_str = "";

System.Object null_obj = 0;

this.axWebBrowser1.Navigate2(ref loc , ref null_obj, ref null_obj, ref null_obj_str, ref null_obj_str);

googleSearch = true;

googleQuery = query;

}

// occurs when the page was completly loaded

private void axWebBrowser1_DocumentComplete(object sender, AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent e)

{

if (googleSearch)

{

HTMLDocument myDoc = new HTMLDocumentClass();

myDoc = (HTMLDocument) axWebBrowser1.Document;

// a quick look at the google html source reveals:

// <input maxLength="256" size="55" name="q">

HTMLInputElement otxtSearchBox = (HTMLInputElement) myDoc.all.item("q", 0);

otxtSearchBox.value = googleQuery;

// google html source for the Google Search Button:

// <input type=submit value="Google Search" name=btnG>

HTMLInputElement btnSearch = (HTMLInputElement) myDoc.all.item("btnG", 0);

btnSearch.click();

googleSearch = false;

}

}

}

}

7. Bibliografie

[1] Knuth, Donald, The Art of Computer Programming, Volume 3: Sorting and Searching, Second Edition, Addison-Wesley, pp. 513-558, 1998.

[2] Hector Garcia-Molina, Peer-To-Peer Data Management. ICDE Conference, February 28, 2002

[3] Mayank Bawa, Brian F Cooper, Arturo Crespo, Neil Daswani, Prasanna Ganesan, Hector Garcia-Molina. Peer-to-Peer Research at Stanford, Computer Science Department, Stanford University.

[4] Beverly Yang, Hector Garcia-Molina, Improving Search în Peer-to-Peer Networks, Computer Science Department, Stanford University.

[5] Neil Daswani, Hector Garcia-Molina, Beverly Yang, Open Problems în Data-Sharing Peer-to-Peer Systems, Computer Science Department, Stanford University.

[6] L.R. Ford and D.R. Fulkerson. Flows în Networks. Princeton University Press, Princeton, NJ, 1962.

[7] R.E. Bellman. Dynamic Programming. Princeton University Press, Princeton,

NJ, 1957.

[8] C. K. Miller. Multicast Networking and Applications. Addison Wesley, 1998.

[9] Gurmeet Singh Manku, Mayank Bawa, Prabhakar Raghava, Symphony: Distributed Hashing în A Small World, Computer Science Department, Stanford University.

[10] Neil Daswani, Hector Garcia-Molina, Query-Flood DoS Attacks în Gnutella, Computer Science Department, Stanford University.

[11] Yahoo! Site. World-wide web: http://www.yahoo.com.

[12] GNU Operațing System – Free Software Foundation. World-wide web: http://www.gnu.org

[13] Freenet. At http://freenet.sourceforge.com.

[14] Google. World-wide web: http://www.google.com.

[15] W3Schools web site. Introduction to DHTML. World-wide web: http://www.w3schools.com/dhtml/dhtml_intro.asp

[16] Microsoft web site. Web Development. HTML and Dynamic HTML. http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/dhtml _node_entry.asp

[17] Kazaa web site. World-wide web: http://www.kazaa.com

[18] Napster. World-wide web: http://www.napster.com. Napster Home Page.

[19] Gnutella.World-wide web: http://gnutella.wego.com. Gnutella Development Page.

[20] Seti@Home. World-wide web: http://setiathome.ssl.berkeley.edu. Seti At Home Page.

[21] Gnutella site. World-wide web: http://www.gnutella.com/.

[22] Free Definition site. World-wide web:

http://www.free-definition.com/Gnutella.html.

[23] Morpheus web site. World-wide web: http://www.morpheus.com .

[24] The Stanford Peers Home Page. World-wide web:

http://www-db.stanford.edu/peers/

Similar Posts