清华大佬耗费三个月吐血整理的几百G的资源,免费分享!....>>>
# -*- coding: utf-8 -*-
from xmlrpclib import ServerProxy, Fault
from os.path import join, isfile, abspath
from SimpleXMLRPCServer import SimpleXMLRPCServer
from urlparse import urlparse
import sys
import xmlrpclib
SimpleXMLRPCServer.allow_reuse_address = 1
#避免循环请求和长链请求。之所以用6是采用了六度分隔的原理
MAX_HISTORY_LENGTH = 6
UNHANDLED = 100
ACCESS_DENIED = 200
class UnhandledQuery(Fault):
def __init__(self, message="Counldn't handle the query"):
Fault.__init__(self, UNHANDLED, message)
class AccessDenied(Fault):
def __init__(self, message='Access denied'):
Fault.__init__(self, ACCESS_DENIED, message)
def inside(dirs, name):
the_dir = abspath(dirs)
name = abspath(name)
return name.startswith(join(the_dir, ''))
def getPort(url):
name = urlparse(url)[1]
parts = name.split(':')
return int(parts[-1])
class Node:
def __init__(self, url, dirname, secret):
self.url = url
self.dirname = dirname
self.secret = secret
self.known = set()
def query(self, query, history=[]):
try:
return self._handle(query)
except UnhandledQuery:
history = history + [self.url]
if len(history) >= MAX_HISTORY_LENGTH: raise
return self._broadcast(query, history)
def hello(self, other):
self.known.add(other)
return 0
def fetch(self, query, secret):
"""找到并下载资源"""
if secret != self.secret: raise AccessDenied
result = self.query(query)
f = open(join(self.dirname, query), 'wb')
f.write(result.data)
f.close()
return 0
def _start(self):
#启动XML_RPC服务器
s = SimpleXMLRPCServer(("", getPort(self.url)), logRequests=False)
s.register_instance(self)
s.serve_forever()
def _handle(self, query):
"""处理请求"""
name = join(self.dirname, query)
if not isfile(name): raise UnhandledQuery
if not inside(self.dirname, name): raise AccessDenied
return xmlrpclib.Binary(open(name, 'rb').read())
def _broadcast(self, query, history):
"""将查询广播到所有已知的Node"""
for other in self.known.copy():
if other in history: continue
try:
s = ServerProxy(other)
return s.query(query, history)
except Fault, f:
if f.faultCode == UNHANDLED: pass
else: self.known.remove(other)
except:
self.known.remove(other)
raise UnhandledQuery
def main():
url, directory, secret = sys.argv[1:]
n = Node(url, directory, secret)
n._start()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt: sys.exit()