Source code: Freenet/client/RequestClient.java
1 package Freenet.client;
2 import java.net.*;
3 import java.io.*;
4 import java.util.*;
5 import Freenet.*;
6 import Freenet.crypt.*;
7 import Freenet.support.*;
8 import Freenet.message.*;
9
10 public class RequestClient
11 {
12 private Address nodeAddress;
13 private ListeningAddress myAddress;
14 private long hopsToLive;
15 private long startDepth;
16
17 // option defaults
18 static private int defaultListenPort = 0;
19 static private String defaultServerAddress = "tcp/127.0.0.1:19114";
20 static private long defaultHopsToLive = 5;
21 static private int defaultLogging = Logger.NORMAL;
22 static private int defaultVerbosity = 1;
23
24 public ClientCore cn;
25 public ConnectionHandler ch;
26 public boolean closeOnExit = true;
27
28 // output all informational and error messages to this stream: (pixelpapst)
29 static private PrintStream errout = System.err;
30 // this is important for piping to stdout
31
32
33 static public void main(String[] args)
34 {
35 // parse command line
36 Logger.threshold = Logger.ERROR;
37 Params params = new Params(args);
38
39 String keyindex=params.getParam("keyindex");
40 if(keyindex!=null)
41 {
42 try
43 {
44 readKeys(keyindex);
45 return;
46 }
47 catch(Exception e) {e.printStackTrace();}
48 }
49
50 // check arguments
51 if (params.getNumArgs() < 1 || params.getNumArgs() > 2) {
52 System.out.println("Usage: freenet_request [options] key [output-file]");
53 System.out.println("");
54 System.out.println(" -listenPort port Local port to listen for replies on");
55 System.out.println(" -serverAddress address Server node to connect to");
56 System.out.println(" -htl hops-to-live Hops-to-live for request");
57 System.out.println(" -logging error|normal|minor|debugging");
58 System.out.println(" Logging level");
59 System.out.println(" -verbosity 1-5 Verbosity of log messages");
60 System.out.println(" -keyindex URL URL to fetch key list from");
61 System.out.println("");
62 System.out.println("If output-file is omitted or is `-', output on standard output.");
63 System.out.println("");
64 System.out.println("Examples:");
65 System.out.println(" freenet_request freenet/manifesto manifesto.txt");
66 System.out.println(" freenet_request -serverAddress tcp/localhost:19114 -htl 15 freenet/manifesto | more");
67 System.out.println("");
68 System.out.println("Send bug reports to freenet-dev@lists.sourceforge.net");
69 return;
70 }
71
72 // process options
73 ListeningAddress lstaddr = new ListeningAddress
74 ("tcp/" + params.getint("listenPort", defaultListenPort));
75 Address addr = new Address
76 (params.getParam("serverAddress", defaultServerAddress));
77 SHA1 sha = new SHA1(true);
78 Key key = new StringKey(sha.doHash(params.getArg(0)));
79 long htl = params.getlong("htl", defaultHopsToLive);
80 if (params.getParam("logging")==null)
81 Logger.threshold = defaultLogging;
82 else if (params.getParam("logging").equalsIgnoreCase("error"))
83 Logger.threshold = Logger.ERROR;
84 else if (params.getParam("logging").equalsIgnoreCase("normal"))
85 Logger.threshold = Logger.NORMAL;
86 else if (params.getParam("logging").equalsIgnoreCase("minor"))
87 Logger.threshold = Logger.MINOR;
88 else if (params.getParam("logging").equalsIgnoreCase("debugging"))
89 Logger.threshold = Logger.DEBUGGING;
90 Logger.verbosity = params.getint("verbosity",defaultVerbosity);
91
92 // open output file, if specified (default stdout)
93 OutputStream out = System.out;
94 String outputFile = params.getArg(1);
95 if (outputFile != null && !outputFile.equals ("-")) {
96 try {
97 out = new FileOutputStream(outputFile);
98 } catch(IOException e) {
99 errout.println(e);
100 System.exit(1);
101 return;
102 }
103 }
104
105 Core.connectTimeout = 30000;
106 Core.handshakeTimeout = 30000;
107 Core.handshakeLife=1000000;
108 Core.connectTimeout=10000;
109 Core.timer=new Ticker(500);
110
111 Logger.threshold=Logger.NORMAL;
112
113 RequestClient rc = new RequestClient(addr, lstaddr, htl, (Math.abs((new Random()).nextLong()) % 30));
114
115 DataReply reply;
116 InputStream stream;
117
118 try {
119 reply = rc.request(key);
120 stream=reply.in;
121 } catch(BadHandshakeException e) {
122 errout.println("Bad handshake from node");
123 System.exit(2);
124 return;
125 } catch (SendFailedException sfe) {
126 errout.print("Couldn't connect to the specified Freenet server - ");
127 if (params.getParam("serverAddress", defaultServerAddress).startsWith("tcp/localhost")) {
128 errout.println("have you started it?");
129 }
130 else {
131 errout.println("please try a different one.");
132 }
133 System.exit(3);
134 return;
135 } catch (ClientException ce) {
136 if (ce.msg == null) {
137 errout.println("Network timed out waiting for a reply from the server.");
138 } else if (ce.msg instanceof RequestFailed) {
139 errout.println("The key you requested could not be found anywhere in the network.");
140 } else if (ce.msg instanceof TimedOut) {
141 errout.println("The key you requested could not be found within HTL hops.");
142 } else {
143 errout.println("Received unexpected reply: " + ce.msg);
144 }
145 System.exit(4);
146 return;
147 }
148
149
150 DotCounter counter=new DotCounter(reply.length.longValue() / 80);
151 Conduit cond=new Conduit(stream, out, counter);
152
153 cond.asyncFeed(null,null,reply.length.longValue());
154
155 }
156
157 private static final void readKeys(String index) throws Exception
158 {
159 InputStreamReader ir = new InputStreamReader((InputStream)(new URL(index).getContent()));
160 BufferedReader br = new BufferedReader(ir);
161 SHA1 sha=new SHA1(true);
162 while(br.ready())
163 {
164 System.out.println(br.readLine());
165 }
166 }
167
168 public RequestClient(Address addr, ListeningAddress myAddr, long htl, long dpth)
169 {
170 nodeAddress = addr;
171 hopsToLive = htl;
172 startDepth = dpth;
173 cn = new ClientCore(myAddr);
174 myAddress = cn.myAddress;
175
176 }
177
178 public DataReply request(Key key) throws ClientException, SendFailedException, BadHandshakeException
179 {
180 Random r = new Random(System.currentTimeMillis());
181
182 ClientMessageHandler cmh = (ClientMessageHandler) cn.mh;
183 cmh.ct = Thread.currentThread();
184
185 try {
186 ch = cn.connect(nodeAddress);
187 } catch (ConnectFailedException e) {
188 throw new SendFailedException(e.peer);
189 }
190
191 HandshakeRequest hr = new HandshakeRequest(r.nextLong());
192 hr.sending(cn, ch);
193 ch.sendMessage(hr);
194
195 try {
196 Thread.sleep(10000);
197 } catch (InterruptedException e) {
198 }
199
200 if (cmh.last == null || !(cmh.last instanceof HandshakeReply) || !((HandshakeReply) cmh.last).check())
201 throw new BadHandshakeException();
202
203 DataRequest dr=new DataRequest(r.nextLong(), hopsToLive, startDepth , key);
204 dr.sending(cn, ch);
205 ch.sendMessage(dr);
206
207 // clear last message
208 cmh.last = null;
209
210 // wait for InsertReply (or loop on QueryRestarted)
211 boolean redo;
212 do {
213 redo = false;
214 try {
215 Logger.log("client/RequestClient","Waiting another " + hopsToLive * 5 + " seconds for a response",Logger.NORMAL);
216 Thread.sleep(hopsToLive * 5000 + 5000);
217 } catch(InterruptedException e) {
218 if (cmh.last instanceof QueryRestarted) {
219 Logger.log("client/RequestClient","The request got stuck on a broken node but has been restarted at a depth of " + cmh.last.depth,Logger.MINOR);
220 redo = true;
221 }
222 }
223 } while (redo);
224
225 if (cmh.last == null || !(cmh.last instanceof DataReply) || cmh.last.id != dr.id) {
226 if (closeOnExit) {
227 Logger.log("client/RequestClient","Closing connection",Logger.NORMAL);
228 ch.close();
229 }
230 throw new ClientException(cmh.last);
231 } else {
232 return (DataReply)cmh.last;
233 }
234 }
235
236 public void setCloseOnExit (boolean closeOnExit) {
237 this.closeOnExit = closeOnExit;
238 }
239 }