~ubuntu-branches/ubuntu/wily/d-rats/wily

« back to all changes in this revision

Viewing changes to d-rats_repeater

  • Committer: Bazaar Package Importer
  • Author(s): Steve Conklin
  • Date: 2011-02-18 18:17:24 UTC
  • Revision ID: james.westby@ubuntu.com-20110218181724-kaxw0ceawnu3wgw6
Tags: upstream-0.3.3~b5
ImportĀ upstreamĀ versionĀ 0.3.3~b5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#
 
3
# Copyright 2008 Dan Smith <dsmith@danplanet.com>
 
4
#
 
5
# This program is free software: you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation, either version 3 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
import threading
 
19
import time
 
20
import socket
 
21
import ConfigParser
 
22
import os
 
23
 
 
24
import gettext
 
25
gettext.install("D-RATS")
 
26
 
 
27
from d_rats import platform
 
28
from d_rats import transport
 
29
from d_rats import comm
 
30
 
 
31
if __name__ == "__main__":
 
32
    from optparse import OptionParser
 
33
 
 
34
    o = OptionParser()
 
35
    o.add_option("-c", "--config",
 
36
                 dest="config",
 
37
                 help="Use alternate configuration directory")
 
38
    o.add_option("-d", "--debug",
 
39
                 dest="debug",
 
40
                 action="store_true",
 
41
                 help="Show debug messages on stdout")
 
42
    o.add_option("-C", "--console",
 
43
                 dest="console",
 
44
                 action="store_true",
 
45
                 help="Run in console mode only")
 
46
    (opts, args) = o.parse_args()
 
47
 
 
48
    if opts.config:
 
49
        platform.get_platform(opts.config)
 
50
 
 
51
from d_rats.comm import SWFSerial
 
52
from d_rats import utils
 
53
 
 
54
def call_with_lock(lock, fn, *args):
 
55
    lock.acquire()
 
56
    r = fn(*args)
 
57
    lock.release()
 
58
    return r
 
59
 
 
60
IN = 0
 
61
OUT = 1
 
62
PEEK = 2
 
63
 
 
64
def DEBUG(str):
 
65
    pass
 
66
    #print str
 
67
 
 
68
class CallInfo:
 
69
    def __init__(self, call, transport):
 
70
        self.__call = call
 
71
        self.just_heard(transport)
 
72
 
 
73
    def get_call(self):
 
74
        return self.__call
 
75
 
 
76
    def just_heard(self, transport):
 
77
        self.__heard = time.time()
 
78
        self.__transport = transport
 
79
 
 
80
    def last_heard(self):
 
81
        return time.time() - self.__heard
 
82
 
 
83
    def last_transport(self):
 
84
        return self.__transport
 
85
 
 
86
def call_in_list(callinfo, call):
 
87
    for info in callinfo:
 
88
        if call == info.get_call():
 
89
            return True
 
90
    return False
 
91
 
 
92
class Repeater:
 
93
    def __init__(self, id="D-RATS Network Proxy", reqauth=False, trustlocal=False):
 
94
        self.paths = []
 
95
        self.calls = {}
 
96
        self.thread = None
 
97
        self.enabled = True
 
98
        self.socket = None
 
99
        self.repeat_thread = None
 
100
        self.id = id
 
101
        self.reqauth = reqauth
 
102
        self.trustlocal = trustlocal
 
103
        self.condition = threading.Condition()
 
104
 
 
105
        # Forget port for a station after 10 minutes
 
106
        self.__call_timeout = 600
 
107
 
 
108
    def __repeat(self, transport, frame):
 
109
 
 
110
        if frame.d_station == "!":
 
111
            return
 
112
 
 
113
        srcinfo = self.calls.get(frame.s_station, None)
 
114
        if srcinfo is None and frame.s_station != "CQCQCQ":
 
115
            print "Adding new station %s to port %s" % (frame.s_station,
 
116
                                                        transport)
 
117
            self.calls[frame.s_station] = CallInfo(frame.s_station,
 
118
                                                   transport)
 
