View Javadoc

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 		// this.answer = null;
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 			// System.err.println("still waiting: " + waittime);
204 
205 			if (answer.containsKey(searchString) == true) {
206 				// System.err.println("received result");
207 				return this.answer.get(searchString);
208 			}
209 
210 			waittime = waittime + (System.currentTimeMillis() - begin);
211 		}
212 		// socket.close();
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 }