-
Notifications
You must be signed in to change notification settings - Fork 2
/
dtella.py
executable file
·225 lines (175 loc) · 6.33 KB
/
dtella.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/usr/bin/env python
"""
Dtella - Startup Module
Copyright (C) 2007-2008 Dtella Labs (http://www.dtella.org/)
Copyright (C) 2007-2008 Paul Marks (http://www.pmarks.net/)
Copyright (C) 2007-2008 Jacob Feisley (http://www.feisley.com/)
$Id$
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
# When Dtella is packaged by py2app, dtella.py and the dtella.* package are
# split into separate directories, causing the import to fail. We'll hack
# around the problem by stripping the base directory from the path.
if __name__ == '__main__':
try:
import dtella.common
except ImportError:
import sys
sys.path = [p for p in sys.path if p != sys.path[0]]
# Patch the twisted bugs before doing anything else.
import dtella.common.fix_twisted
import twisted.internet.error
import twisted.python.log
from twisted.internet import reactor
import sys
import socket
import time
import getopt
from dtella.common.log import setLogFile
from dtella.common.log import LOG
def addTwistedErrorCatcher(handler):
def logObserver(eventDict):
if not eventDict['isError']:
return
try:
text = eventDict['failure'].getTraceback()
except KeyError:
text = ' '.join(str(m) for m in eventDict['message'])
handler(text)
twisted.python.log.startLoggingWithObserver(logObserver, setStdout=False)
def runBridge():
import dtella.bridge_config as cfg
setLogFile(cfg.file_base + ".log", 4<<20, 4)
LOG.debug("Bridge Logging Manager Initialized")
addTwistedErrorCatcher(LOG.critical)
from dtella.bridge.main import DtellaMain_Bridge
dtMain = DtellaMain_Bridge()
from dtella.bridge.bridge_server import getServiceConfig
scfg = getServiceConfig()
scfg.startService(dtMain)
reactor.run()
def runDconfigPusher():
import dtella.bridge_config as cfg
setLogFile(cfg.file_base + ".log", 4<<20, 4)
LOG.debug("Dconfig Pusher Logging Manager Initialized")
addTwistedErrorCatcher(LOG.critical)
from dtella.bridge.push_dconfig_main import DtellaMain_DconfigPusher
dtMain = DtellaMain_DconfigPusher()
reactor.run()
def runClient(dc_port):
#Logging for Dtella Client
setLogFile("dtella.log", 1<<20, 1)
LOG.debug("Client Logging Manager Initialized")
from dtella.client.main import DtellaMain_Client
dtMain = DtellaMain_Client()
import dtella.local_config as local
from dtella.common.util import get_version_string
def botErrorReporter(text):
dch = dtMain.dch
if dch:
dch.bot.say(
"Something bad happened. You might want to email this to "
"bugs@dtella.org so we'll know about it:\n"
"Version: %s %s\n%s" %
(local.hub_name, get_version_string()[3:], text))
addTwistedErrorCatcher(botErrorReporter)
addTwistedErrorCatcher(LOG.critical)
from dtella.client.dc import DCFactory
dfactory = DCFactory(dtMain, dc_port)
LOG.info("%s %s" % (local.hub_name, local.version))
def cb(first):
try:
reactor.listenTCP(dc_port, dfactory, interface='127.0.0.1')
except twisted.internet.error.CannotListenError:
if first:
LOG.warning("TCP bind failed. Killing old process...")
if terminate(dc_port):
LOG.info("Ok. Sleeping...")
reactor.callLater(2.0, cb, False)
else:
LOG.error("Kill failed. Giving up.")
reactor.stop()
else:
LOG.error("Bind failed again. Giving up.")
reactor.stop()
else:
LOG.info("Listening on 127.0.0.1:%d" % dc_port)
dtMain.startConnecting()
reactor.callWhenRunning(cb, True)
reactor.run()
def terminate(dc_port):
# Terminate another Dtella process on the local machine
try:
print "Sending Packet of Death on port %d..." % dc_port
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', dc_port))
sock.sendall("$KillDtella|")
sock.close()
except socket.error:
return False
return True
def main():
# Parse command-line arguments
allowed_opts = []
usage_str = "Usage: %s" % sys.argv[0]
try:
import dtella.client
except ImportError:
pass
else:
usage_str += " [--port=#] [--terminate]"
allowed_opts.extend(['port=', 'terminate'])
try:
import dtella.bridge
except ImportError:
pass
else:
usage_str += " [--bridge] [--dconfigpusher] [--makeprivatekey]"
allowed_opts.extend(['bridge', 'dconfigpusher', 'makeprivatekey'])
try:
opts, args = getopt.getopt(sys.argv[1:], '', allowed_opts)
except getopt.GetoptError:
print usage_str
return
opts = dict(opts)
if '--bridge' in opts:
runBridge()
return
if '--dconfigpusher' in opts:
runDconfigPusher()
return
if '--makeprivatekey' in opts:
from dtella.bridge.private_key import makePrivateKey
makePrivateKey()
return
# User-specified TCP port
dc_port = 7314
if '--port' in opts:
try:
dc_port = int(opts['--port'])
if not (1 <= dc_port < 65536):
raise ValueError
except ValueError:
print "Port must be between 1-65535"
return
# Try to terminate an existing process
if '--terminate' in opts:
if terminate(dc_port):
# Give the other process time to exit first
print "Sleeping..."
time.sleep(2.0)
print "Done."
return
runClient(dc_port)
if __name__=='__main__':
main()