More PEP8 compliance
[breadcrumb.git] / code / breadcrumb / server / net.py
blobe61e61a3570bce2713a08e1686fbaa677566b350
1 #-*- coding: utf8 -*-
2 """Network code for the Breadcrumb server."""
4 # Copyright (C) 2008 Laurens Van Houtven <lvh at laurensvh.be>
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.
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.
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/>.
18 from twisted.internet import reactor
19 from twisted.internet.protocol import DatagramProtocol # UDP
20 from twisted.internet.protocol import Protocol, Factory # TCP
22 import os
23 import sys
24 import time
25 import atexit
26 import logging
27 import decoding
29 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
30 import common.consts as consts
32 class BreadcrumbServer:
33 """A superclass for Breadcrumb servers."""
34 def __init__(self, handler = None):
35 self.handler = handler
36 atexit.register(self.clean_up)
38 self.keepdatapoints = False
39 self.datapoints = []
41 def new_crumb(self, packed):
42 """Unpacks a new crumb, checks it, and passes it to the handler."""
44 logging.debug('Got a new crumb, sending to decoder...')
45 point = decoding.decodecrumb(packed)
47 if self.keepdatapoints:
48 self.datapoints.append(point)
50 if 'handlerid' in point and 'handlermsg' in point:
51 id, msg = point['handlerid'], point['handlermsg']
52 self.handler.newmessage(id, msg)
54 self.handler.newpoint(point)
56 def clean_up(self):
57 """Cleans up before closing.
59 This tells the handler that we're about to shut down, so it has a
60 chance to close connections, finalize files...
61 """
62 try:
63 logging.info('Cleaning up...')
64 self.handler.cleanup()
65 except NameError:
66 logging.info('... but the handler has no cleanup method.')
68 class BreadcrumbTCPServer(BreadcrumbServer, Protocol):
69 """A TCP server for the breadcrumb protocol."""
70 def __init__(self, handler = None):
71 BreadcrumbServer.__init__(self, handler)
73 def dataReceived(self, crumb):
74 """Handles a new crumb, received over TCP."""
75 self.new_crumb(crumb)
77 class BreadcrumbUDPServer(BreadcrumbServer, DatagramProtocol):
78 """A UDP server for the breadcrumb protocol."""
79 def __init__(self, handler = None):
80 BreadcrumbServer.__init__(self, handler)
81 logging.debug("New BreadcrumbUDPServer instance created.")
83 def datagramReceived(self, crumb, (host, port)):
84 """Handles a new crumb, received over UDP."""
85 logging.debug("received something from %s:%d" % (host, port))
86 self.new_crumb(crumb)
88 def start_server(port = None, handler = None, encap = 'UDP'):
89 """Runs the Breadcrumb server.
91 The server argument is either the server proper (for UDP servers) or the
92 relevant factory (for TCP and derived protocols).
93 """
94 logging.info("Booting the Breadcrumb server (version %s)" % consts.VERSION)
95 logging.debug("Server started at %s." % time.ctime())
97 try:
98 port = int(port)
99 except ValueError:
100 logging.error("Got noninteger port %s, can't start server..." % port)
101 raise RuntimeError, 'Bad port: %s' % port
103 encap = encap.upper()
104 if encap == 'TCP':
105 server = BreadcrumbTCPServer(handler = handler)
107 factory = Factory()
108 factory.protocol = server
110 if port is None:
111 port = consts.DEFAULT_TCP_PORT
113 logging.debug("Prepared TCP reactor on port %d" % port)
114 reactor.listenTCP(port, factory)
116 elif encap == 'UDP':
117 server = BreadcrumbUDPServer(handler = handler)
119 if port is None:
120 port = consts.DEFAULT_UDP_PORT
122 logging.debug("Prepared UDP reactor on port %d" % port)
123 reactor.listenUDP(port, server)
125 elif encap == 'SSH':
126 # TODO: Implement
127 raise NotImplementedError, 'SSH protocol server not implemented.'
128 else:
129 raise RuntimeError, 'Unknown encapsulation %s' % encap
131 reactor.run()