--- /dev/null
+
+Comunicare Client <-> Server
+
+
+
+++---------+ start server +----------------------------------------------------------+
+| |---------------> | +--------------+ +--------+ +-------------+ |
+| Client | send commands | | Server daemon| | tribler| | transmission| .... |
+| |---------------> | +--------------+ +--------+ +-------------+ |
+++---------+<--------------- +----------------------------------------------------------+
+ ack
+
+
+
+1. Pas initial - NU MAI ESTE NEVOIE
+ - informatiile legate de clienti
+ - msg 1: tipul mesajului: CONFIG_MSG (definit in Util.py)
+ - msg 2: dictionar de dictionare cu datele din clients.xml
+ exp: {"tribler":{FILE:"Tribler/Tools/cmdline.py",
+ RUN_TYPE:"script",
+ INTERPRETER:"python", PREFIX:"PYTHONPATH=.",SUFFIX:"",
+ UP_LIMIT_OPTION:"",DL_LIMIT_OPTION:"", PORT_OPTION:"-p",
+ LOG_DIR_OPTION:"-l",DL_DIR_OPTION:"-d"}
+ }
+ - dupa fiecare msg 1,2 Serverul trimite un mesaj care indica daca a aparut sau nu vreo eroare
+
+
+
+2. Mesaje START
+ - trimis pt pornirea unui client
+ - msg 1: tipul mesajului START_MSG (definit in Util.py)
+ - msg 2: dictionar cu parametrii
+ exp: {CLIENT:"tribler",
+ BASE_DIR: "/usr/bin",
+ UP_LIMIT: "512",
+ DL_LIMIT:"256",
+ PORT:"9999",
+ DL_DIR:"/this/dir",
+ LOG_DIR:"/this/dir",
+ OUT_FILE: "output_file", ??? nu stim exact scopul lui
+ LOG_FILE:"log_file",
+ TORRENT: "torrent file"
+ }
+
+
+ - dupa fiecare msg 1,2 Serverul trimite un mesaj care indica daca a aparut sau nu vreo eroare
+ -> dupa msg 2 serverul trimite "<pid client torrent>"
+
+3. Mesaje STOP
+ - trimis pt oprirea unui client
+ - msg 1: STOP_MSG (definit in Util.py)
+ - msg 2: numele clientului (un string)
+ - dupa fiecare msg 1,2 Serverul trimite un mesaj care indica daca a aparut sau nu vreo eroare
+
+4. Mesaje STATUS
+ - trimise de client pt interogarea starii
+ - msg 1: tipul mesajului STATUS_MSG (definit in Util.py)
+ - msg 2: dictionar - TODO
+ - dupa fiecare msg 1,2 Serverul trimite un mesaj care indica daca a aparut sau nu vreo eroare
+
+
+
+
+.....
--- /dev/null
+server/Server.py - serverul ce ruleaza ca daemon
+server/Server_NO_DAEMON.py - folosit pt testarea functionarii, nu este daemon
+server/Client.py - testeaza comunicatia cu serverul folosind sockets
+ - usage: python Client.py torrent_file
+Util.py - constante folosite atat de server cat si de commander
+start-clients/BitTorrentClientRun - porneste instante de clienti bittorrent
+start-clients/*Run.py - subclase ale BitTorrentClientRun modificate pt fiecare client in parte.
+commander/ -clasele pt Commander
+
+
+
+
+
--- /dev/null
+
+#!/usr/bin/env python
+
+SERVER_PORT = 10004
+SERVER_HOST = "127.0.0.1"
+
+""" Message types: client -> server """
+
+START_MSG = "1";
+STOP_MSG = "2";
+STATUS_MSG = "3";
+
+ACK_MSG = "ACK" # send by server to the client after receiving a message if everything was ok
+ERROR_MSG = "ERROR " # send by server to the client if the parameters were incorrect
+ # or the client could not be started etc
+
+#xml tags from swarm.xml
+CLIENT = "client"
+BASE_DIR = "base"
+UP_LIMIT = "upload_limit"
+DL_LIMIT = "download_limit"
+DL_DIR = "download_dir"
+LOG_DIR = "logging_dir"
+OUT_FILE = "output_file"
+LOG_FILE = "log_file"
+PORT = "port"
+TORRENT = "torrent_file"
+
+#clients
+TRIBLER = "tribler"
+TRANSMISSION = "transmission"
+
--- /dev/null
+import sys, socket
+import pickle
+import paramiko
+import os
+from Util import *
+from XMLParser import *
+from TrafficControl import *
+from threading import Thread
+paramiko.util.log_to_file('/tmp/paramiko.log')
+
+MSGLEN = 1024
+DEBUG = True
+
+class Commander(Thread):
+ def __init__(self, nodes_xml, swarm_xml):
+ Thread.__init__(self)
+ self.nodes = Nodes(nodes_xml);
+ self.swarm = Swarm(swarm_xml);
+ self.tc = TrafficControl("openvz");
+ self.sshc = paramiko.SSHClient()
+ self.sshc.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ self.sshc.load_system_host_keys()
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ def sendSSHComm(self, hostname, username, port, comm):
+ try:
+ self.sshc.connect(hostname=hostname, username=username, port=port)
+ stdin, stdout, stderr = self.sshc.exec_command(comm)
+ print stdout.readlines()
+ except Exception as e:
+ print e
+ finally:
+ self.sshc.close()
+
+ def sendMultipleSSHComm(self, hostname, username, port, comms):
+ try:
+ self.sshc.connect(hostname=hostname, username=username, port=port)
+ for c in comms:
+ stdin, stdout, stderr = self.sshc.exec_command(comm)
+ except Exception as e:
+ print e
+ finally:
+ self.sshc.close()
+
+ def sendComm(self, hostname, port, msg_type, config_data):
+ try:
+ self.sock.connect((hostname, port))
+ self.send(msg_type)
+ response = self.recv_msg()
+ if response == ACK_MSG:
+ self.sendMsg(pickle.dumps(config_data))
+ response = self.recv_msg()
+ print "->>>>>>>>>>>>>>>>>>>>>>>>>", response
+ except Exception as e:
+ print e
+ finally:
+ self.sock.close()
+
+ def sendMsg(self, msg):
+ totalsent = 0
+ while totalsent < len(msg):
+ sent = self.sock.send(msg[totalsent:])
+ if sent == 0:
+ raise RuntimeError, "socket connection broken"
+ totalsent = totalsent + sent
+
+ def recvMsg(self):
+ msg = ''
+ chunk = self.sock.recv(MSGLEN)
+ if chunk == '':
+ raise RuntimeError, "socket connection broken"
+ msg = msg + chunk
+
+ return msg
+
+ def startDaemon(self, node):
+ print node.daemon_dir
+ comm = "PYTHONPATH=/home/p2p/cs-p2p-next/bt_comm:/home/p2p/cs-p2p-next/bt_comm/start-clients/ python /home/p2p/cs-p2p-next/bt_comm/server/Server.py start " + node.public_address + " " + node.listen_port
+ print comm
+ #self.printDummyCommand(node.public_address, node.public_port, node.ssh_port, comm)
+ self.sendSSHComm(node.public_address, node.username, int(node.ssh_port), comm)
+ self.sendSSHComm(node.public_address, node.username, int(node.ssh_port), "ps -ef | grep Server")
+
+ def applyTC(self, node):
+ si = self.swarm.getSIByNode(node)
+ self.tc.config(node.public_address, node.public_port, node.public_iface, \
+ node.private_address, node.private_port, node.private_iface)
+ self.tc.set_upload_limit(si.upload_limit)
+ self.tc.set_download_limit(si.download_limit)
+
+ commands = self.tc.get_all_commands()
+ self.printDummyCommand(node.public_address, node.public_port, node.ssh_port, commands)
+ #sendMultipleSSHComm(node.public_address, node.username, node.ssh_port, commands)
+
+ def sendSIStart(self, si):
+ node = self.nodes.getNodeBySi(si)
+ base_path = node.getClientBaseDir(si.btclient)
+ torrent_file = self.swarm.getTorrentFile()
+
+ config_data = {CLIENT : si.btclient,
+ BASE_DIR : base_path,
+ UP_LIMIT : si.download_limit,
+ DL_LIMIT : si.upload_limit,
+ PORT : node.public_port,
+ DL_DIR : si.download_dir,
+ LOG_DIR : si.log_dir,
+ OUT_FILE : si.output_file,
+ LOG_FILE : si.log_file,
+ TORRENT : torrent_file
+ }
+
+ self.printDummyCommand(node.public_address, node.listen_port, START_MSG, config_data)
+ self.sendComm(node.public_address, int(node.listen_port), START_MSG, config_data)
+
+ def printDummyCommand(self, public_address, public_port, option1, data):
+ print "----------------------"
+ print "sending to: [%s:%s] with option %s" %(public_address, public_port, option1)
+ print "this data: %s" %(data)
+ print "----------------------\n"
+
+
+ def sendSIStop(self, node):
+ pass
+
+ def sendSIStatus(self, node):
+ pass
+
+ def startAll(self):
+ for node in self.nodes.getNodes():
+ #self.applyTC(node)
+ self.startDaemon(node)
+
+ for si in self.swarm.getSIs():
+ self.sendSIStart(si)
+
+ def run(self):
+ self.printUsage()
+ while True:
+ k = raw_input("Choose option:")
+ if k == '': break
+ elif k == '1':
+ self.startAll()
+
+ def printUsage(self):
+ print "=========Commander Options=========="
+ print "1. Start Swarm"
+ print "===================================="
+
+if __name__ == "__main__":
+ c = Commander("../xml/nodes.xml", "../xml/swarm.xml")
+ c.start()
+
--- /dev/null
+import paramiko
+import os
+paramiko.util.log_to_file('/tmp/paramiko.log')
+
+class SSHCommander:
+ def __init__(self, hostname, username, port):
+ #self.sshclient = paramiko.Transport((hostname, port))
+ self.sshclient = paramiko.SSHClient()
+ self.sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ self.sshclient.load_system_host_keys()
+ #~ transport = paramiko.Transport((host, port))
+ #pkey_file = os.path.expanduser('~/.ssh/id_rsa')
+ #self.pkey = paramiko.RSAKey.from_private_key_file(pkey_file)
+ self.hostname = hostname
+ self.username = username
+ self.port = port
+
+ def connect(self):
+ self.sshclient.connect(hostname=self.hostname, username=self.username, port=self.port)
+ #self.sshclient.connect(username=self.username, pkey=self.pkey)
+
+ def emitCommand(self, comm):
+ stdin, stdout, stderr = self.sshclient.exec_command(comm)
+ print stdout.readlines()
+
+ def closeConnection(self):
+ self.sshclient.close()
+
+
+sshc = SSHCommander("141.85.224.204", "p2p", 20322)
+sshc.connect()
+sshc.emitCommand("ls -lh")
+sshc.closeConnection()
+
+#~ #client.connect(hostname='p2p-next-07.grid.pub.ro', username='p2p')
+#~ stdin, stdout, stderr = client.exec_command('touch gugu dudu')
+#~ stdin, stdout, stderr = client.exec_command('ls -l')
+#~ print stdout.readlines()
+#~ client.close()
+
+
+#~ host = "p2p-next-09.grid.pub.ro"
+#~ port = 22
+#~ transport = paramiko.Transport((host, port))
+
+#~ privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
+#~ mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
+#~ username = 'p2p'
+#~ transport.connect(username = username, pkey = mykey)
+
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Traffic control interface for Linux tc
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import sqlite3
+import os.path
+
+DEBUG = False
+
+class TrafficControl:
+ """
+ Basic class interface to Linux tc
+ """
+
+ def __init__(self, node_type):
+ self.node_type = node_type
+ self.upload_limit = -1
+ self.download_limit = -1
+
+ def config(self, host_address, host_port, host_iface,
+ vm_address = None, vm_port = -1, vm_iface = None):
+ self.host_address = host_address
+ self.host_port = host_port
+ self.host_iface = host_iface
+ self.vm_address = vm_address
+ self.vm_port = vm_port
+ self.vm_iface = vm_iface
+
+ """
+ Set upload limit. Argument in KB/s (kilobytes/s)
+ """
+ def set_upload_limit(self, upload_limit):
+ self.upload_limit = upload_limit
+
+ """
+ Set download limit. Argument in KB/s (kilobytes/s)
+ """
+ def set_download_limit(self, download_limit):
+ self.download_limit = download_limit
+
+ def get_upload_limit_commands(self):
+ upload_limit_commands = []
+ upload_limit_commands.append("tc qdisc add dev %s root handle 1: htb default 90" % (self.vm_iface))
+ upload_limit_commands.append("tc class add dev %s parent 1: classid 1:1 htb rate %skb ceil %skb" % (self.vm_iface, self.upload_limit, self.upload_limit))
+ upload_limit_commands.append("tc qdisc add dev %s parent 1:1 handle 10: sfq perturb 10" % (self.vm_iface))
+ upload_limit_commands.append("tc filter add dev %s parent 1:0 protocol ip u32 match ip dst %s match ip dport %s 0xffff classid 1:1" % (self.vm_iface, self.vm_address, self.vm_port))
+
+ return upload_limit_commands
+
+ def get_download_limit_commands(self):
+ download_limit_commands = []
+ download_limit_commands.append("tc qdisc add dev %s root handle 1: htb default 90" % (self.host_iface))
+ download_limit_commands.append("tc class add dev %s parent 1: classid 1:1 htb rate %skb ceil %skb" % (self.host_iface, self.download_limit, self.download_limit))
+ download_limit_commands.append("tc qdisc add dev %s parent 1:1 handle 10: sfq perturb 10" % (self.host_iface))
+ download_limit_commands.append("tc filter add dev %s parent 1:0 protocol ip u32 match ip src %s classid 1:1" % (self.host_iface, self.vm_address))
+
+ return download_limit_commands
+
+ def get_flush_commands(self):
+ flush_commands = []
+ flush_commands.append("tc qdisc del dev %s root handle 1:" % (self.host_iface))
+ flush_commands.append("tc qdisc del dev %s root handle 1:" % (self.vm_iface))
+
+ return flush_commands
+
+ def get_all_commands(self):
+ all_commands = []
+ all_commands.extend(self.get_upload_limit_commands())
+ all_commands.extend(self.get_download_limit_commands())
+ all_commands.extend(self.get_flush_commands())
+
+ return all_commands
+
+
+def print_commands(commands, header):
+ print "\n\t== %s ==\n" % (header)
+
+ for c in commands:
+ print c
+
+def main():
+
+ """
+ Test case
+ """
+
+ tc = TrafficControl("openvz")
+ tc.config("141.85.224.201", 10150, "eth0",
+ "172.16.10.0", 10150, "venet0")
+ tc.set_upload_limit(512)
+ tc.set_download_limit(256)
+
+ upload_limit_commands = tc.get_upload_limit_commands()
+ download_limit_commands = tc.get_download_limit_commands()
+ flush_commands = tc.get_flush_commands()
+ all_commands = tc.get_all_commands()
+
+ print_commands(upload_limit_commands, "upload limit commands")
+ print_commands(download_limit_commands, "download limit commands")
+ print_commands(flush_commands, "flush commands")
+ print_commands(all_commands, "all commands")
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+from lxml import etree
+
+class SwarmInstance:
+ def __init__(self, id, list):
+ self.id = id;
+ self.node_id = list[0];
+ self.btclient = list[1];
+ self.upload_limit = list[2];
+ self.download_limit = list[3];
+ self.download_dir = list[4];
+ self.log_dir = list[5];
+ self.log_file = list[6];
+ self.output_dir = list[7];
+ self.output_file = list[8];
+
+ def __str__(self):
+ return '[%s: %s: %s: %s: %s: %s: %s: %s]' \
+ %(self.id, self.node_id, self.btclient, self.upload_limit, \
+ self.download_limit, self.download_dir, self.log_dir, self.output_dir);
+
+class Node:
+ def __init__(self, id, list):
+ self.id = id;
+ self.public_address = list[0];
+ self.public_port = list[1];
+ self.public_iface = list[2];
+ self.private_address = list[3];
+ self.private_port = list[4];
+ self.private_iface = list[5];
+ self.ssh_port = list[6];
+ self.username = list[7];
+ self.listen_port = list[8];
+ self.clients_base_dir = list[10];
+ self.daemon_dir = list[9];
+
+ def __str__(self):
+ return '[%s: %s: %s: %s: %s: %s %s: %s]' \
+ %(self.id, self.public_address, self.public_port, self.private_address, \
+ self.private_port, self.ssh_port, self.username, self.clients_base_dir);
+
+ def getClientBaseDir(self, client):
+ return self.clients_base_dir[client]
+
+class Nodes:
+ def __init__(self, nodes_xml):
+ try:
+ tree = etree.parse(nodes_xml)
+ root = tree.getroot()
+ self.nodes = []
+ for elem in root:
+ id = elem.get("id")
+ list = [elem2.text for elem2 in elem[:len(elem)-1]]
+ client_paths = {}
+ for elem2 in elem[len(elem)-1]:
+ client_id = elem2.get("id");
+ client_paths [client_id]=elem2[0].text;
+ list.append(client_paths);
+ self.nodes.append(Node(id, list))
+ except IOError as e:
+ print e
+ return None
+
+ def getNode(self, id):
+ for node in self.nodes:
+ if node.id == id:
+ return node
+
+ def getNodeBySi(self, si):
+ for node in self.nodes:
+ if node.id == si.node_id:
+ return node
+
+ def getNodes(self):
+ return self.nodes
+
+
+class Swarm:
+ def __init__(self, swarm_xml):
+ try:
+ tree = etree.parse(swarm_xml)
+ root = tree.getroot()
+ self.swarm = []
+ self.torrent_file = root[0].text
+ for elem in root[1:]:
+ id = elem.get("id")
+ list = [elem2.text for elem2 in elem[:len(elem)-1]]
+ self.swarm.append(SwarmInstance(id, list))
+ except IOError as e:
+ print e
+ return None
+
+ def getSIByNode(self, node):
+ for si in self.swarm:
+ if si.node_id == node.id:
+ return si
+
+ def getTorrentFile(self):
+ return self.torrent_file
+
+ def getSIs(self):
+ return self.swarm
+
+#~ swarm = Swarm("swarm.xml")
+#~ for si in swarm.getSIs():
+ #~ print si
+
+#~ nodes = Nodes("nodes.xml")
+#~ for node in nodes.getNodes():
+ #~ print node
+ #~ print node.getClientBaseDir('libtorrent')
--- /dev/null
+#!/bin/bash
+PYTHONPATH=/home/marius/cs-p2p-next/bt_comm/:/home/marius/cs-p2p-next/bt_comm/xml/ python Client.py
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running Aria client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class AriaRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+ BitTorrentClientRun.__init__(self, base_path,
+ "$base_path/src/aria2c --log-level=debug --dir=$download_dir --log=$log_dir/$log_file --torrent-file=$torrent_file &> $output_dir/$output_file",
+ "$base_path/src/aria2c --log-level=debug --dir=$download_dir --log=$log_dir/$log_file --torrent-file=$torrent_file &> $output_dir/$output_file")
+
+
+def main():
+
+ """
+ Test case
+ """
+
+ ar = AriaRun("/home/p2p/p2p-clients/aria")
+ ar.config_run("/home/p2p/p2p-dld/aria", "/home/p2p/p2p-log/aria", "aria-fedora.out", "/home/p2p/p2p-log/aria", "aria-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ ar.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running BitTorrent client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os
+import os.path
+import subprocess
+import shlex
+from string import Template
+
+DEBUG = True
+
+class BitTorrentClientRun:
+ def __init__(self, base_path, simple_run_expr, logging_run_expr):
+ self.base_path = base_path
+ self.simple_run_expr = simple_run_expr
+ self.logging_run_expr = logging_run_expr
+
+ def config_run(self, download_dir, output_dir, output_file, log_dir, log_file, port, torrent_file):
+ self.download_dir = download_dir
+ self.output_dir = output_dir
+ self.output_file = output_file # output from stdout
+ self.log_dir = log_dir
+ self.log_file = log_file # output from stderr
+ self.port = port
+ self.torrent_file = torrent_file
+
+ def start(self):
+ t = Template(self.simple_run_expr)
+ self.simple_run_command = t.substitute(
+ base_path = self.base_path,
+ download_dir = self.download_dir,
+ output_dir = self.output_dir,
+ output_file = self.output_file,
+ log_dir = self.log_dir,
+ log_file = self.log_file,
+ port = str(self.port),
+ torrent_file = self.torrent_file
+ )
+
+ t = Template(self.logging_run_expr)
+ self.logging_run_command = t.substitute(
+ base_path = self.base_path,
+ download_dir = self.download_dir,
+ output_dir = self.output_dir,
+ output_file = self.output_file,
+ log_dir = self.log_dir,
+ log_file = self.log_file,
+ port = str(self.port),
+ torrent_file = self.torrent_file
+ )
+
+ print self.simple_run_command
+ print self.logging_run_command
+
+ def run_client(self, command):
+
+ # split command
+ args = shlex.split(command)
+
+ # remove redirectation parameters
+ for i in range(0, len(args)):
+ if args[i].find(">") > -1 :
+ for j in range(i, len(args)):
+ args.pop(i)
+ break;
+ if(DEBUG):
+ print "BitTorrentClientRun: command =", args
+
+ log_redirect = open(self.log_dir+"/"+self.log_file,"w")
+ output_redirect = open(self.output_dir+"/"+self.output_file,"w")
+ p=subprocess.Popen(args, shell=False, #does not create sh process
+ stdout=log_redirect,
+ stderr=output_redirect)
+ pid = p.pid
+ if(DEBUG):
+ print "BitTorrentClientRun: pid =", pid
+ return [pid, log_redirect, output_redirect]
+
+
+def main():
+
+ """
+ Test case
+
+ btcr = BitTorrentClientRun("/home/p2p/p2p-clients/transmission",
+ "$base_path/cli/transmissioncli --download-dir $download_dir --port $port $torrent_file > $output_dir/$output_file",
+ "TR_DEBUG=2 $base_path/cli/transmissioncli --download-dir $download_dir --port $port $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file")
+ btcr.config_run("/home/p2p/p2p-dld/transmission", "/home/p2p/p2p-log/transmission", "transmission-fedora.out", "/home/p2p/p2p-log/transmission", "transmission-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ btcr.start()
+
+
+ """
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+import sys,time, socket
+import pickle
+from Util import *
+MSGLEN = 1024
+DEBUG = True
+class MySocket:
+ def __init__(self, sock=None):
+ if sock is None:
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ else:
+ self.sock = sock
+
+ def connect(self, host, port):
+ self.sock.connect((host, port))
+ print "connected to %s %s"%(host, port)
+
+ def send_msg(self, msg):
+ totalsent = 0
+ while totalsent < len(msg):
+ sent = self.sock.send(msg[totalsent:])
+ if sent == 0:
+ raise RuntimeError, "socket connection broken"
+ totalsent = totalsent + sent
+
+ def send_command(self, msg_type, config_data):
+ self.send_msg(msg_type)
+ print "am trimis ", msg_type
+ response = self.recv_msg()
+ if response == ACK_MSG:
+ self.send_dict(config_data)
+ print "am trimis"
+ response = self.recv_msg()
+
+ return response
+
+ def recv_msg(self):
+ msg = ''
+ chunk = self.sock.recv(MSGLEN)
+ if chunk == '':
+ raise RuntimeError, "socket connection broken"
+ msg = msg + chunk
+ print "am primit ", msg
+ return msg
+
+ # send a pickled dictionary
+ def send_dict(self, data):
+ dumped_data = pickle.dumps(data)
+ self.send_msg(dumped_data)
+
+# basic test that starts and stops a BT Client
+def test_all_commands(torrent_file):
+ s = MySocket()
+ s.connect(SERVER_HOST, SERVER_PORT)
+ torrent_name = torrent_file[(torrent_file.rfind("/")+1):torrent_file.find(".torrent")];
+
+ start_data_tribler = {
+ CLIENT: TRIBLER, PORT:10150,
+ BASE_DIR:"/home/p2p/p2p-clients/tribler",
+ TORRENT:"/home/p2p/p2p-meta/" + torrent_name+".torrent",
+ DL_DIR: "/home/p2p/p2p-dld/tribler",
+ LOG_DIR: "/home/p2p/p2p-log/tribler",
+ OUT_FILE: torrent_name + ".out", #status messages
+ LOG_FILE: "tribler-" + torrent_name + ".log", #verbose messages
+
+ }
+ start_data_transmission = {
+ CLIENT: TRANSMISSION, PORT:10250,
+ BASE_DIR:"/usr/bin/",
+ TORRENT: "/home/p2p/p2p-meta/" + torrent_name+".torrent",
+ DL_DIR: "/home/p2p/p2p-dld/transmission",
+ LOG_DIR: "/home/p2p/p2p-log/transmission",
+ OUT_FILE: torrent_name + ".out", #status messages
+ LOG_FILE: "transmission-" + torrent_name + ".log", #verbose messages
+
+ }
+
+ start_data_hrktorrent = {
+ CLIENT: HRKTORRENT, PORT:10350,
+ BASE_DIR:"/home/p2p/p2p-clients/hrktorrent",
+ TORRENT: "/home/p2p/p2p-meta/" + torrent_name+".torrent",
+ DL_DIR: "/home/p2p/p2p-dld/hrktorrent",
+ LOG_DIR: "/home/p2p/p2p-log/hrktorrent",
+ OUT_FILE: torrent_name + ".out", #status messages
+ LOG_FILE: "hrktorrent-" + torrent_name + ".log", #verbose messages
+
+
+ }
+ response = s.send_command(START_MSG, start_data_tribler)
+ print response
+ pid = (response.split(" "))[1]
+ print pid
+ s = MySocket()
+ s.connect(SERVER_HOST, SERVER_PORT)
+ time.sleep(100)
+ response = s.send_command(STOP_MSG, pid)
+ print response
+
+def test_send_recv():
+ # test 1
+
+ s.send_msg("hello")
+ # test 2
+ dd = {'a':1, 'b':2}
+ s.send_dict(dd)
+ s.recv_msg()
+
+
+if __name__ == "__main__":
+
+ if len(sys.argv) != 2:
+ print "Usage: python %s <torrent_file>"%sys.argv[0]
+ else:
+ test_all_commands(sys.argv[1])
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running libtorrent (hrktorrent) client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class HrktorrentRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+ BitTorrentClientRun.__init__(self, base_path,
+ "cd $download_dir && $base_path/hrktorrent --minport$port --maxport$port $torrent_file &> $output_dir/$output_file",
+ "cd $download_dir && $base_path/hrktorrent --minport$port --maxport$port $torrent_file &> $output_dir/$output_file")
+
+
+def main():
+
+ """
+ Test case
+ """
+
+ hr = HrktorrentRun("/home/p2p/p2p-clients/hrktorrent")
+ hr.config_run("/home/p2p/p2p-dld/hrktorrent", "/home/p2p/p2p-log/hrktorrent", "hrktorrent-fedora.out", "/home/p2p/p2p-log/hrktorrent", "hrktorrent-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ hr.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running BitTorrent (Mainline) client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class MainlineRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+ BitTorrentClientRun.__init__(self, base_path,
+ "$base_path/bittorrent-console.py --save_in $download_dir --display_interval 1 $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file",
+ "$base_path/bittorrent-console.py --save_in $download_dir --display_interval 1 $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file")
+
+
+def main():
+
+ """
+ Test case
+ """
+
+ mr = MainlineRun("/home/p2p/p2p-clients/mainline")
+ mr.config_run("/home/p2p/p2p-dld/mainline", "/home/p2p/p2p-log/mainline", "mainline-fedora.out", "/home/p2p/p2p-log/mainline", "mainline-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ mr.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+import sys, os, socket
+import pickle
+import signal
+from daemon import Daemon
+from Util import *
+from Util import SERVER_HOST, SERVER_PORT
+from BitTorrentClientRun import *
+from TransmissionRun import *
+from TriblerRun import *
+
+DEBUG = True
+
+
+class MyDaemon(Daemon):
+
+ ip = ""
+ port = 0
+ BUFFER_SIZE = 4096
+
+ states = {} # keeps track of what kind of message was previously receveid on a socket.
+ processes = {}
+ WAITING_MSG_TYPE = 0
+ WAITING_START_DATA = 3
+ WAITING_STOP_DATA = 4
+ WAITING_STATUS_DATA = 5
+
+ def __init__(self, pidfile, ip='', port = 0, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
+ Daemon.__init__(self, pidfile, stdin, stdout, stderr)
+ self.ip = ip
+ self.port = port
+
+ def set_address(self, ip):
+ self.ip = ip
+ print "am setat ip ", ip
+
+ def set_port(self, port):
+ self.port = port
+ print "am setat port ", port
+
+ def run(self):
+ self.doServer(self.ip, self.port)
+
+ def recv_pickled_data(self, clientsock):
+ # while chunk:
+ # chunk = clientsock.recv(self.BUFFER_SIZE)
+ # data += chunk
+ data = clientsock.recv(self.BUFFER_SIZE)
+ dd = pickle.loads(data)
+ return dd
+
+
+ """ Starts a process for a BitTorrent client and returns its pid.
+ @return: -1, if any error is encountered
+ """
+ def start_bt_client(self, bt_client_data):
+
+ btcr = None
+
+ if bt_client_data[CLIENT] == TRANSMISSION:
+ btcr = TransmissionRun(bt_client_data[BASE_DIR])
+ elif bt_client_data[CLIENT] == TRIBLER:
+ btcr = TriblerRun(bt_client_data[BASE_DIR])
+
+ else:
+ return -1
+
+ btcr.config_run(bt_client_data[DL_DIR], bt_client_data[LOG_DIR],
+ bt_client_data[OUT_FILE], bt_client_data[LOG_DIR],
+ bt_client_data[LOG_FILE], bt_client_data[PORT],
+ bt_client_data[TORRENT])
+
+ btcr.start()
+ [pid, log_fd, output_fd] = btcr.run_client(btcr.simple_run_command)
+ self.processes[pid] = (log_fd, output_fd)
+ print self.processes[pid]
+ if(DEBUG):
+ print "Server: started client with pid = ", pid
+ return pid
+
+ """Simple test
+
+ btcr = TransmissionRun("/usr/bin/transmissioncli")
+ btcr.config_run("/home/adriana/p2p/p2p-dld/transmission",
+ "/home/adriana/p2p/p2p-log/transmission",
+ "scrubs.out", "/home/adriana/p2p/",
+ "transmission-scrubs.log", 10150,
+ "/home/adriana/p2p/p2p-meta/scrubs.torrent")
+
+ btcr.start()
+ btcr.run_client(btcr.simple_run_command)
+ """
+
+ def stop_bt_client(self, pid):
+
+ int_pid = int(pid)
+ os.kill(int_pid, signal.SIGKILL) # kill generates zombies
+ os.wait()
+ self.processes[int_pid][0].close()
+ self.processes[int_pid][1].close()
+ del self.processes[int_pid]
+ if(DEBUG):
+ print "Server: killed process with pid = ", pid
+
+ def doServer(self, ip, port):
+
+ serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ if(DEBUG):
+ print "Server: host ip = %s, port = %d"%(SERVER_HOST,SERVER_PORT)
+ serversocket.bind((ip,port));
+ serversocket.listen(10) #max 10 requests
+ clientsocks = []
+ while(1):
+ if(DEBUG):
+ print "Server: accepting connections"
+ (clientsock, address) = serversocket.accept();
+ if(DEBUG):
+ print "Server: accepted connection from ", address
+
+ if clientsock not in self.states:
+ self.states[clientsock] = self.WAITING_MSG_TYPE;
+
+ if self.states[clientsock] == self.WAITING_MSG_TYPE:
+ print self.states[clientsock]
+ msg = clientsock.recv(self.BUFFER_SIZE)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ msg_types = {
+ START_MSG: self.WAITING_START_DATA,
+ STOP_MSG: self.WAITING_STOP_DATA,
+ STATUS_MSG: self.WAITING_STATUS_DATA
+ }
+ if msg not in msg_types:
+ clientsock.send(ERROR_MSG +"wrong message type " + msg)
+ else:
+ self.states[clientsock] = msg_types[msg]
+ clientsock.send(ACK_MSG)
+ #else:
+ print self.states[clientsock]
+
+ if self.states[clientsock] == self.WAITING_START_DATA:
+ bt_client_data = self.recv_pickled_data(clientsock)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ client_pid = self.start_bt_client(bt_client_data)
+ clientsock.send(ACK_MSG +" "+ str(client_pid))
+
+ elif self.states[clientsock] == self.WAITING_STOP_DATA:
+ client_pid = self.recv_pickled_data(clientsock)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ self.stop_bt_client(client_pid)
+ clientsock.send(ACK_MSG)
+
+ elif self.states[clientsock] == self.WAITING_STATUS_DATA:
+ config = self.recv_pickled_data(clientsock)
+ clientsock.send(ACK_MSG)
+
+ self.states[clientsock] = self.WAITING_MSG_TYPE
+
+ # clientsock.recv(self.BUFFER_SIZE)
+ # recv_pickled_data(clientsock)
+ clientsock.close()
+
+if __name__ == "__main__":
+
+ if len(sys.argv) >= 2:
+
+ if 'start' == sys.argv[1]:
+ if(len(sys.argv) != 4):
+ print "usage:\n\t %s start <host_ip> <port>" % sys.argv[0]
+ sys.exit(2)
+ daemon = MyDaemon('/tmp/daemon-example.pid', sys.argv[2], int(sys.argv[3]), stdout = '/home/p2p/out', stderr = 'home/p2p/err')
+ daemon.start()
+ elif 'stop' == sys.argv[1]:
+ daemon = MyDaemon('/tmp/daemon-example.pid')
+ daemon.stop()
+ elif 'restart' == sys.argv[1]:
+ daemon = MyDaemon('/tmp/daemon-example.pid')
+ daemon.restart()
+ else:
+ print "Unknown command"
+ sys.exit(2)
+ sys.exit(0)
+ else:
+ print "usage:\n\t %s start <host_ip> <port>" % sys.argv[0]
+ print "\t%s stop|restart " % sys.argv[0]
+ sys.exit(2)
+
+
--- /dev/null
+#!/usr/bin/env python
+
+import sys, os, socket
+import pickle
+import signal
+from daemon import Daemon
+from Util import *
+from Util import SERVER_HOST, SERVER_PORT
+from BitTorrentClientRun import *
+from TransmissionRun import *
+from TriblerRun import *
+BUFFER_SIZE = 4096
+
+states = {} # keeps track of what kind of message was previously receveid on a socket.
+processes = {}
+WAITING_MSG_TYPE = 0
+WAITING_START_DATA = 3
+WAITING_STOP_DATA = 4
+WAITING_STATUS_DATA = 5
+
+DEBUG = True
+
+def recv_pickled_data(clientsock):
+ # while chunk:
+ # chunk = clientsock.recv(BUFFER_SIZE)
+ # data += chunk
+ data = clientsock.recv(BUFFER_SIZE)
+ dd = pickle.loads(data)
+ return dd
+
+
+def start_bt_client(bt_client_data):
+
+ btcr = None
+
+ if bt_client_data[CLIENT] == TRANSMISSION:
+ #btcr = TransmissionRun("/usr/bin/transmissioncli")
+ btcr = TransmissionRun(bt_client_data[BASE_DIR])
+ elif bt_client_data[CLIENT] == TRIBLER:
+ btcr = TriblerRun(bt_client_data[BASE_DIR])
+ # btcr = TriblerRun("/home/p2p/p2p-clients/tribler")
+
+ else:
+ return -1
+
+ btcr.config_run(bt_client_data[DL_DIR], bt_client_data[LOG_DIR],
+ bt_client_data[OUT_FILE], bt_client_data[LOG_DIR],
+ bt_client_data[LOG_FILE], bt_client_data[PORT],
+ bt_client_data[TORRENT])
+
+ btcr.start()
+ [pid, log_fd, output_fd] = btcr.run_client(btcr.simple_run_command)
+ processes[pid] = (log_fd, output_fd)
+ print processes[pid]
+ if(DEBUG):
+ print "Server: started client with pid = ", pid
+ return pid
+
+ """Simple test
+
+ btcr = TransmissionRun("/usr/bin/transmissioncli")
+ btcr.config_run("/home/adriana/p2p/p2p-dld/transmission",
+ "/home/adriana/p2p/p2p-log/transmission",
+ "scrubs.out", "/home/adriana/p2p/",
+ "transmission-scrubs.log", 10150,
+ "/home/adriana/p2p/p2p-meta/scrubs.torrent")
+
+ btcr.start()
+ btcr.run_client(btcr.simple_run_command)
+ """
+
+def stop_bt_client(pid):
+
+ int_pid = int(pid)
+ os.kill(int_pid, signal.SIGKILL) # kill generates zombies
+ os.wait()
+ processes[int_pid][0].close()
+ processes[int_pid][1].close()
+ del processes[int_pid]
+ if(DEBUG):
+ print "Server: killed process with pid = ", pid
+
+def doServer():
+
+ serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if(DEBUG):
+ print "Server: host ip = %s, port = %d"%(SERVER_HOST,SERVER_PORT)
+ serversocket.bind((SERVER_HOST, SERVER_PORT));
+ serversocket.listen(10) #max 10 requests
+ clientsocks = []
+ while(1):
+ if(DEBUG):
+ print "Server: accepting connections"
+ (clientsock, address) = serversocket.accept();
+ if(DEBUG):
+ print "Server: accepted connection from ", address
+
+ if clientsock not in states:
+ states[clientsock] = WAITING_MSG_TYPE;
+
+ if states[clientsock] == WAITING_MSG_TYPE:
+ print states[clientsock]
+ msg = clientsock.recv(BUFFER_SIZE)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ msg_types = {
+ START_MSG: WAITING_START_DATA,
+ STOP_MSG: WAITING_STOP_DATA,
+ STATUS_MSG: WAITING_STATUS_DATA
+ }
+ if msg not in msg_types:
+ clientsock.send(ERROR_MSG +"wrong message type " + msg)
+ else:
+ states[clientsock] = msg_types[msg]
+ clientsock.send(ACK_MSG)
+ #else:
+ print states[clientsock]
+
+ if states[clientsock] == WAITING_START_DATA:
+ bt_client_data = recv_pickled_data(clientsock)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ client_pid = start_bt_client(bt_client_data)
+ clientsock.send(ACK_MSG +" "+ str(client_pid))
+
+ elif states[clientsock] == WAITING_STOP_DATA:
+ client_pid = recv_pickled_data(clientsock)
+ if(DEBUG):
+ print "Server: received message:\n", msg
+ stop_bt_client(client_pid)
+ clientsock.send(ACK_MSG)
+
+ elif states[clientsock] == WAITING_STATUS_DATA:
+ config = recv_pickled_data(clientsock)
+ clientsock.send(ACK_MSG)
+
+ states[clientsock] = WAITING_MSG_TYPE
+
+ # clientsock.recv(BUFFER_SIZE)
+ # recv_pickled_data(clientsock)
+ clientsock.close()
+
+if __name__ == "__main__":
+ doServer()
+
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running Transmission client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class TransmissionRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+ BitTorrentClientRun.__init__(self, base_path,
+ "$base_path/transmission --download-dir $download_dir --port $port $torrent_file > $output_dir/$output_file",
+ "TR_DEBUG=2 $base_path/transmission --download-dir $download_dir --port $port $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file")
+
+
+def main():
+
+ """
+ Test case
+ """
+
+ tr = TransmissionRun("/home/p2p/p2p-clients/transmission")
+ tr.config_run("/home/p2p/p2p-dld/transmission", "/home/p2p/p2p-log/transmission", "transmission-fedora.out", "/home/p2p/p2p-log/transmission", "transmission-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ tr.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running Tribler client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class TriblerRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+
+ self.set_PYTHONPATH(base_path)
+ BitTorrentClientRun.__init__(self, base_path,
+ "python $base_path/Tribler/Tools/cmdlinedl.py -o $download_dir -p $port $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file",
+ "python $base_path/Tribler/Tools/cmdlinedl.py -o $download_dir -p $port $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file")
+
+
+ """
+ Adds lines in cmdlinedl.py that set the PYTHONPATH variable.
+ """
+ def set_PYTHONPATH(self, base_path):
+ filename = base_path + "/Tribler/Tools/cmdlinedl.py"
+ tmp_filename = filename + "_tmp"
+ if not os.path.exists(filename) or not os.path.isfile(filename):
+ print "Error: invalid Tribler path ", filename
+ return
+ f = open(filename, "r");
+ f_copy = open(tmp_filename, "w");
+ import_line = "import sys"
+ instr_line = "\nsys.path.append('"+base_path+"')\n"
+ exists = False
+ position = -1
+ exists = False
+ for line in f:
+ if line.find("import")>=0 and line.find("sys")>=0 and (not line.find("sys."))>=0:
+ #position = f.tell() + len(line) + 1
+ f_copy.write(line)
+ f_copy.write(instr_line)
+ continue
+ if line == instr_line:
+ exists = True
+ break
+ f_copy.write(line)
+
+ f_copy.close()
+ f.close()
+ if not exists:
+ os.remove(filename)
+ os.rename(tmp_filename, filename)
+ else:
+ os.remove(tmp_filename)
+
+def main():
+
+ """
+ Test case
+ """
+
+ tr = TriblerRun("/home/p2p/p2p-clients/tribler")
+ #tr.config_run("/home/p2p/p2p-dld/tribler", "/home/p2p/p2p-log/tribler", "tribler-fedora.out", "/home/p2p/p2p-log/tribler", "tribler-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ #tr.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+"""
+ Base class for running Transmission client instances
+ 2010, Razvan Deaconescu, razvan.deaconescu@cs.pub.ro
+"""
+
+import sys
+import os.path
+from BitTorrentClientRun import BitTorrentClientRun
+
+DEBUG = False
+
+
+class TransmissionRun(BitTorrentClientRun):
+ def __init__(self, base_path):
+ BitTorrentClientRun.__init__(self, base_path,
+ "$base_path/cli/transmissioncli --download-dir $download_dir --port $port $torrent_file > $output_dir/$output_file",
+ "TR_DEBUG=2 $base_path/cli/transmissioncli --download-dir $download_dir --port $port $torrent_file 2> $log_dir/$log_file > $output_dir/$output_file")
+
+
+def main():
+
+ """
+ Test case
+ """
+
+ tr = TransmissionRun("/home/p2p/p2p-clients/transmission")
+ tr.config_run("/home/p2p/p2p-dld/transmission", "/home/p2p/p2p-log/transmission", "transmission-fedora.out", "/home/p2p/p2p-log/transmission", "transmission-fedora.log", 10150, "/home/p2p/p2p-meta/fedora.torrent")
+ tr.start()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+#!/usr/bin/env python
+
+import sys, os, time, atexit
+from signal import SIGTERM
+
+class Daemon:
+ """
+ A generic daemon class.
+
+ Usage: subclass the Daemon class and override the run() method
+ """
+ def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
+ self.stdin = stdin
+ self.stdout = stdout
+ self.stderr = stderr
+ self.pidfile = pidfile
+
+ def daemonize(self):
+ """
+ do the UNIX double-fork magic, see Stevens' "Advanced
+ Programming in the UNIX Environment" for details (ISBN 0201563177)
+ http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
+ """
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit first parent
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+ sys.exit(1)
+
+ # decouple from parent environment
+ os.chdir("/")
+ os.setsid()
+ os.umask(0)
+
+ # do second fork
+ try:
+ pid = os.fork()
+ if pid > 0:
+ # exit from second parent
+ sys.exit(0)
+ except OSError, e:
+ sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+ sys.exit(1)
+
+ # redirect standard file descriptors
+ sys.stdout.flush()
+ sys.stderr.flush()
+ si = file(self.stdin, 'r')
+ so = file(self.stdout, 'a+')
+ se = file(self.stderr, 'a+', 0)
+ os.dup2(si.fileno(), sys.stdin.fileno())
+ os.dup2(so.fileno(), sys.stdout.fileno())
+ os.dup2(se.fileno(), sys.stderr.fileno())
+
+ # write pidfile
+ atexit.register(self.delpid)
+ pid = str(os.getpid())
+ file(self.pidfile,'w+').write("%s\n" % pid)
+
+ def delpid(self):
+ os.remove(self.pidfile)
+
+ def start(self):
+ """
+ Start the daemon
+ """
+ # Check for a pidfile to see if the daemon already runs
+ try:
+ pf = file(self.pidfile,'r')
+ pid = int(pf.read().strip())
+ pf.close()
+ except IOError:
+ pid = None
+
+ if pid:
+ message = "pidfile %s already exist. Daemon already running?\n"
+ sys.stderr.write(message % self.pidfile)
+ sys.exit(1)
+
+ # Start the daemon
+ self.daemonize()
+ self.run()
+
+ def stop(self):
+ """
+ Stop the daemon
+ """
+ # Get the pid from the pidfile
+ try:
+ pf = file(self.pidfile,'r')
+ pid = int(pf.read().strip())
+ pf.close()
+ except IOError:
+ pid = None
+
+ if not pid:
+ message = "pidfile %s does not exist. Daemon not running?\n"
+ sys.stderr.write(message % self.pidfile)
+ return # not an error in a restart
+
+ # Try killing the daemon process
+ try:
+ while 1:
+ os.kill(pid, SIGTERM)
+ time.sleep(0.1)
+ except OSError, err:
+ err = str(err)
+ if err.find("No such process") > 0:
+ if os.path.exists(self.pidfile):
+ os.remove(self.pidfile)
+ else:
+ print str(err)
+ sys.exit(1)
+
+ def restart(self):
+ """
+ Restart the daemon
+ """
+ self.stop()
+ self.start()
+
+ def run(self):
+ """
+ You should override this method when you subclass Daemon. It will be called after the process has been
+ daemonized by start() or restart().
+ """
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<clients>
+ <client id="tribler">
+ <run type="script">
+ <file>Tribler/Tools/cmdlinedl.py</file>
+ <interpreter>python </interpreter>
+ <prefix>PYTHONPATH=.</prefix>
+ <suffix></suffix>
+ </run>
+ <upload_limit_option></upload_limit_option>
+ <download_limit_option></download_limit_option>
+ <port_option>-p</port_option>
+ <logging_dir_option>-l</logging_dir_option>
+ <download_dir_option>-d</download_dir_option>
+ </client>
+ <client id="libtorrent">
+ <run type="executable">
+ <file>hrktorrent</file>
+ <interpreter></interpreter>
+ <prefix></prefix>
+ <suffix></suffix>
+ </run>
+ <port_option>-p</port_option>
+ <download_dir_option>-d</download_dir_option>
+ </client>
+ <client id="transmission">
+ <run type="executable">
+ <file>src/transmission-cli</file>
+ <interpreter></interpreter>
+ <prefix></prefix>
+ <suffix></suffix>
+ </run>
+ <upload_limit_option>-u</upload_limit_option>
+ <download_limit_option>-d</download_limit_option>
+ <port_option>-p</port_option>
+ <logging_dir_option>-l</logging_dir_option>
+ <download_dir_option>-o</download_dir_option>
+ </client>
+</clients>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<nodes>
+ <node id="1">
+ <public_address>141.85.224.204</public_address>
+ <public_port>10150</public_port>
+ <public_iface>eth0</public_iface>
+ <private_address>172.16.20.3</private_address>
+ <private_port></private_port>
+ <private_iface>venet0:0</private_iface>
+ <ssh_port>20322</ssh_port>
+ <username>p2p</username>
+ <listen_port>10004</listen_port>
+ <daemon_dir>/home/p2p/cs-p2p-next/bt_comm/server</daemon_dir>
+ <clients>
+ <client id="tribler">
+ <base>/home/p2p/p2p-clients/tribler/</base>
+ </client>
+ <client id="libtorrent">
+ <base>/home/p2p/p2p-clients/libtorrent/</base>
+ </client>
+ <client id="transmission">
+ <base>/home/p2p/p2p-clients/transmission/</base>
+ </client>
+ </clients>
+ </node>
+</nodes>
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<swarm>
+ <torrent_file>/home/p2p/p2p-meta/bbt316.torrent</torrent_file>
+ <instance id="1">
+ <node>1</node>
+ <client>tribler</client>
+ <upload_limit>512</upload_limit>
+ <download_limit>256</download_limit>
+ <download_dir>/home/p2p/p2p-dld/tribler</download_dir>
+ <log_dir>/home/p2p/p2p-log/tribler</log_dir>
+ <log_file>tribler-bbt316.log</log_file>
+ <output_dir>/home/p2p/p2p-log/tribler</output_dir>
+ <output_file>tribler-bbt316.out</output_file>
+ <actions>
+ <action type="start" delay="00:05:00" />
+ <action type="stop" delay="00:10:00" />
+ <action type="start" delay="00:15:00" />
+ <action type="stop" delay="00:20:00" />
+ <action type="start" delay="00:25:00" />
+ <action type="start" delay="end" />
+ </actions>
+ </instance>
+</swarm>