Skip to content

Commit 96a5a85

Browse files
committed
Add deny_new_connections and allow_new_connections
1 parent 531624a commit 96a5a85

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ The WebsocketServer can be initialized with the below parameters.
8181
| `send_message_to_all()` | Sends a `message` to **all** connected clients. The message is a simple string. | message | None |
8282
| `disconnect_clients_gracefully()` | Disconnect all connected clients by sending a websocket CLOSE handshake. | Optional: status, reason | None |
8383
| `disconnect_clients_abruptly()` | Disconnect all connected clients. Clients won't be aware until they try to send some data. | None | None |
84-
| `shutdown_gracefully()` | Disconnect clients with a CLOSE handshake and shutdown server. | Optional: status, reason | None |
85-
| `shutdown_abruptly()` | Disconnect clients and shutdown server with no handshake. | None | None |
86-
84+
| `shutdown_gracefully()` | Disconnect clients with a CLOSE handshake and shutdown server. | Optional: status, reason | None |
85+
| `shutdown_abruptly()` | Disconnect clients and shutdown server with no handshake. | None | None |
86+
| `deny_new_connections()` | Close connection for new clients. | Optional: status, reason | None |
87+
| `allow_new_connections()` | Allows back connection for new clients. | | None |
8788

8889

8990
### Callback functions

tests/test_server.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,19 @@ def test_disconnect_clients_gracefully(self, session):
141141
for i in range(3):
142142
client.send("test")
143143
sleep(0.2)
144+
145+
def test_deny_new_connections(self, threaded_server):
146+
url = "ws://{}:{}".format(*threaded_server.server_address)
147+
server = threaded_server
148+
server.deny_new_connections(status=1013, reason=b"Please try re-connecting later")
149+
150+
conn = websocket.create_connection(url)
151+
try:
152+
conn.send("test")
153+
except websocket.WebSocketProtocolException as e:
154+
assert 'Invalid close opcode' in e.args[0]
155+
assert not server.clients
156+
157+
server.allow_new_connections()
158+
conn = websocket.create_connection(url)
159+
conn.send("test")

websocket_server/websocket_server.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ def send_message(self, client, msg):
8080
def send_message_to_all(self, msg):
8181
self._multicast(msg)
8282

83+
def deny_new_connections(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON):
84+
self._deny_new_connections(status, reason)
85+
86+
def allow_new_connections(self):
87+
self._allow_new_connections()
88+
8389
def shutdown_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON):
8490
self._shutdown_gracefully(status, reason)
8591

@@ -131,6 +137,8 @@ def __init__(self, host='127.0.0.1', port=0, loglevel=logging.WARNING, key=None,
131137
self.id_counter = 0
132138
self.thread = None
133139

140+
self._deny_clients = False
141+
134142
def _run_forever(self, threaded):
135143
cls_name = self.__class__.__name__
136144
try:
@@ -161,6 +169,13 @@ def _pong_received_(self, handler, msg):
161169
pass
162170

163171
def _new_client_(self, handler):
172+
if self._deny_clients:
173+
status = self._deny_clients["status"]
174+
reason = self._deny_clients["reason"]
175+
handler.send_close(status, reason)
176+
self._terminate_client_handler(handler)
177+
return
178+
164179
self.id_counter += 1
165180
client = {
166181
'id': self.id_counter,
@@ -188,14 +203,17 @@ def handler_to_client(self, handler):
188203
if client['handler'] == handler:
189204
return client
190205

206+
def _terminate_client_handler(self, handler):
207+
handler.keep_alive = False
208+
handler.finish()
209+
handler.connection.close()
210+
191211
def _terminate_client_handlers(self):
192212
"""
193213
Ensures request handler for each client is terminated correctly
194214
"""
195215
for client in self.clients:
196-
client["handler"].keep_alive = False
197-
client["handler"].finish()
198-
client["handler"].connection.close()
216+
self._terminate_client_handler(client["handler"])
199217

200218
def _shutdown_gracefully(self, status=CLOSE_STATUS_NORMAL, reason=DEFAULT_CLOSE_REASON):
201219
"""
@@ -229,6 +247,15 @@ def _disconnect_clients_abruptly(self):
229247
"""
230248
self._terminate_client_handlers()
231249

250+
def _deny_new_connections(self, status, reason):
251+
self._deny_clients = {
252+
"status": status,
253+
"reason": reason,
254+
}
255+
256+
def _allow_new_connections(self):
257+
self._deny_clients = False
258+
232259

233260
class WebSocketHandler(StreamRequestHandler):
234261

0 commit comments

Comments
 (0)