instrumentation: add next-share/
[cs-p2p-next.git] / instrumentation / next-share / BaseLib / Tools / proxy-cmdline.py
1 # Written by Arno Bakker, George Milescu 
2 # see LICENSE.txt for license information
3 #
4 # Razvan Deaconescu, 2008:
5 #       * corrected problem when running in background
6 #       * added usage and print_version functions
7 #       * uses getopt for command line argument parsing
8 # George Milescu, 2009
9 #       * Added arguments for proxymode
10
11 import sys
12 import shutil
13 import time
14 import tempfile
15 import random
16 import os
17 import getopt
18 from traceback import print_exc
19
20 from BaseLib.Core.API import *
21 from BaseLib.Core.BitTornado.__init__ import version, report_email
22 from BaseLib.Core.Utilities.utilities import show_permid_short
23 from M2Crypto import EC
24
25 # Print usage message
26 def usage():
27     print "Usage: python proxy-cmdlinedl.py [options] torrent_file"
28     print "Options:"
29     print "\t--port <port>"
30     print "\t-p <port>\t\tuse <port> to listen for connections"
31     print "\t\t\t\t(default is random value)"
32     print "\t--output <output-dir>"
33     print "\t-o <output-dir>\t\tuse <output-dir> for storing downloaded data"
34     print "\t\t\t\t(default is current directory)"
35     print "\t--state-dir <state-dir>"
36     print "\t\t\t\tuse <state-dir> for storing session data"
37     print "\t\t\t\t(default is /tmp/tmp-tribler)"
38     print "\t--proxymode <proxy-mode>"
39     print "\t\t\t\t[DEVEL] use <proxy-mode> to specify how the client behaves"
40     print "\t\t\t\t * proxy-mode = off: no proxy is being used (the client is either an helper, or it does not start use proxy connections)"
41     print "\t\t\t\t * proxy-mode = private: only proxy connections are being used"
42     print "\t\t\t\t * proxy-mode = speed: both proxy and direct connections are being used"
43     print "\t\t\t\t(default is off)"
44     print "\t--proxyservice <proxy-service>"
45     print "\t\t\t\t[DEVEL] use <proxy-mode> to specify how the client behaves"
46     print "\t\t\t\t * proxy-service = off: the current node can not be used as a proxy by other nodes"
47     print "\t\t\t\t * proxy-service = on: the current node can be used as a proxy by other nodes"
48     print "\t\t\t\t(default is off)"
49     print "\t--helpers <helpers>"
50     print "\t\t\t\t[DEVEL] use <helpers> to specify maximum number of helpers used or a torrent"
51     print "\t\t\t\t(default is 5)"
52     print "\t--test-mode <test-mode>"
53     print "\t\t\t\t[DEVEL] use <test-mode> to specify if the client runs as part of a test"
54     print "\t\t\t\t * test-mode = off: the client is not run as part of a test"
55     print "\t\t\t\t * test-mode = coord: the client is part of a test, as a coordinator"
56     print "\t\t\t\t * test-mode = helper: the client is part of a test, as a helper"
57     print "\t\t\t\t(default is off)"
58     print "\t--no-download"
59     print "\t\t\t\t[DEVEL] Don't download anything, just stay and wait"
60     print "\t\t\t\t(if not present the default to download the torrent data)"
61     print "\t--version"
62     print "\t-v\t\t\tprint version and exit"
63     print "\t--help"
64     print "\t-h\t\t\tprint this help screen"
65     print
66     print "Report bugs to <" + report_email + ">"
67
68 # Print version information
69 def print_version():
70     print version, "<" + report_email + ">"
71
72 # Print torrent statistics
73 def state_callback(ds):
74     d = ds.get_download()
75 #    print >>sys.stderr,`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD)
76     print >>sys.stderr, '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s' % \
77             (d.get_def().get_name(), \
78             dlstatus_strings[ds.get_status()], \
79             ds.get_progress() * 100, \
80             ds.get_error(), \
81             ds.get_current_speed(UPLOAD), \
82             ds.get_current_speed(DOWNLOAD))
83
84     return (1.0, False)
85
86 def main():
87     try:
88         # opts = a list of (option, value) pairs
89         # args = the list of program arguments left after the option list was stripped
90         opts, args = getopt.getopt(sys.argv[1:], "hvo:p:", ["help", "version", "output-dir=", "port=", "proxymode=", "proxyservice=", "helpers=", "test-mode=", "state-dir=", "no-download"])
91     except getopt.GetoptError, err:
92         print str(err)
93         usage()
94         sys.exit(2)
95
96     # init the default values
97     output_dir = os.getcwd()
98     port = random.randint(10000, 65535)
99     id = None
100     proxy_mode = PROXY_MODE_OFF
101     proxy_service = PROXYSERVICE_OFF
102     helpers = 5
103     test_mode="off" # off, coord, helper
104     no_download = False
105     statedir = "/tmp/tmp-tribler"
106
107     # get values from arguments
108     for option, value in opts:
109         if option in ("-h", "--help"):
110             usage()
111             sys.exit(0)
112         elif option in ("-o", "--output-dir"):
113             output_dir = value
114         elif option in ("--state-dir"):
115             statedir = value
116         elif option in ("-p", "--port"):
117             port = int(value)
118         elif option in ("--proxymode"):
119             if value == "off":
120                 proxy_mode = PROXY_MODE_OFF
121             elif value == "private":
122                 proxy_mode = PROXY_MODE_PRIVATE
123             elif value == "speed":
124                 proxy_mode = PROXY_MODE_SPEED
125             else:
126                 proxy_mode = PROXY_MODE_OFF
127         elif option in ("--proxyservice"):
128             if value == "off":
129                 proxy_service = PROXYSERVICE_OFF
130             elif value == "on":
131                 proxy_service = PROXYSERVICE_ON
132             else:
133                 proxy_service = PROXYSERVICE_OFF
134         elif option in ("--helpers"):
135             helpers = int(value)
136         elif option in ("--test-mode"):
137             test_mode = value
138         elif option in ("-v", "--version"):
139             print_version()
140             sys.exit(0)
141         elif option in ("--no-download"):
142             no_download = True
143         else:
144             assert False, "unhandled option"
145
146     # arg should have only one element left: the torrent file name
147     # ProxyDevel
148     # if no_download is false (the client has to download torrent data), check number of arguments
149     if (no_download == False) and len(args) == 0:
150         usage()
151         sys.exit(2)
152     if len(args) > 1:
153         print "Too many arguments"
154         usage()
155         sys.exit(2)
156
157     # ProxyDevel
158     # is no_download is false (the client has to download torrent data), get torrent file name
159     if (no_download == False):
160         torrent_file = args[0]
161
162     print "Press Ctrl-C to stop the download"
163
164     # session setup
165     session_startup_config = SessionStartupConfig()
166     #statedir = tempfile.mkdtemp()
167     # ProxyDevel - set custom state dir
168     session_startup_config.set_state_dir(statedir)
169     session_startup_config.set_download_help_dir(os.path.join(statedir,"help_dir"))
170     session_startup_config.set_listen_port(port)
171     session_startup_config.set_megacache(True)
172     session_startup_config.set_overlay(True)
173     session_startup_config.set_dialback(True)
174     session_startup_config.set_internal_tracker(False)
175     # ProxyDevel - turn DHT off
176     session_startup_config.set_mainline_dht(False)
177     # ProxyDevel - turn buddycast off
178     session_startup_config.set_buddycast(False)
179     # ProxyDevel - set new core API values
180     session_startup_config.set_proxyservice_status(proxy_service)
181     
182     s = Session(session_startup_config)
183     
184     # DEBUG
185     print "*** My Permid = ", show_permid_short(s.get_permid())
186
187     # ProxyDevel - Receive overlay messages from anyone
188     s.set_overlay_request_policy(AllowAllRequestPolicy())
189
190     if test_mode == "coord":
191         # add the helper 1 as a friend
192         # get helper1 permid
193         helper1_keypair_filename = os.path.join("../../P2P-Testing-Infrastructure/ClientWorkingFolders/Proxy01/statedir","ec.pem")
194         helper1_keypair = EC.load_key(helper1_keypair_filename)
195         helper1_permid = str(helper1_keypair.pub().get_der())
196         # set helper1 ip address
197         helper1_ip="10.10.3.1"
198 #        helper1_ip="141.85.224.203"
199         # set helper1 port
200         helper1_port = 25123
201         # add helper1 as a peer
202         peerdb = s.open_dbhandler(NTFY_PEERS)
203         peer = {}
204         peer['permid'] = helper1_permid
205         peer['ip'] = helper1_ip
206         peer['port'] = helper1_port
207         peer['last_seen'] = 0
208         peerdb.addPeer(peer['permid'], peer, update_dns=True, commit=True)
209
210         # add the helper 2 as a friend
211         # get helper2 permid
212         helper2_keypair_filename = os.path.join("../../P2P-Testing-Infrastructure/ClientWorkingFolders/Proxy02/statedir","ec.pem")
213         helper2_keypair = EC.load_key(helper2_keypair_filename)
214         helper2_permid = str(helper2_keypair.pub().get_der())
215         # set helper2 ip address
216         helper2_ip="10.10.4.1"
217 #        helper2_ip="141.85.224.204"
218         # set helper2 port
219         helper2_port = 25123
220         # add helper2 as a peer
221         peerdb = s.open_dbhandler(NTFY_PEERS)
222         peer = {}
223         peer['permid'] = helper2_permid
224         peer['ip'] = helper2_ip
225         peer['port'] = helper2_port
226         peer['last_seen'] = 0
227         peerdb.addPeer(peer['permid'], peer, update_dns=True, commit=True)
228         
229     # ProxyDevel - if in no_download is false (the client has to download torrent data), then start downloading 
230     if (no_download == False):
231         # setup and start download
232         download_startup_config = DownloadStartupConfig()
233         download_startup_config.set_dest_dir(output_dir);
234         # ProxyDevel - turn PEX off
235         download_startup_config.set_ut_pex_max_addrs_from_peer(0)
236         download_startup_config.set_proxy_mode(proxy_mode)
237         download_startup_config.set_no_helpers(helpers)
238
239         torrent_def = TorrentDef.load(torrent_file)
240     
241         d = s.start_download(torrent_def, download_startup_config)
242         d.set_state_callback(state_callback, getpeerlist=False)
243     
244         # if the client is a coordinator
245         if test_mode == "coord":
246             # allow time for the download to start, before starting the help request
247             time.sleep(3)
248             # ask peer for help
249             for download in s.get_downloads():
250                 # DEBUG
251                 print "*** COORDINATOR Sending help request"
252                 peerlist = []
253                 peerlist.append(helper1_permid)
254                 peerlist.append(helper2_permid)
255                 download.ask_coopdl_helpers(peerlist)
256
257     #
258     # loop while waiting for CTRL-C (or any other signal/interrupt)
259     #
260     # - cannot use sys.stdin.read() - it means busy waiting when running
261     #   the process in background
262     # - cannot use condition variable - that don't listen to KeyboardInterrupt
263     #
264     # time.sleep(sys.maxint) has "issues" on 64bit architectures; divide it
265     # by some value (2048) to solve problem
266     #
267     try:
268         while True:
269             time.sleep(sys.maxint/2048)
270     except:
271         print_exc()
272
273     s.shutdown()
274     time.sleep(3)
275     # ProxyDevel
276     #shutil.rmtree(statedir)
277     
278 if __name__ == "__main__":
279     main()