#!/usr/bin/python import SocketServer from threading import Thread import select import socket import urllib import os from queue import QueueEntry from BitQueue import version,BindException import policy from i18n import * class WebServiceServer(SocketServer.ThreadingTCPServer,Thread): allow_reuse_address = 1 def __init__(self,RequestHandlerClass,queue): Thread.__init__(self) self.queue = queue self.policy = policy.get_policy() self._quit = 0 addr = self.policy(policy.WEBSERVICE_IP), \ self.policy(policy.WEBSERVICE_PORT) try: SocketServer.ThreadingTCPServer.__init__(self,addr,RequestHandlerClass) except Exception,why: raise BindException,'%s:%d: %s' % (addr+(str(why),)) def get_request(self): while not self._quit: try: ifds,ofds,efds = select.select([self],[],[],10) except: ifds,ofds,efds = [],[],[] if len(ifds) > 0: return self.socket.accept() return None def run(self): while not self._quit: try: self.handle_request() except TypeError: pass print 'webservice stopped' def stop(self): self._quit = 1 self.server_close() class WebServiceRequestHandler(SocketServer.StreamRequestHandler): rbufsize = 0 def setup(self): SocketServer.StreamRequestHandler.setup(self) self.queue = self.server.queue self.policy = self.server.policy self.id = self.policy(policy.WEBSERVICE_ID).split(',') def handle(self): try: data = self.read(5048) idline,cmdline = data.split('\n') # idline = self.rfile.readline() # cmdline = self.rfile.readline() self.handle_cmd(idline,cmdline) except IOError,why: pass except ValueError,why: print why def read(self,size): return self.connection.recv(size) def write(self,buf): return self.connection.send(buf) def handle_cmd(self,idline,cmdline): key,id = idline.split('|',1) if key != 'ID' or not id in self.id: self.handle_error('mismatch id') return cmd,args = cmdline.split('|',1) attr = 'do_%s' % cmd if hasattr(self,attr): if self.policy(policy.WEBSERVICE_+cmd.lower()): getattr(self,attr)(args) else: self.handle_noperm(cmd.upper()) else: self.handle_error('unknown command %s in WebServiceRequestHandler' % cmd) return def feedback(self,msg,type='Feedback'): self.write('%s\n%s' % (type,msg)) def handle_error(self,msg,cmd=None): if cmd: msg = '%s,%s' % (cmd,msg) self.feedback('Error=%s' % msg) def handle_noperm(self,cmd): self.handle_error('permission denied',cmd=cmd) def handle_notimpl(self,cmd): self.handle_error('not implemented',cmd=cmd) def do_CLOSE(self,args): self.handle_notimpl('CLOSE') def do_QUERY(self,args): if not args: fields = QueueEntry.default_fields else: fields = args.split(',') fields.append('infohash') header = [] nf = [] for field in fields: if not field in QueueEntry.all_fields: self.handle_error('unknown field %s' % field,cmd='QUERY') return header.append(QueueEntry.header_fields[field]) reply = '' for j in self.queue.jobs(): entry = [] for field in fields: entry.append(str(j.get(field))) reply += '|'.join(entry)+'\n' self.feedback(reply,type='|'.join(header)) def do_ADD(self,args): reply = self.queue.add_url(args) if reply.has_key('error'): self.handle_error(reply.get('error'),cmd='ADD') else: self.feedback('OK') def do_DELETE(self,args): if args == 'COMPLETED': for j in self.queue.jobs(): if j.state in [STATE_FINISHED,STATE_SEEDING]: reply = self.queue.remove(j) if reply: self.handle_error(reply,cmd='DELETE') return else: item = self.queue.job(args) reply = self.queue.remove(item) if reply: self.handle_error(reply,cmd='DELETE') return self.feedback('OK') def do_RESUME(self,args): item = self.queue.job(args) if not item: self.handle_error('not found',cmd='RESUME') return self.queue.resume(item) self.feedback('OK') def do_PAUSE(self,args): item = self.queue.job(args) if not item: self.handle_error('not found',cmd='PAUSE') return self.queue.resume(item) self.queue.pause(item) self.feedback('OK') def do_QUEUE(self,args): item = self.queue.job(args) if not item: self.handle_error('not found',cmd='QUEUE') return self.queue.pause(item) self.queue.resume(item) self.feedback('OK') def do_VERSION(self,args): self.feedback(version,type='Version') def do_GSET(self,args): ret='' setting=urllib.unquote_plus(args) #print setting key,value=setting.split('=',1) self.policy.update(key.strip(),value.strip()) ret = ret + key + ' = ' + value self.policy.save() self.feedback(ret) class WebServiceRequest: def __init__(self,addr,id): self.addr = addr self.id = id def _request(self,msg): self.socket = socket.socket() self.socket.connect(self.addr) self.socket.send('ID|%s\n%s' % (self.id,msg)) reply = self.socket.recv(10240) self.socket.close() return self._decode(reply) def _decode(self,reply): try: data = reply.split('\n',1) key,value = data except ValueError: return data,'' return key,value def query(self,fields=QueueEntry.default_fields): request = 'QUERY|%s' % ','.join(fields) header,lines = self._request(request) if header == 'Feedback': return lines header = header.split('|') values = [] lines = lines.strip().split('\n') for line in lines: pairs = map(None,header,line.split('|')) item = {} for key,value in pairs: item[key] = value values.append(item) return header,values def add(self,url): request = 'ADD|%s' % url header,lines = self._request(request) return header,lines def gset(self,args): all_lines='' request = 'GSET|%s'% args urllib.quote_plus(request) header, lines = self._request(request) return header, lines class WebInterface: def __init__(self): self.policy = policy.get_policy() self.addr = (self.policy(policy.WEBSERVICE_IP), self.policy(policy.WEBSERVICE_PORT)) def process(self,command,args=[]): self.request = WebServiceRequest(self.addr, self.policy(policy.WEBSERVICE_ID)) attr = 'do_%s' % command if hasattr(self,attr): ret = getattr(self,attr)(args) else: ret = 'unknown command %s in WebInterface' % command return ret def do_query(self,args): try: reply = self.request.query() header,values = reply except ValueError: return str(reply) except socket.error,why: return "Socket error - problem connecting to web service" except Exception,why: return str(why) #for item in values: # print '%(Title)s\n\t%(Progress)6s %(DL Speed)9s %(UL Speed)9s %(#Seeds)6s %(#Peers)6s %(BT Status)-10s' % item return values def do_add(self,args): if len(args) != 1: print 'an argument required' return url = args[0] if url.find(':/') == -1: url = os.path.abspath(url) url = urllib.quote(url) try: header,lines = self.request.add(url) except socket.error,why: return "Socket error - problem connecting to web service" except Exception,why: return str(why) def do_gset(self,args): if len(args) < 1: print 'an argument required' return for arg in args: try: header,lines = self.request.gset(arg) except socket.error,why: return "Socket error - problem connecting to web service" except Exception,why: return str(why)