119
        elif srcinfo:
 
120
            if srcinfo.last_transport() != transport:
 
121
                print "Station %s moved to port %s" % (frame.s_station,
 
122
                                                       transport)
 
123
            srcinfo.just_heard(transport)
 
124
 
 
125
        dstinfo = self.calls.get(frame.d_station, None)
 
126
        if dstinfo is not None:
 
127
            if not dstinfo.last_transport().enabled:
 
128
                print "Last transport for %s is dead" % frame.d_station
 
129
            elif dstinfo.last_heard() < self.__call_timeout:
 
130
                print "Delivering frame to %s at %s" % \
 
131
                    (frame.d_station, dstinfo.last_transport())
 
132
                dstinfo.last_transport().send_frame(frame.get_copy())
 
133
                return
 
134
            else:
 
135
                print "Last port for %s was %i sec ago (>%i sec)" % \
 
136
                    (frame.d_station,
 
137
                     dstinfo.last_heard(),
 
138
                     self.__call_timeout)
 
139
                
 
140
        print "Repeating frame to %s on all ports" % frame.d_station
 
141
 
 
142
        for path in self.paths[:]:
 
143
            if path == transport:
 
144
                continue
 
145
            if not path.enabled:
 
146
                print "Found a stale path, removing..."
 
147
                path.disable()
 
148
                self.paths.remove(path)
 
149
            else:
 
150
                path.send_frame(frame.get_copy())
 
151
 
 
152
    def add_new_transport(self, transport):
 
153
        self.paths.append(transport)
 
154
 
 
155
        def handler(frame):
 
156
            self.condition.acquire()
 
157
            try:
 
158
                self.__repeat(transport, frame)
 
159
            except Exception, e:
 
160
                print "Exception during __repeat: %s" % e
 
161
            self.condition.release()
 
162
 
 
163
        transport.inhandler = handler
 
164
 
 
165
    def auth_exchange(self, pipe):
 
166
        username = password = None
 
167
        count = 0
 
168
 
 
169
        def readline(_s):
 
170
            data = ""
 
171
            while "\r\n" not in data:
 
172
                try:
 
173
                    _d = _s.read(32)
 
174
                except socket.timeout:
 
175
                    continue
 
176
 
 
177
                if _d == "":
 
178
                    break
 
179
 
 
180
                data += _d
 
181
            return data.strip()
 
182
 
 
183
        while (not username or not password) and count < 3:
 
184
            line = readline(pipe)
 
185
            if not line:
 
186
                continue
 
187
            try:
 
188
                cmd, value = line.split(" ", 1)
 
189
            except Exception, e:
 
190
                print "Unable to read auth command: `%s': %s" % (line, e)
 
191
                pipe.write("501 Invalid Syntax\r\n")
 
192
                break
 
193
 
 
194
            cmd = cmd.upper()
 
195
 
 
196
            if cmd == "USER" and not username and not password:
 
197
                username = value
 
198
            elif cmd == "PASS" and username and not password:
 
199
                password = value
 
200
            else:
 
201
                pipe.write("201 Protocol violation\r\n")
 
202
                break
 
203
 
 
204
            if username and not password:
 
205
                pipe.write("102 %s okay\r\n" % cmd)
 
206
 
 
207
        if not username or not password:
 
208
            print "Negotiation failed with client"
 
209
 
 
210
        return username, password
 
211
 
 
212
    def auth_user(self, pipe):
 
213
        host, port = pipe._socket.getpeername()
 
214
 
 
215
        if not self.reqauth:
 
216
            pipe.write("100 Authentication not required\r\n")
 
217
            return True
 
218
        elif self.trustlocal and host == "127.0.0.1":
 
219
            pipe.write("100 Authentication not required for localhost\r\n")
 
220
            return True
 
221
 
 
222
        auth_fn = platform.get_platform().config_file("users.txt")
 
223
        try:
 
224
            auth = file(auth_fn)
 
225
            lines = auth.readlines()
 
