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
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
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
)
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...
63 logging
.info('Cleaning up...')
64 self
.handler
.cleanup()
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."""
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
))
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).
94 logging
.info("Booting the Breadcrumb server (version %s)" % consts
.VERSION
)
95 logging
.debug("Server started at %s." % time
.ctime())
100 logging
.error("Got noninteger port %s, can't start server..." % port
)
101 raise RuntimeError, 'Bad port: %s' % port
103 encap
= encap
.upper()
105 server
= BreadcrumbTCPServer(handler
= handler
)
108 factory
.protocol
= server
111 port
= consts
.DEFAULT_TCP_PORT
113 logging
.debug("Prepared TCP reactor on port %d" % port
)
114 reactor
.listenTCP(port
, factory
)
117 server
= BreadcrumbUDPServer(handler
= handler
)
120 port
= consts
.DEFAULT_UDP_PORT
122 logging
.debug("Prepared UDP reactor on port %d" % port
)
123 reactor
.listenUDP(port
, server
)
127 raise NotImplementedError, 'SSH protocol server not implemented.'
129 raise RuntimeError, 'Unknown encapsulation %s' % encap