Generalize the way to setup the server to use Litecoin.
[electrum-server.git] / backends / irc / __init__.py
1 import threading, socket, traceback, time, sys
2
3 def random_string(N):
4     import random, string
5     return ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N))
6
7 from processor import Processor
8 from version import VERSION
9
10 class IrcThread(threading.Thread):
11
12     def __init__(self, processor, config):
13         threading.Thread.__init__(self)
14         self.processor = processor
15         self.daemon = True
16         self.stratum_tcp_port = config.get('server','stratum_tcp_port')
17         self.stratum_http_port = config.get('server','stratum_http_port')
18         self.peers = {}
19         self.host = config.get('server','host')
20         self.nick = config.get('server', 'irc_nick')
21         if not self.nick: self.nick = random_string(10)
22         self.prepend = 'E_'
23         if config.get('server', 'coin') == 'litecoin':
24             self.prepend = 'EL_'
25         self.nick = self.prepend + self.nick
26
27     def get_peers(self):
28         return self.peers.values()
29
30
31     def getname(self):
32         s = 'v' + VERSION + ' '
33         if self.stratum_tcp_port:
34             s += 't' + self.stratum_tcp_port + ' ' 
35         if self.stratum_http_port:
36             s += 'h' + self.stratum_http_port + ' '
37         return s
38
39
40     def run(self):
41         ircname = self.getname()
42
43         while not self.processor.shared.stopped():
44             try:
45                 s = socket.socket()
46                 s.connect(('irc.freenode.net', 6667))
47                 s.send('USER electrum 0 * :' + self.host + ' ' + ircname + '\n')
48                 s.send('NICK ' + self.nick + '\n')
49                 s.send('JOIN #electrum\n')
50                 sf = s.makefile('r', 0)
51                 t = 0
52                 while not self.processor.shared.stopped():
53                     line = sf.readline()
54                     line = line.rstrip('\r\n')
55                     line = line.split()
56                     if not line: continue
57                     if line[0]=='PING': 
58                         s.send('PONG '+line[1]+'\n')
59                     elif '353' in line: # answer to /names
60                         k = line.index('353')
61                         for item in line[k+1:]:
62                             if item.startswith(self.prepend):
63                                 s.send('WHO %s\n'%item)
64                     elif '352' in line: # answer to /who
65                         # warning: this is a horrible hack which apparently works
66                         k = line.index('352')
67                         ip = line[k+4]
68                         ip = socket.gethostbyname(ip)
69                         name = line[k+6]
70                         host = line[k+9]
71                         ports  = line[k+10:]
72                         self.peers[name] = (ip, host, ports)
73                     if time.time() - t > 5*60:
74                         self.processor.push_response({'method':'server.peers', 'params':[self.get_peers()]})
75                         s.send('NAMES #electrum\n')
76                         t = time.time()
77                         self.peers = {}
78             except:
79                 traceback.print_exc(file=sys.stdout)
80             finally:
81                 sf.close()
82                 s.close()
83
84         print "quitting IRC"
85
86
87
88 class ServerProcessor(Processor):
89
90     def __init__(self, config):
91         Processor.__init__(self)
92         self.daemon = True
93         self.banner = config.get('server','banner')
94         self.password = config.get('server','password')
95
96         if config.get('server', 'irc') == 'yes':
97             self.irc = IrcThread(self, config)
98         else: 
99             self.irc = None
100
101
102     def get_peers(self):
103         if self.irc:
104             return self.irc.get_peers()
105         else:
106             return []
107
108
109     def run(self):
110         if self.irc:
111             self.irc.start()
112         Processor.run(self)
113
114     def process(self, request):
115         method = request['method']
116         params = request['params']
117         result = None
118
119         if method in ['server.stop', 'server.info']:
120             try:
121                 password = request['params'][0]
122             except:
123                 password = None
124
125             if password != self.password:
126                 response = { 'id':request['id'], 'result':None,  'error':'incorrect password'}
127                 self.push_response(response)
128                 return
129
130         if method == 'server.banner':
131             result = self.banner.replace('\\n','\n')
132
133         elif method == 'server.peers.subscribe':
134             result = self.get_peers()
135
136         elif method == 'server.version':
137             result = VERSION
138
139         elif method == 'server.stop':
140             self.shared.stop()
141             result = 'ok'
142
143         elif method == 'server.info':
144             result = map(lambda s: { "time":s.time, 
145                                      "name":s.name,
146                                      "address":s.address, 
147                                      "version":s.version, 
148                                      "subscriptions":len(s.subscriptions)}, 
149                          self.dispatcher.request_dispatcher.get_sessions())
150
151         elif method == 'server.cache':
152             p = self.dispatcher.request_dispatcher.processors['blockchain']
153             result = len(repr(p.store.tx_cache))
154
155         elif method == 'server.load':
156             p = self.dispatcher.request_dispatcher.processors['blockchain']
157             result = p.queue.qsize()
158
159         else:
160             print "unknown method", request
161
162         if result!='':
163             response = { 'id':request['id'], 'result':result }
164             self.push_response(response)
165