I2P

Invisible Internet Project


root/src/jsp/announce.jsp @ 7eb54a02d52760c6c4dd0d0617f417ba0f148061

Revision 18fd6701d6926b6778d5997f341bd0b70fcff3b2, 6.2 KB (checked in by dev@…, 2 years ago)

Managed to get plugin installing correctly.

Line 
1<%@page import="java.util.ArrayList" %><%@page import="java.util.Collections" %><%@page import="java.util.List" %><%@page import="java.util.Map" %><%@page import="java.util.HashMap" %><%@page import="net.i2p.data.Base64" %><%@page import="net.i2p.data.Destination" %><%@page import="net.i2p.i2pcontrol.*" %><%@page import="org.klomp.snark.bencode.BEncoder" %><%
2
3/*
4 *  Above one-liner is so there is no whitespace -> IllegalStateException
5 *
6 *  Copyright 2010 zzz (zzz@mail.i2p)
7 *
8 *  Licensed under the Apache License, Version 2.0 (the "License");
9 *  you may not use this file except in compliance with the License.
10 *  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *  Unless required by applicable law or agreed to in writing, software
15 *  distributed under the License is distributed on an "AS IS" BASIS,
16 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *  See the License for the specific language governing permissions and
18 *  limitations under the License.
19 *
20 */
21
22/*
23 * USE CAUTION WHEN EDITING
24 * Trailing whitespace OR NEWLINE on the last line will cause
25 * IllegalStateExceptions !!!
26 *
27 */
28        // would be nice to make these configurable
29        final int MAX_RESPONSES = 25;
30        final int INTERVAL = 27*60;
31        final boolean ALLOW_IP_MISMATCH = false;
32        final boolean ALLOW_COMPACT_RESPONSE = true;
33
34        // so the chars will turn into bytes correctly
35        request.setCharacterEncoding("ISO-8859-1");
36        java.io.OutputStream cout = response.getOutputStream();
37        response.setCharacterEncoding("ISO-8859-1");
38        response.setContentType("text/plain");
39        response.setHeader("Pragma", "no-cache");
40        String info_hash = request.getParameter("info_hash");
41        String peer_id = request.getParameter("peer_id");
42        // ignored
43        String port = request.getParameter("port");
44        // ignored
45        String uploaded = request.getParameter("uploaded");
46        // ignored
47        String downloaded = request.getParameter("downloaded");
48        String sleft = request.getParameter("left");
49        String event = request.getParameter("event");
50        String ip = request.getParameter("ip");
51        String numwant = request.getParameter("numwant");
52        boolean compact = ALLOW_COMPACT_RESPONSE && request.getParameter("compact") != null;
53        // use to enforce destination
54        String him = request.getHeader("X-I2P-DestB64");
55        String xff = request.getHeader("X-Forwarded-For");
56        String xfs = request.getHeader("X-Forwarded-Server");
57
58        boolean fail = false;
59        String msg = "bad announce";
60
61        if (xff != null || xfs != null) {
62                fail = true;
63                msg = "Non-I2P access denied";
64                response.setStatus(403, msg);
65        }
66
67        if (info_hash == null && !fail) {
68                fail = true;
69                msg = "no info hash";
70        }
71
72        if (ip == null && !fail) {
73                fail = true;
74                msg = "no ip (dest)";
75        }
76
77        if (peer_id == null && !fail) {
78                fail = true;
79                msg = "no peer id";
80        }
81
82        InfoHash ih = null;
83        if (!fail) {
84                try {
85                        ih = new InfoHash(info_hash);
86                } catch (Exception e) {
87                        fail = true;
88                        msg = "bad infohash " + e;
89                }
90        }
91
92        Destination d = null;
93        if (!fail) {
94                try {
95                        if (ip.endsWith(".i2p"))
96                                ip = ip.substring(0, ip.length() - 4);
97                        d = new Destination(ip);  // from b64 string
98                } catch (Exception e) {
99                        fail = true;
100                        msg = "bad dest " + e;
101                }
102        }
103
104        PID pid = null;
105        if (!fail) {
106                try {
107                        pid = new PID(peer_id);
108                } catch (Exception e) {
109                        fail = true;
110                        msg = "bad peer id " + e;
111                }
112        }
113
114        // int params
115
116        // ignored
117        long up = 0;
118        try {
119                up = Long.parseLong(uploaded);
120                if (up < 0)
121                        up = 0;
122        } catch (NumberFormatException nfe) {};
123
124        // ignored
125        long down = 0;
126        try {
127                down = Long.parseLong(downloaded);
128                if (down < 0)
129                        down = 0;
130        } catch (NumberFormatException nfe) {};
131
132        int want = MAX_RESPONSES;
133        try {
134                want = Integer.parseInt(numwant);
135                if (want > MAX_RESPONSES)
136                        want = MAX_RESPONSES;
137                else if (want < 0)
138                        want = 0;
139        } catch (NumberFormatException nfe) {};
140
141        // spoof check
142        // if him == null, we are not using the I2P HTTP server tunnel, or something is wrong
143        boolean matchIP = ALLOW_IP_MISMATCH || him == null || ip == null || ip.equals(him);
144        if (want <= 0 && (!matchIP) && !fail) {
145                fail = true;
146                msg = "ip mismatch";
147        }
148
149        long left = 0;
150        if (!"completed".equals(event)) {
151                try {
152                        left = Long.parseLong(sleft);
153                        if (left < 0)
154                                left = 0;
155                } catch (NumberFormatException nfe) {};
156        }
157
158        Torrents torrents = I2PControlController.getTorrents();
159        Map<String, Object> m = new HashMap();
160        if (fail) {
161                m.put("failure reason", msg);           
162        } else if ("stopped".equals(event)) {
163                Peers peers = torrents.get(ih);
164                if (matchIP && peers != null)
165                        peers.remove(pid);
166                m.put("interval", Integer.valueOf(INTERVAL));
167        } else {
168                Peers peers = torrents.get(ih);
169                if (peers == null) {
170                        peers = new Peers();
171                        Peers p2 = torrents.putIfAbsent(ih, peers);
172                        if (p2 != null)
173                                peers = p2;
174                }
175
176                // fixme same peer id, different dest
177                Peer p = peers.get(pid);
178                if (p == null) {
179                        p = new Peer(pid.getData(), d);
180                        // don't add if spoofed
181                        if (matchIP) {
182                                Peer p2 = peers.putIfAbsent(pid, p);
183                                if (p2 != null)
184                                        p = p2;
185                        }
186                }
187                // don't update if spoofed
188                if (matchIP)
189                        p.setLeft(left);
190
191                m.put("interval", Integer.valueOf(INTERVAL));
192                int size = peers.size();
193                int seeds = peers.countSeeds();
194                m.put("complete", Integer.valueOf(seeds));
195                m.put("incomplete", Integer.valueOf(size - seeds));
196                if (want <= 0) {
197                        // snark < 0.7.13 always wants a list
198                        m.put("peers", java.util.Collections.EMPTY_LIST);
199                } else {
200                        List<Peer> peerlist = new ArrayList(peers.values());
201                        peerlist.remove(p);   // them
202                        if (want < size - 1) {
203                                Collections.shuffle(peerlist);
204                                peerlist = peerlist.subList(0, want);
205                        }
206                        if (compact) {
207                                // old experimental way - list of hashes
208                                //List<String> peerhashes = new ArrayList(peerlist.size());
209                                //for (Peer pe : peerlist) {
210                                //      peerhashes.add(pe.getHash());
211                                //}
212                                // new way - one big string
213                                byte[] peerhashes = new byte[32 * peerlist.size()];
214                                for (int i = 0; i < peerlist.size(); i++)
215                                        System.arraycopy(peerlist.get(i).getHash().getBytes("ISO-8859-1"), 0, peerhashes, i * 32, 32);
216                                m.put("peers", peerhashes);
217                        } else {
218                                m.put("peers", peerlist);
219                        }
220                }
221        }
222        BEncoder.bencode(m, cout);
223
224/*
225 *  Remove the newline on the last line or
226 *  it will generate an IllegalStateException
227 *
228 */
229%>
Note: See TracBrowser for help on using the browser.