emtpy default ssl ports to make ssl optional
[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     config.add_section('database')
65     config.set('database', 'type', 'psycopg2')
66     config.set('database', 'database', 'abe')
67     config.set('database', 'limit', '1000')
68     config.set('server', 'backend', 'abe')
69
70     for path in ('/etc/', ''):
71         filename = path + 'electrum.conf'
72         attempt_read_config(config, filename)
73
74     try:
75         with open('/etc/electrum.banner', 'r') as f:
76             config.set('server', 'banner', f.read())
77     except IOError:
78         pass
79
80     return config
81
82
83 def run_rpc_command(command, stratum_tcp_port):
84     try:
85         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
86         s.connect((host, int(stratum_tcp_port)))
87     except:
88         print "cannot connect to server."
89         return
90
91     method = 'server.' + command
92     request = json.dumps({'id': 0, 'method': method, 'params': [password]})
93     s.send(request + '\n')
94     msg = ''
95     while True:
96         o = s.recv(1024)
97         msg += o
98         if msg.find('\n') != -1:
99             break
100     s.close()
101     r = json.loads(msg).get('result')
102
103     if command == 'info':
104         now = time.time()
105         print 'type           address   sub  version  time'
106         for item in r:
107             print '%4s   %15s   %3s  %7s  %.2f' % (item.get('name'),
108                                                    item.get('address'),
109                                                    item.get('subscriptions'),
110                                                    item.get('version'),
111                                                    (now - item.get('time')),
112                                                    )
113     else:
114         print r
115
116
117 if __name__ == '__main__':
118     config = create_config()
119     password = config.get('server', 'password')
120     host = config.get('server', 'host')
121     stratum_tcp_port = config.get('server', 'stratum_tcp_port')
122     stratum_http_port = config.get('server', 'stratum_http_port')
123     stratum_tcp_ssl_port = config.get('server', 'stratum_tcp_ssl_port')
124     stratum_http_ssl_port = config.get('server', 'stratum_http_ssl_port')
125     ssl_certfile = config.get('server', 'ssl_certfile')
126     ssl_keyfile = config.get('server', 'ssl_keyfile')
127
128     if stratum_tcp_ssl_port or stratum_http_ssl_port:
129         assert ssl_certfile and ssl_keyfile
130
131     if len(sys.argv) > 1:
132         run_rpc_command(sys.argv[1], stratum_tcp_port)
133         sys.exit(0)
134
135     from processor import Dispatcher, print_log
136     from backends.irc import ServerProcessor
137
138     backend_name = config.get('server', 'backend')
139     if backend_name == 'abe':
140         from backends.abe import BlockchainProcessor
141     elif 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")