/usr/share/pyshared/bjsonrpc/server.py is in python-bjsonrpc 0.2.0-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | """
bjson/server.py
Asynchronous Bidirectional JSON-RPC protocol implementation over TCP/IP
Copyright (c) 2010 David Martinez Marti
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of copyright holders nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
"""
import socket, select
from bjsonrpc.connection import Connection
from bjsonrpc.exceptions import EofError
class Server(object):
"""
Handles a listening socket and automatically accepts incoming
connections. It will create a *bjsonrpc.connection.Connection* for
each socket connected to it.
Use the *Server.serve()* method to start accepting connections.
Parameters:
**lstsck**
Listening socket to watch for incoming connections. Must be an instance
of *socket.socket* or something compatible, and must to be already
listening for new connections in the desired port.
**handler_factory**
Class (object type) to instantiate to publish methods for incoming
connections. Should be an inherited class of *bjsonrpc.handlers.BaseHandler*
"""
def __init__(self, lstsck, handler_factory):
self._lstsck = lstsck
self._handler = handler_factory
self._debug_socket = False
self._debug_dispatch = False
self._serve = True
def stop(self):
self._serve = False
def debug_socket(self, value = None):
"""
Sets or retrieves the internal debug_socket value.
When is set to true, each new connection will have it set to true,
and every data sent or received by the socket will be printed to
stdout.
By default is set to *False*
"""
retval = self._debug_socket
if type(value) is bool:
self._debug_socket = value
return retval
def debug_dispatch(self, value = None):
"""
Sets or retrieves the internal debug_dispatch value.
When is set to true, each new connection will have it set to true,
and every error produced by client connections will be printed to
stdout.
By default is set to *False*
"""
ret = self._debug_dispatch
if type(value) is bool:
self._debug_dispatch = value
return ret
def serve(self):
"""
Starts the forever-serving loop. This function only exits when an
Exception is raised inside, by unexpected error, KeyboardInterrput,
etc.
It is coded using *select.select* function, and it is capable to
serve to an unlimited amount of connections at same time
without using threading.
"""
try:
sockets = []
connections = []
connidx = {}
while self._serve:
ready_to_read = select.select(
[self._lstsck]+sockets, # read
[], [], # write, errors
1 # timeout
)[0]
if not ready_to_read:
continue
if self._lstsck in ready_to_read:
clientsck, clientaddr = self._lstsck.accept()
sockets.append(clientsck)
conn = Connection(
sck = clientsck, address = clientaddr,
handler_factory = self._handler
)
connidx[clientsck.fileno()] = conn
conn._debug_socket = self._debug_socket
conn._debug_dispatch = self._debug_socket
# conn.internal_error_callback = self.
connections.append(conn)
for sck in ready_to_read:
fileno = sck.fileno()
if fileno not in connidx:
continue
conn = connidx[fileno]
try:
conn.dispatch_until_empty()
except EofError:
conn.close()
sockets.remove(conn.socket)
connections.remove(conn)
#print "Closing client conn."
finally:
for conn in connections:
conn.close()
self._lstsck.shutdown(socket.SHUT_RDWR)
self._lstsck.close()
|