implement client-to-server read timeout PINGs
This commit is contained in:
parent
f33a0ad369
commit
ba57d06a56
3 changed files with 22 additions and 1 deletions
|
@ -76,6 +76,7 @@ class IServer(Server):
|
||||||
disconnected: bool
|
disconnected: bool
|
||||||
params: ConnectionParams
|
params: ConnectionParams
|
||||||
desired_caps: Set[ICapability]
|
desired_caps: Set[ICapability]
|
||||||
|
last_read: float
|
||||||
|
|
||||||
def send_raw(self, line: str, priority=SendPriority.DEFAULT
|
def send_raw(self, line: str, priority=SendPriority.DEFAULT
|
||||||
) -> Awaitable[SentLine]:
|
) -> Awaitable[SentLine]:
|
||||||
|
|
|
@ -2,8 +2,10 @@ import asyncio
|
||||||
from asyncio import Future, PriorityQueue
|
from asyncio import Future, PriorityQueue
|
||||||
from typing import Awaitable, Deque, Dict, List, Optional, Set, Tuple
|
from typing import Awaitable, Deque, Dict, List, Optional, Set, Tuple
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from time import monotonic
|
||||||
|
|
||||||
from asyncio_throttle import Throttler
|
from asyncio_throttle import Throttler
|
||||||
|
from async_timeout import timeout
|
||||||
from ircstates import Emit, Channel
|
from ircstates import Emit, Channel
|
||||||
from ircstates.numerics import *
|
from ircstates.numerics import *
|
||||||
from ircstates.server import ServerDisconnectedException
|
from ircstates.server import ServerDisconnectedException
|
||||||
|
@ -23,6 +25,7 @@ from .interface import ITCPTransport, ITCPReader, ITCPWriter
|
||||||
|
|
||||||
THROTTLE_RATE = 4 # lines
|
THROTTLE_RATE = 4 # lines
|
||||||
THROTTLE_TIME = 2 # seconds
|
THROTTLE_TIME = 2 # seconds
|
||||||
|
PING_TIMEOUT = 60 # seconds
|
||||||
|
|
||||||
class Server(IServer):
|
class Server(IServer):
|
||||||
_reader: ITCPReader
|
_reader: ITCPReader
|
||||||
|
@ -39,6 +42,8 @@ class Server(IServer):
|
||||||
rate_limit=100, period=THROTTLE_TIME)
|
rate_limit=100, period=THROTTLE_TIME)
|
||||||
|
|
||||||
self.sasl_state = SASLResult.NONE
|
self.sasl_state = SASLResult.NONE
|
||||||
|
self.last_read = -1.0
|
||||||
|
self._ping_sent = False
|
||||||
|
|
||||||
self._sent_count: int = 0
|
self._sent_count: int = 0
|
||||||
self._write_queue: PriorityQueue[SentLine] = PriorityQueue()
|
self._write_queue: PriorityQueue[SentLine] = PriorityQueue()
|
||||||
|
@ -174,7 +179,21 @@ class Server(IServer):
|
||||||
both = self._read_queue.popleft()
|
both = self._read_queue.popleft()
|
||||||
else:
|
else:
|
||||||
while True:
|
while True:
|
||||||
data = await self._reader.read(1024)
|
|
||||||
|
try:
|
||||||
|
async with timeout(PING_TIMEOUT):
|
||||||
|
data = await self._reader.read(1024)
|
||||||
|
except asyncio.exceptions.TimeoutError:
|
||||||
|
if self._ping_sent:
|
||||||
|
data = b"" # empty data means the socket disconnected
|
||||||
|
else:
|
||||||
|
self._ping_sent = True
|
||||||
|
await self.send(build("PING", ["hello"]))
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.last_read = monotonic()
|
||||||
|
self._ping_sent = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lines = self.recv(data)
|
lines = self.recv(data)
|
||||||
except ServerDisconnectedException:
|
except ServerDisconnectedException:
|
||||||
|
|
|
@ -3,3 +3,4 @@ asyncio-throttle ==1.0.1
|
||||||
dataclasses ==0.6
|
dataclasses ==0.6
|
||||||
ircstates ==0.9.6
|
ircstates ==0.9.6
|
||||||
async_stagger ==0.3.0
|
async_stagger ==0.3.0
|
||||||
|
async_timeout ==3.0.1
|
||||||
|
|
Loading…
Reference in a new issue