226
            auth.close()
 
227
        except Exception, e:
 
228
            print "Failed to open %s: %s" % (auth_fn, e)
 
229
 
 
230
        pipe.write("101 Authorization required\r\n")
 
231
        username, password = self.auth_exchange(pipe)
 
232
 
 
233
        lno = 1
 
234
        for line in lines:
 
235
            line = line.strip()
 
236
            try:
 
237
                u, p = line.split(" ", 1)
 
238
                u = u.upper()
 
239
            except Exception, e:
 
240
                print "Failed to parse line %i in users.txt: %s" % (lno, line)
 
241
                continue
 
242
 
 
243
            if u == username and p == password:
 
244
                print "Authorized user %s" % u
 
245
                pipe.write("200 Authorized\r\n")
 
246
                return True
 
247
 
 
248
        print "User %s failed to authenticate" % username
 
249
        pipe.write("500 Not authorized\r\n")
 
250
        return False
 
251
 
 
252
    def accept_new(self):
 
253
        if not self.socket:
 
254
            return
 
255
 
 
256
        try:
 
257
            (csocket, addr) = self.socket.accept()
 
258
        except:
 
259
            return
 
260
 
 
261
        print "Accepted new client %s:%i" % addr
 
262
        path = comm.SocketDataPath(csocket)
 
263
        tport = transport.Transporter(path,
 
264
                                      authfn=self.auth_user,
 
265
                                      warmup_timeout=0)
 
266
        self.add_new_transport(tport)
 
267
 
 
268
    def listen_on(self, port):
 
269
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
270
        self.socket.setblocking(0)
 
271
        self.socket.setsockopt(socket.SOL_SOCKET,
 
272
                               socket.SO_REUSEADDR,
 
273
                               1)
 
274
        self.socket.bind(('0.0.0.0', port))
 
275
        self.socket.listen(0)
 
276
 
 
277
    def _repeat(self):
 
278
        while self.enabled:
 
279
            self.condition.acquire()
 
280
            self.accept_new()
 
281
            self.condition.release()
 
282
 
 
283
            time.sleep(0.5)
 
284
 
 
285
        print "Repeater thread ended"
 
286
 
 
287
    def repeat(self):
 
288
        self.repeat_thread = threading.Thread(target=self._repeat)
 
289
        self.repeat_thread.setDaemon(True)
 
290
        self.repeat_thread.start()
 
291
 
 
292
    def stop(self):
 
293
        self.enabled = False
 
294
 
 
295
        self.condition.acquire()
 
296
        self.condition.notify()
 
297
        self.condition.release()
 
298
 
 
299
        if self.repeat_thread:
 
300
            print "Stopping repeater"
 
301
            self.repeat_thread.join()
 
302
 
 
303
        for p in self.paths:
 
304
            print "Stopping"
 
305
            p.disable()
 
306
 
 
307
        if self.socket:
 
308
            self.socket.close()
 
309
 
 
310
class RepeaterUI:
 
311
    def __init__(self):
 
312
        self.repeater = None
 
313
        self.tap = None
 
314
        self.tick = 0
 
315
 
 
316
        self.platform = platform.get_platform()
 
317
        self.config = self.load_config()
 
318
 
 
319
    def load_config(self):
 
320
        self.config_fn = self.platform.config_file("repeater.config")
 
321
        config = ConfigParser.ConfigParser()
 
322
        config.add_section("settings")
 
323
        config.set("settings", "devices", "[]")
 
324
        config.set("settings", "acceptnet", "True")
 
325
        config.set("settings", "netport", "9000")
 
326
        config.set("settings", "id", "W1AW")
 
327
        config.set("settings", "idfreq", "30")
 
328
        config.set("settings", "require_auth", "False")
 
329
        config.set("settings", "trust_local", "True")
 
330
        config.read(self.config_fn)
 
331
 
 
332
        return config
 
333
 
 
334
    def save_config(self, config):
 
335
        self.sync_config()
 
336
        f = file(self.config_fn, "w")
 
