Skip to content

Commit

Permalink
Make sure TCP connections end gracefully
Browse files Browse the repository at this point in the history
TCP connections establish sessions, and expect graceful shut downs (FIN
packet). Make sure on connection close, this packet gets sent.
  • Loading branch information
ItsDrike committed Jun 8, 2023
1 parent 744f06c commit bb81bf2
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 0 deletions.
10 changes: 10 additions & 0 deletions mcproto/connection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import asyncio
import errno
import socket
from abc import ABC, abstractmethod
from typing import Generic, Optional, TypeVar
Expand Down Expand Up @@ -160,6 +161,14 @@ def write(self, data: bytes) -> None:

def _close(self) -> None:
"""Close the underlying connection."""
# Gracefully end the connection first (shutdown), informing the other side
# we're disconnecting, and waiting for them to disconnect cleanly (TCP FIN)
try:
self.socket.shutdown(socket.SHUT_RDWR)
except OSError as exc:
if exc.errno != errno.ENOTCONN:
raise

self.socket.close()


Expand Down Expand Up @@ -218,6 +227,7 @@ async def write(self, data: bytes) -> None:

async def _close(self) -> None:
"""Close the underlying connection."""
# Close automatically performs a graceful TCP connection shutdown too
self.writer.close()

@property
Expand Down
3 changes: 3 additions & 0 deletions tests/mcproto/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def recv(self, length: int) -> bytearray:
def close(self) -> None:
self._closed = True

def shutdown(self, __how: int, /) -> None:
pass


class MockStreamWriter(CustomMockMixin, MagicMock):
spec_set = asyncio.StreamWriter
Expand Down

0 comments on commit bb81bf2

Please # to comment.