net.py: typo fix + catch the right exception
[breadcrumb.git] / code / breadcrumb / server / net.py
blob95046b73c465f584bbb58283977320b49574a738
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.decode_crumb(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 (calling the clean_up method)...')
64 self.handler.clean_up()
65 except AttributeError:
66 logging.error('... but the handler has no cleanup method!')
67 logging.error('Does it inherit from BaseHandler properly?')
68 except NotImplementedError:
69 logging.debug("... but the handler didn't implement it.")
71 class BreadcrumbTCPServer(BreadcrumbServer, Protocol):
72 """A TCP server for the breadcrumb protocol."""
73 def __init__(self, handler = None):
74 BreadcrumbServer.__init__(self, handler)
76 def dataReceived(self, crumb):
77 """Handles a new crumb, received over TCP."""
78 self.new_crumb(crumb)
80 class BreadcrumbUDPServer(BreadcrumbServer, DatagramProtocol):
81 """A UDP server for the breadcrumb protocol."""
82 def __init__(self, handler = None):
83 BreadcrumbServer.__init__(self, handler)
84 logging.debug("New BreadcrumbUDPServer instance created.")
86 def datagramReceived(self, crumb, (host, port)):
87 """Handles a new crumb, received over UDP."""
88 logging.debug("received something from %s:%d" % (host, port))
89 self.new_crumb(crumb)
91 def start_server(port = None, handler = None, encap = 'UDP', **kwargs):
92 """Runs the Breadcrumb server.
94 The server argument is either the server proper (for UDP servers) or the
95 relevant factory (for TCP and derived protocols).
96 """
97 logging.info("Booting the Breadcrumb server (version %s)" % consts.VERSION)
98 logging.debug("Server started at %s." % time.ctime())
100 try:
101 port = int(port)
102 except ValueError:
103 logging.error("Got noninteger port %s, can't start server..." % port)
104 raise RuntimeError, 'Bad port: %s' % port
106 encap = encap.upper()
107 if encap == 'TCP':
108 server = BreadcrumbTCPServer(handler = handler)
110 factory = Factory()
111 factory.protocol = server
113 if port is None:
114 port = consts.DEFAULT_TCP_PORT
116 logging.debug("Prepared TCP reactor on port %d" % port)
117 reactor.listenTCP(port, factory)
119 elif encap == 'UDP':
120 server = BreadcrumbUDPServer(handler = handler)
122 if port is None:
123 port = consts.DEFAULT_UDP_PORT
125 logging.debug("Prepared UDP reactor on port %d" % port)
126 reactor.listenUDP(port, server)
128 else:
129 raise RuntimeError, 'Unknown encapsulation %s' % encap
131 reactor.run()