337
        config.write(f)
 
338
        f.close()
 
339
 
 
340
    def add_outgoing_paths(self, id, paths):
 
341
        reqauth = self.config.get("settings", "require_auth") == "True"
 
342
        trustlocal = self.config.get("settings", "trust_local") == "True"
 
343
        print "Repeater id is %s" % id
 
344
        self.repeater = Repeater(id, reqauth, trustlocal)
 
345
        for dev,param in paths:
 
346
            to = 0
 
347
            if dev.startswith("net:"):
 
348
                try:
 
349
                    net, host, port = dev.split(":", 2)
 
350
                    port = int(port)
 
351
                except Exception, e:
 
352
                    print "Invalid net string: %s (%s)" % (dev, e)
 
353
                    continue
 
354
 
 
355
                print "Socket %s %i (%s)" % (host, port, param)
 
356
 
 
357
                if param:
 
358
                    path = comm.SocketDataPath((host, port, id, param))
 
359
                else:
 
360
                    path = comm.SocketDataPath((host, port))
 
361
            elif dev.startswith("tnc:"):
 
362
                try:
 
363
                    tnc, port, device = dev.split(":", 2)
 
364
                    device = int(device)
 
365
                except Exception, e:
 
366
                    print "Invalid tnc string: %s (%s)" % (dev, e)
 
367
                    continue
 
368
                print "TNC %s %i" % (dev.replace("tnc:", ""), int(param))
 
369
                path = comm.TNCDataPath((dev.replace("tnc:", ""), int(param)))
 
370
            else:
 
371
                print "Serial: %s %i" % (dev, int(param))
 
372
                path = comm.SerialDataPath((dev, int(param)))
 
373
                to = 3
 
374
 
 
375
            path.connect()
 
376
            tport = transport.Transporter(path, warmup_timout=to)
 
377
            self.repeater.add_new_transport(tport)
 
378
 
 
379
 
 
380
class RepeaterGUI(RepeaterUI):
 
381
    def add_serial(self, widget):
 
382
        name, portspec, param = prompt_for_port(None, pname=False)
 
383
        if portspec is None:
 
384
            return
 
385
 
 
386
        self.dev_list.add_item(portspec, param)
 
387
 
 
388
    def sig_destroy(self, widget, data=None):
 
389
        self.button_off(None, False)
 
390
        self.save_config(self.config)
 
391
        gtk.main_quit()
 
392
 
 
393
    def ev_delete(self, widget, event, data=None):
 
394
        self.button_off(None, False)
 
395
        self.save_config(self.config)
 
396
        self.repeater.stop()
 
397
        gtk.main_quit()
 
398
 
 
399
    def make_side_buttons(self):
 
400
        vbox = gtk.VBox(False, 2)
 
401
 
 
402
        but_add = gtk.Button("Add")
 
403
        but_add.connect("clicked", self.add_serial)
 
404
        but_add.set_size_request(75, 30)
 
405
        but_add.show()
 
406
        vbox.pack_start(but_add, 0,0,0)
 
407
 
 
408
        but_remove = gtk.Button("Remove")
 
409
        but_remove.set_size_request(75, 30)
 
410
        but_remove.connect("clicked", self.button_remove)
 
411
        but_remove.show()
 
412
        vbox.pack_start(but_remove, 0,0,0)
 
413
 
 
414
        vbox.show()
 
415
        
 
416
        return vbox
 
417
 
 
418
    def load_devices(self):
 
419
        try:
 
420
            l = eval(self.config.get("settings", "devices"))
 
421
            for d,r in l:
 
422
                self.dev_list.add_item(d, r)
 
423
        except Exception, e:
 
424
            print "Unable to load devices: %s" % e
 
425
 
 
426
    def make_devices(self):
 
427
        frame = gtk.Frame("Paths")
 
428
 
 
429
        vbox = gtk.VBox(False, 2)
 
430
        frame.add(vbox)
 
431
 
 
432
        hbox = gtk.HBox(False, 2)
 
