Some tidying up and re-arranging.
[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 time, sys, traceback
19 import ConfigParser
20
21 def attempt_read_config(config, filename):
22     try:
23         with open(filename, 'r') as f:
24             config.readfp(f)
25     except IOError:
26         print "Could not read %s. Falling back." % filename
27
28 def create_config():
29     config = ConfigParser.ConfigParser()
30     # set some defaults, which will be overwritten by the config file
31     config.add_section('server')
32     config.set('server','banner', 'Welcome to Electrum!')
33     config.set('server', 'host', 'localhost')
34     config.set('server', 'native_port', '50000')
35     config.set('server', 'stratum_tcp_port', '50001')
36     config.set('server', 'stratum_http_port', '8081')
37     config.set('server', 'password', '')
38     config.set('server', 'irc', 'yes')
39     config.set('server', 'irc_nick', '')
40     config.add_section('database')
41     config.set('database', 'type', 'psycopg2')
42     config.set('database', 'database', 'abe')
43     config.set('server', 'backend', 'abe')
44
45     for path in ('', '/etc/'):
46         filename = path + 'electrum.conf'
47         attempt_read_config(config, filename)
48
49     try:
50         with open('/etc/electrum.banner', 'r') as f:
51             config.set('server','banner', f.read())
52     except IOError:
53         pass
54
55     return config
56
57 def run_rpc_command(command, stratum_http_port):
58     import jsonrpclib
59     server = jsonrpclib.Server('http://%s:%s'%(host, stratum_http_port))
60     if command == 'stop':
61         result = server.server.stop(password)
62     else:
63         result = "Unknown command: '%s'" % command
64     print result
65
66 if __name__ == '__main__':
67     config = create_config()
68     password = config.get('server', 'password')
69     host = config.get('server', 'host')
70     native_port = config.get('server', 'native_port')
71     stratum_tcp_port = config.get('server', 'stratum_tcp_port')
72     stratum_http_port = config.get('server', 'stratum_http_port')
73
74     if len(sys.argv) > 1:
75         run_rpc_command(sys.argv[1], stratum_http_port)
76         sys.exit(0)
77
78     from processor import Dispatcher
79     from transports.stratum_http import HttpServer
80     from transports.stratum_tcp import TcpServer
81     from transports.native import NativeServer
82
83     from modules.irc import ServerProcessor
84     backend_name = config.get('server', 'backend')
85     if backend_name == "libbitcoin":
86         # NativeServer cannot be used with libbitcoin
87         native_port = None
88         config.set('server', 'native_port', '')
89         from modules.python_bitcoin import BlockchainProcessor
90     elif backend_name == "abe":
91         from modules.abe import AbeProcessor as BlockchainProcessor
92     else:
93         sys.stderr.write('Unknown backend specified\n')
94         sys.exit(-1)
95
96     # Create hub
97     dispatcher = Dispatcher()
98     shared = dispatcher.shared
99
100     # Create and register processors
101     chain_proc = BlockchainProcessor(config)
102     dispatcher.register('blockchain', chain_proc)
103
104     server_proc = ServerProcessor(config)
105     dispatcher.register('server', server_proc)
106
107     transports = []
108     # Create various transports we need
109     if native_port is not None:
110         server_banner = config.get('server','banner')
111         native_server = NativeServer(shared, chain_proc, server_proc,
112                                      server_banner, host, int(native_port))
113         transports.append(native_server)
114
115     if stratum_tcp_port is not None:
116         tcp_server = TcpServer(dispatcher, host, int(stratum_tcp_port))
117         transports.append(tcp_server)
118
119     if stratum_http_port is not None:
120         http_server = HttpServer(dispatcher, host, int(stratum_http_port))
121         transports.append(http_server)
122
123     for server in transports:
124         server.start()
125
126     print "Starting Electrum server on", host
127     while not shared.stopped():
128         time.sleep(1)
129     print "Server stopped"
130