1 package org.xvsm.lookup.gnutella;
2
3 import java.io.IOException;
4 import java.io.ObjectInputStream;
5 import java.io.ObjectOutputStream;
6 import java.net.BindException;
7 import java.net.InetAddress;
8 import java.net.InetSocketAddress;
9 import java.net.Socket;
10 import java.net.SocketAddress;
11 import java.net.UnknownHostException;
12 import java.util.ArrayList;
13 import java.util.Hashtable;
14
15 import org.xvsm.lookup.gnutella.exceptions.NotFoundException;
16 import org.xvsm.lookup.gnutella.objects.GnutellaRequest;
17 import org.xvsm.lookup.gnutella.threads.ListenerThread;
18
19 /***
20 * Is the class that handles the Gnutella functions of a peer.
21 *
22 * @author Hannu-Daniel Goiss
23 */
24 public class GnutellaPeer {
25 private Hashtable<String, Object> list = new Hashtable<String, Object>();
26 private ListenerThread listenerThread = null;
27 private Hashtable<String, Object> answer = new Hashtable<String, Object>();
28 private ArrayList<SocketAddress> peer = new ArrayList<SocketAddress>();
29 private int localPort;
30 private String serverIp;
31 private int serverPort;
32
33 /***
34 * starting a standalone peer. Simply used for testing
35 *
36 * @param args
37 * @throws IOException
38 * @throws ClassNotFoundException
39 */
40 public static void main(String[] args) throws IOException,
41 ClassNotFoundException {
42 new GnutellaPeer(4600, "localhost", 4500);
43 }
44
45 /***
46 * Constructor to initiate a peer using the local port and the server
47 * ip-address as well as the port of the server
48 *
49 * @param port
50 * @param serverIp
51 * @param serverPort
52 * @throws UnknownHostException
53 * @throws IOException
54 * @throws ClassNotFoundException
55 */
56 public GnutellaPeer(int port, String serverIp, int serverPort)
57 throws UnknownHostException, IOException, ClassNotFoundException {
58 this.localPort = port;
59 this.serverIp = serverIp;
60 this.serverPort = serverPort;
61
62 listenerThread = new ListenerThread(localPort, this);
63 listenerThread.start();
64
65 this.connect();
66 }
67
68 /***
69 * connects the peer to the server to retrieve some addresses of other peers
70 *
71 * @throws UnknownHostException
72 * @throws IOException
73 * @throws ClassNotFoundException
74 */
75 public void connect() throws UnknownHostException, IOException,
76 ClassNotFoundException {
77 Socket socket = new Socket(serverIp, serverPort);
78
79 ObjectOutputStream oos = new ObjectOutputStream(socket
80 .getOutputStream());
81 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
82
83 oos.writeObject(new Integer(localPort));
84
85 peer = (ArrayList<SocketAddress>) ois.readObject();
86
87 socket.close();
88 }
89
90 /***
91 * returns the list of objects, which have been published
92 *
93 * @return
94 */
95 public Hashtable<String, Object> getList() {
96 return list;
97 }
98
99 /***
100 * adds an additional object to the list of objects, which have been
101 * published
102 *
103 * @param searchString
104 * @param object
105 */
106 public void publish(String searchString, Object object) {
107 this.list.put(searchString, object);
108 }
109
110 /***
111 * removes an object for the list of objects, which have been published
112 *
113 * @param searchString
114 */
115 public void unpublish(String searchString) {
116 this.list.remove(searchString);
117 }
118
119 /***
120 * sends a request to another peer. This function should not be used by
121 * users of this api. The search function should be used instead.
122 *
123 * @param request
124 * @param throwException
125 * @throws NotFoundException
126 * @throws UnknownHostException
127 * @throws IOException
128 * @throws ClassNotFoundException
129 */
130 public void senden(GnutellaRequest request, boolean throwException)
131 throws NotFoundException, UnknownHostException, IOException,
132 ClassNotFoundException {
133 if (peer == null) {
134 this.connect();
135 if (peer == null) {
136 if (throwException == true)
137 throw new NotFoundException(request.getSearchString());
138 else
139 return;
140 }
141 }
142
143 this.answer.remove(request.getSearchString());
144
145 for (int i = 0; i < peer.size(); i++) {
146 try {
147 Socket socket = new Socket();
148 socket.connect(peer.get(i));
149
150 ObjectOutputStream oos = new ObjectOutputStream(socket
151 .getOutputStream());
152 oos.writeObject(request);
153 oos.flush();
154 socket.close();
155 } catch (BindException e) {
156
157 } catch (Exception e) {
158 System.err.println(peer.get(i));
159 e.printStackTrace();
160
161 peer.remove(i);
162 i--;
163 }
164 }
165 }
166
167 /***
168 * function to search for an object in the gnutella network by its string.
169 *
170 * @param searchString
171 * @return
172 * @throws UnknownHostException
173 * @throws IOException
174 * @throws ClassNotFoundException
175 * @throws NotFoundException
176 */
177 public Object search(String searchString) throws UnknownHostException,
178 IOException, ClassNotFoundException, NotFoundException {
179 if (this.list.containsKey(searchString) == true)
180 return this.list.get(searchString);
181
182 GnutellaRequest request = new GnutellaRequest(searchString,
183 new InetSocketAddress(InetAddress.getLocalHost(),
184 this.localPort));
185 this.senden(request, true);
186
187 long waittime = 0;
188
189 try {
190 Thread.sleep(10);
191 } catch (Exception e) {
192
193 }
194
195 while (waittime < 600) {
196 long begin = System.currentTimeMillis();
197 try {
198 Thread.sleep(20);
199 } catch (Exception e) {
200
201 }
202
203
204
205 if (answer.containsKey(searchString) == true) {
206
207 return this.answer.get(searchString);
208 }
209
210 waittime = waittime + (System.currentTimeMillis() - begin);
211 }
212
213
214 throw new NotFoundException(request.getSearchString());
215 }
216
217 public int getLocalPort() {
218 return localPort;
219 }
220
221 public String getServerIp() {
222 return serverIp;
223 }
224
225 public int getServerPort() {
226 return serverPort;
227 }
228
229 public Hashtable<String, Object> getAnswer() {
230 return answer;
231 }
232 }