433
 
 
434
        self.dev_list = miscwidgets.ListWidget([(gobject.TYPE_STRING, "Device"),
 
435
                                                (gobject.TYPE_STRING, "Param")])
 
436
        self.dev_list.show()
 
437
        self.load_devices()
 
438
 
 
439
        sw = gtk.ScrolledWindow()
 
440
        sw.add_with_viewport(self.dev_list)
 
441
        sw.show()
 
442
 
 
443
        hbox.pack_start(sw, 1,1,1)
 
444
        hbox.pack_start(self.make_side_buttons(), 0,0,0)
 
445
        hbox.show()
 
446
 
 
447
        vbox.pack_start(hbox, 1,1,1)
 
448
        
 
449
        vbox.show()
 
450
        frame.show()
 
451
 
 
452
        return frame
 
453
 
 
454
    def make_network(self):
 
455
        frame = gtk.Frame("Network")
 
456
 
 
457
        vbox = gtk.VBox(False, 2)
 
458
        frame.add(vbox)
 
459
        hbox = gtk.HBox(False, 2)
 
460
 
 
461
 
 
462
        self.net_enabled = gtk.CheckButton("Accept incoming connections")
 
463
        try:
 
464
            accept = self.config.getboolean("settings", "acceptnet")
 
465
        except:
 
466
            accept = True
 
467
 
 
468
        self.net_enabled.set_active(accept)
 
469
        self.net_enabled.show()
 
470
 
 
471
        hbox.pack_start(self.net_enabled, 0,0,0)
 
472
 
 
473
        self.entry_port = gtk.Entry()
 
474
        try:
 
475
            port = self.config.get("settings", "netport")
 
476
        except:
 
477
            port = "9000"
 
478
        
 
479
        self.entry_port.set_text(port)
 
480
        self.entry_port.set_size_request(100, -1)
 
481
        self.entry_port.show()
 
482
        hbox.pack_end(self.entry_port, 0,0,0)
 
483
 
 
484
        lab = gtk.Label("Port:")
 
485
        lab.show()
 
486
        hbox.pack_end(lab, 0,0,0)
 
487
 
 
488
        hbox.show()
 
489
        vbox.pack_start(hbox, 0,0,0)
 
490
 
 
491
        vbox.show()
 
492
        frame.show()
 
493
 
 
494
        return frame
 
495
 
 
496
    def make_bottom_buttons(self):
 
497
        hbox = gtk.HBox(False, 2)
 
498
 
 
499
        self.but_on = gtk.Button("On")
 
500
        self.but_on.set_size_request(75, 30)
 
501
        self.but_on.connect("clicked", self.button_on)
 
502
        self.but_on.show()
 
503
        hbox.pack_start(self.but_on, 0,0,0)
 
504
 
 
505
        self.but_off = gtk.Button("Off")
 
506
        self.but_off.set_size_request(75, 30)
 
507
        self.but_off.connect("clicked", self.button_off)
 
508
        self.but_off.set_sensitive(False)
 
509
        self.but_off.show()
 
510
        hbox.pack_start(self.but_off, 0,0,0)
 
511
 
 
512
        hbox.show()
 
513
 
 
514
        return hbox        
 
515
 
 
516
    def make_id(self):
 
517
        frame = gtk.Frame("Repeater Callsign")
 
518
 
 
519
        hbox = gtk.HBox(False, 2)
 
520
 
 
521
        self.entry_id = gtk.Entry()
 
522
        try:
 
523
            deftxt = self.config.get("settings", "id")
 
524
        except:
 
525
            deftxt = "W1AW"
 
526
 
 
527
        self.entry_id.set_text(deftxt)
 
528
        self.entry_id.set_max_length(8)
 
529
        self.entry_id.show()
 
530
        hbox.pack_start(self.entry_id, 1,1,1)
 
531
 
 
532
        try:
 
533
            idfreq = self.config.get("settings", "idfreq")
 
534
        except:
 
535
            idfreq = "30"
 
