remove support for abe
[electrum-server.git] / server.py
1 #!/usr/bin/env python
2 # Copyright(C) 2012 thomasv@gitorious
3
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as
6 # published by the Free Software Foundation, either version 3 of the
7 # License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Affero General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public
15 # License along with this program.  If not, see
16 # <http://www.gnu.org/licenses/agpl.html>.
17
18 import ConfigParser
19 import logging
20 import socket
21 import sys
22 import time
23 import threading
24 import traceback
25
26 import json
27
28 logging.basicConfig()
29
30 if sys.maxsize <= 2**32:
31     print "Warning: it looks like you are using a 32bit system. You may experience crashes caused by mmap"
32
33
34 def attempt_read_config(config, filename):
35     try:
36         with open(filename, 'r') as f:
37             config.readfp(f)
38     except IOError:
39         pass
40
41
42 def create_config():
43     config = ConfigParser.ConfigParser()
44     # set some defaults, which will be overwritten by the config file
45     config.add_section('server')
46     config.set('server', 'banner', 'Welcome to Electrum!')
47     config.set('server', 'host', 'localhost')
48     config.set('server', 'report_host', '')
49     config.set('server', 'stratum_tcp_port', '50001')
50     config.set('server', 'stratum_http_port', '8081')
51     config.set('server', 'stratum_tcp_ssl_port', '')
52     config.set('server', 'stratum_http_ssl_port', '')
53     config.set('server', 'report_stratum_tcp_port', '')
54     config.set('server', 'report_stratum_http_port', '')
55     config.set('server', 'report_stratum_tcp_ssl_port', '')
56     config.set('server', 'report_stratum_http_ssl_port', '')
57     config.set('server', 'ssl_certfile', '')
58     config.set('server', 'ssl_keyfile', '')
59     config.set('server', 'password', '')
60     config.set('server', 'irc', 'yes')
61     config.set('server', 'irc_nick', '')
62     config.set('server', 'coin', '')
63     config.set('server', 'datadir', '')
64
65     # use leveldb as default
66     config.set('server', 'backend', 'leveldb')
67     config.add_section('leveldb')
68     config.set('leveldb', 'path', '/dev/shm/electrum_db')
69     config.set('leveldb', 'pruning_limit', '100')
70
71     for path in ('/etc/', ''):
72         filename = path + 'electrum.conf'
73         attempt_read_config(config, filename)
74
75     try:
76         with open('/etc/electrum.banner', 'r') as f:
77             config.set('server', 'banner', f.read())
78     except IOError:
79         pass
80
81     return config
82
83
84 def run_rpc_command(command, stratum_tcp_port):
85     try:
86         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
87         s.connect((host, int(stratum_tcp_port)))
88     except:
89         print "cannot connect to server."
90         return
91
92     method = 'server.' + command
93     request = json.dumps({'id': 0, 'method': method, 'params': [password]})
94     s.send(request + '\n')
95     msg = ''
96     while True:
97         o = s.recv(1024)
98         if not o: break
99         msg += o
100         if msg.find('\n') != -1:
101             break
102     s.close()
103     r = json.loads(msg).get('result')
104
105     if command == 'info':
106         now = time.time()
107         print 'type           address   sub  version  time'
108         for item in r:
109             print '%4s   %15s   %3s  %7s  %.2f' % (item.get('name'),
110                                                    item.get('address'),
111                                                    item.get('subscriptions'),
112                                                    item.get('version'),
113                                                    (now - item.get('time')),
114                                                    )
115     else:
116         print r
117
118
119 if __name__ == '__main__':
120     config = create_config()
121     password = config.get('server', 'password')
122     host = config.get('server', 'host')
123     stratum_tcp_port = config.get('server', 'stratum_tcp_port')
124     stratum_http_port = config.get('server', 'stratum_http_port')
125     stratum_tcp_ssl_port = config.get('server', 'stratum_tcp_ssl_port')
126     stratum_http_ssl_port = config.get('server', 'stratum_http_ssl_port')
127     ssl_certfile = config.get('server', 'ssl_certfile')
128     ssl_keyfile = config.get('server', 'ssl_keyfile')
129
130     if stratum_tcp_ssl_port or stratum_http_ssl_port:
131         assert ssl_certfile and ssl_keyfile
132
133     if len(sys.argv) > 1:
134         run_rpc_command(sys.argv[1], stratum_tcp_port)
135         sys.exit(0)
136
137     from processor import Dispatcher, print_log
138     from backends.irc import ServerProcessor
139
140     backend_name = config.get('server', 'backend')
141     if backend_name == 'libbitcoin':
142         from backends.libbitcoin import BlockchainProcessor
143     elif backend_name == 'leveldb':
144         from backends.bitcoind import BlockchainProcessor
145     else:
146         print "Unknown backend '%s' specified\n" % backend_name
147         sys.exit(1)
148
149     for i in xrange(5):
150         print ""
151     print_log("Starting Electrum server on", host)
152
153     # Create hub
154     dispatcher = Dispatcher(config)
155     shared = dispatcher.shared
156
157     # Create and register processors
158     chain_proc = BlockchainProcessor(config, shared)
159     dispatcher.register('blockchain', chain_proc)
160
161     server_proc = ServerProcessor(config)
162     dispatcher.register('server', server_proc)
163
164     transports = []
165     # Create various transports we need
166     if stratum_tcp_port:
167         from transports.stratum_tcp import TcpServer
168         tcp_server = TcpServer(dispatcher, host, int(stratum_tcp_port), False, None, None)
169         transports.append(tcp_server)
170
171     if stratum_tcp_ssl_port:
172         from transports.stratum_tcp import TcpServer
173         tcp_server = TcpServer(dispatcher, host, int(stratum_tcp_ssl_port), True, ssl_certfile, ssl_keyfile)
174         transports.append(tcp_server)
175
176     if stratum_http_port:
177         from transports.stratum_http import HttpServer
178         http_server = HttpServer(dispatcher, host, int(stratum_http_port), False, None, None)
179         transports.append(http_server)
180
181     if stratum_http_ssl_port:
182         from transports.stratum_http import HttpServer
183         http_server = HttpServer(dispatcher, host, int(stratum_http_ssl_port), True, ssl_certfile, ssl_keyfile)
184         transports.append(http_server)
185
186     for server in transports:
187         server.start()
188
189     while not shared.stopped():
190         try:
191             time.sleep(1)
192         except:
193             shared.stop()
194
195     print_log("Electrum Server stopped")