536
 
 
537
        self.id_freq = make_choice(["Never", "30", "60", "120"],
 
538
                                   True,
 
539
                                   idfreq)
 
540
        self.id_freq.set_size_request(75, -1)
 
541
        #self.id_freq.show()
 
542
        hbox.pack_start(self.id_freq, 0,0,0)
 
543
 
 
544
        hbox.show()
 
545
        frame.add(hbox)
 
546
        frame.show()
 
547
 
 
548
        return frame
 
549
 
 
550
    def make_auth(self):
 
551
        frame = gtk.Frame("Authentication")
 
552
 
 
553
        hbox = gtk.HBox(False, 20)
 
554
 
 
555
        def toggle_option(cb, option):
 
556
            self.config.set("settings", option, str(cb.get_active()))
 
557
 
 
558
        self.req_auth = gtk.CheckButton("Require Authentication")
 
559
        self.req_auth.connect("toggled", toggle_option, "require_auth")
 
560
        self.req_auth.show()
 
561
        self.req_auth.set_active(self.config.getboolean("settings",
 
562
                                                        "require_auth"))
 
563
        hbox.pack_start(self.req_auth, 0, 0, 0)
 
564
 
 
565
        self.trust_local = gtk.CheckButton("Trust localhost")
 
566
        self.trust_local.connect("toggled", toggle_option, "trust_local")
 
567
        self.trust_local.show()
 
568
        self.trust_local.set_active(self.config.getboolean("settings",
 
569
                                                           "trust_local"))
 
570
        hbox.pack_start(self.trust_local, 0, 0, 0)
 
571
 
 
572
        def do_edit_users(but):
 
573
            p = platform.get_platform()
 
574
            p.open_text_file(p.config_file("users.txt"))
 
575
 
 
576
        edit_users = gtk.Button("Edit Users")
 
577
        edit_users.connect("clicked", do_edit_users)
 
578
        edit_users.show()
 
579
        edit_users.set_size_request(75, 30)
 
580
        hbox.pack_end(edit_users, 0, 0, 0)
 
581
 
 
582
        hbox.show()
 
583
        frame.add(hbox)
 
584
        frame.show()
 
585
        return frame
 
586
 
 
587
    def make_settings(self):
 
588
        vbox = gtk.VBox(False, 5)
 
589
 
 
590
        hbox = gtk.HBox(False, 5)
 
591
 
 
592
        vbox.pack_start(self.make_devices(), 1,1,1)
 
593
        vbox.pack_start(self.make_network(), 0,0,0)
 
594
        vbox.pack_start(self.make_auth(), 0,0,0)
 
595
        vbox.pack_start(self.make_id(), 0,0,0)
 
596
 
 
597
        vbox.pack_start(hbox, 0, 0, 0)
 
598
        hbox.show()
 
599
        vbox.show()
 
600
 
 
601
        self.settings = vbox
 
602
 
 
603
        return vbox
 
604
 
 
605
    def make_connected(self):
 
606
        frame = gtk.Frame("Connected Paths")
 
607
 
 
608
        idlist = miscwidgets.ListWidget([(gobject.TYPE_STRING, "ID")])
 
609
        idlist.show()
 
610
 
 
611
        self.conn_list = gtk.ScrolledWindow()
 
612
        self.conn_list.add_with_viewport(idlist)
 
613
        self.conn_list.show()
 
614
 
 
615
        frame.add(self.conn_list)
 
616
        frame.show()
 
617
 
 
618
        return frame
 
619
 
 
620
    def make_traffic(self):
 
621
        frame = gtk.Frame("Traffic Monitor")
 
622
 
 
623
        self.traffic_buffer = gtk.TextBuffer()
 
624
        self.traffic_view = gtk.TextView(buffer=self.traffic_buffer)
 
625
        self.traffic_view.set_wrap_mode(gtk.WRAP_WORD)
 
626
        self.traffic_view.show()
 
627
 
 
628
        self.traffic_buffer.create_mark("end",
 
629
                                        self.traffic_buffer.get_end_iter(),
 
630
                                        False)
 
631
 
 
632
        sw = gtk.ScrolledWindow()
 
633
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
634
        sw.add(self.traffic_view)
 
635
        sw.show()
 
636
 
 
637
        frame.add(sw)
 
638
        frame.show()
 
639
 
 
640
        return frame
 
641
 
 
642
    def make_monitor(self):
 
643
        vbox = gtk.VBox(False, 5)
 
644
 
 
645
        vbox.pack_start(self.make_connected(), 1,1,1)
 
646
        vbox.pack_start(self.make_traffic(), 1,1,1)
 
647
 
 
648
        vbox.show()
 
649
 
 
650
        return vbox
 
651
 
 
652
    def sync_config(self):
 
653
        id = self.entry_id.get_text()
 
654
        #idfreq = self.id_freq.get_active_text()
 
655
        port = self.entry_port.get_text()
 
656
        acceptnet = str(self.net_enabled.get_active())
 
657
        devices = self.dev_list.get_values()
 
658
        auth = self.req_auth.get_active()
 
659
        local = self.trust_local.get_active()
 
660
 
 
661
        self.config.set("settings", "id", id)
 
662
        #self.config.set("settings", "idfreq", idfreq)
 
663
        self.config.set("settings", "netport", port)
 
664
        self.config.set("settings", "acceptnet", acceptnet)
 
665
        self.config.set("settings", "devices", devices)
 
666
        self.config.set("settings", "require_auth", str(auth))
 
667
        self.config.set("settings", "trust_local", str(local))
 
668
 
 
669
    def button_remove(self, widget):
 
670
        self.dev_list.remove_selected()
 
671
 
 
672
    def button_on(self, widget, data=None):
 
673
        self.tick = 0
 
674
 
 
675
        self.config.set("settings", "state", "True")
 
676
        self.save_config(self.config)
 
677
 
 
678
        self.but_off.set_sensitive(True)
 
679
        self.but_on.set_sensitive(False)
 
680
        self.settings.set_sensitive(False)
 
681
 
 
682
        self.add_outgoing_paths(self.config.get("settings", "id"),
 
683
                                self.dev_list.get_values())
 
684
 
 
685
        try:
 
686
            port = int(self.entry_port.get_text())
 
687
            enabled = self.net_enabled.get_active()
 
688
        except:
 
689
            port = 0
 
690
 
 
691
        if port and enabled:
 
692
            self.repeater.listen_on(port)
 
693
 
 
694
        #self.tap = LoopDataPath("TAP", self.repeater.condition)
 
695
        #self.repeater.paths.append(self.tap)
 
696
 
 
697
        self.repeater.repeat()
 
698
 
 
699
    def button_off(self, widget, user=True):
 
700
        if user:
 
701
            self.config.set("settings", "state", "False")
 
702
            self.save_config(self.config)
 
703
 
 
704
        self.but_off.set_sensitive(False)
 
705
        self.but_on.set_sensitive(True)
 
706
        self.settings.set_sensitive(True)
 
707
 
 
708
        if self.repeater:
 
709
            self.repeater.stop()
 
710
            self.repeater = None
 
711
            self.tap = None
 
712
 
 
713
    def update(self):
 
714
        if self.repeater:
 
715
            paths = self.repeater.paths
 
716
            l = [(x.id,) for x in paths]
 
717
        else:
 
718
            l = []
 
719
 
 
720
        if ("TAP",) in l:
 
721
            l.remove(("TAP",))
 
722
 
 
723
        self.conn_list.child.set_values(l)            
 
724
 
 
725
        if self.tap:
 
726
            traffic = self.tap.peek()
 
727
            end = self.traffic_buffer.get_end_iter()
 
728
            self.traffic_buffer.insert(end, utils.filter_to_ascii(traffic))
 
729
 
 
730
            count = self.traffic_buffer.get_line_count()
 
731
            if count > 200:
 
732
                start = self.traffic_buffer.get_start_iter()
 
733
                limit = self.traffic_buffer.get_iter_at_line(count - 200)
 
734
                self.traffic_buffer.delete(start, limit)
 
735
 
 
736
            endmark = self.traffic_buffer.get_mark("end")
 
737
            self.traffic_view.scroll_to_mark(endmark, 0.0, True, 0, 1)
 
738
        try:
 
739
            limit = int(self.id_freq.get_active_text())
 
740
            if (self.tick / 60) == limit:
 
741
                self.repeater.send_data(None, self.entry_id.get_text())
 
742
                self.tick = 0
 
743
        except:
 
744
            pass
 
745
 
 
746
        self.tick += 1
 
747
 
 
748
        return True
 
749
 
 
750
    def __init__(self):
 
751
        RepeaterUI.__init__(self)
 
752
 
 
753
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
754
        self.window.set_default_size(450, 380)
 
755
        self.window.connect("delete_event", self.ev_delete)
 
756
        self.window.connect("destroy", self.sig_destroy)
 
757
        self.window.set_title("D-RATS Repeater Proxy")
 
758
 
 
759
        vbox = gtk.VBox(False, 5)
 
760
 
 
761
        self.tabs = gtk.Notebook()
 
762
        self.tabs.append_page(self.make_settings(), gtk.Label("Settings"))
 
763
        # FIXME: later
 
764
        # self.tabs.append_page(self.make_monitor(), gtk.Label("Monitor"))
 
765
        self.tabs.show()
 
766
 
 
767
        vbox.pack_start(self.tabs, 1,1,1)
 
768
        vbox.pack_start(self.make_bottom_buttons(), 0,0,0)
 
769
        vbox.show()
 
770
 
 
771
        self.window.add(vbox)
 
772
        self.window.show()
 
773
 
 
774
        #gobject.timeout_add(1000, self.update)
 
775
 
 
776
        try:
 
777
            if self.config.get("settings", "state") == "True":
 
778
                self.button_on(None, None)
 
779
        except Exception, e:
 
780
            print e
 
781
 
 
782
class RepeaterConsole(RepeaterUI):
 
783
    def main(self):
 
784
        devices = eval(self.config.get("settings", "devices"))
 
785
        self.add_outgoing_paths(self.config.get("settings", "id"), devices)
 
786
 
 
787
        try:
 
788
            acceptnet = eval(self.config.get("settings", "acceptnet"))
 
789
            netport = int(self.config.get("settings", "netport"))
 
790
            idfreq = self.config.get("settings", "idfreq")
 
791
            if idfreq == "Never":
 
792
                idfreq = 0
 
793
            else:
 
794
                idfreq = int(idfreq)
 
795
        except Exception, e:
 
796
            print "Failed to parse network info: %s" % e
 
797
            acceptnet = False
 
798
 
 
799
        if acceptnet:
 
800
            self.repeater.listen_on(netport)
 
801
 
 
802
        self.repeater.repeat()
 
803
 
 
804
        while True:
 
805
            try:
 
806
                time.sleep(0.25)
 
807
            except KeyboardInterrupt:
 
808
                self.repeater.stop()
 
809
                break
 
810
       
 
811
 
 
812
if __name__=="__main__":
 
813
    import sys
 
814
 
 
815
 
 
816
    if not opts.debug:
 
817
        p = platform.get_platform()
 
818
        f = file(p.config_file("repeater.log"), "w", 0)
 
819
        if f:
 
820
            sys.stdout = f
 
821
            sys.stderr = f
 
822
        else:
 
823
            print "Failed to open log"
 
824
 
 
825
    if opts.console:
 
826
        r = RepeaterConsole()
 
827
        r.main()
 
828
    else:
 
829
        import gtk
 
830
        import gobject
 
831
        from d_rats.miscwidgets import make_choice
 
832
        from d_rats import miscwidgets
 
833
        from d_rats.config import prompt_for_port
 
834
 
 
835
        gobject.threads_init()
 
836
 
 
837
        g = RepeaterGUI()
 
838
        gtk.main()
 
839