about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUltraQbik <no1skill@yandex.ru>2024-08-29 13:05:49 +0300
committerUltraQbik <no1skill@yandex.ru>2024-08-29 13:05:49 +0300
commit8173c19f6fd5109fd7878091f414eb1b13d07c9e (patch)
treecca343a58f66f44cc9805119cbc2684a20bed91b
parent75e5a8b67975e715ba2ba8d351d3391622a2aefc (diff)
downloadhttpy-8173c19f6fd5109fd7878091f414eb1b13d07c9e.tar.gz
httpy-8173c19f6fd5109fd7878091f414eb1b13d07c9e.zip
Make own timeout
Built-in time out didn't work for some reason
-rw-r--r--main.py56
-rw-r--r--src/config.py7
2 files changed, 42 insertions, 21 deletions
diff --git a/main.py b/main.py
index ff6f5c0..2bd9c9d 100644
--- a/main.py
+++ b/main.py
@@ -21,7 +21,7 @@ _usocket = socket.socket | ssl.SSLSocket
 # logging
 if not os.path.exists(f"{LOGGER_PATH}"):
     os.makedirs(f"{LOGGER_PATH}")
-if os.path.isfile(f"{LOGGER_PATH}/latest.log"):
+if os.path.isfile(f"{LOGGER_PATH}/latest.log") and os.path.getsize(f"{LOGGER_PATH}/latest.log") > 0:
     import gzip
     from datetime import datetime
     with open(f"{LOGGER_PATH}/latest.log", "rb") as file:
@@ -173,7 +173,11 @@ class HTTPServer:
         # Remove self from thread list and close the connection
         self.client_threads.remove(threading.current_thread())
         self.semaphore.release()
-        client.close()
+
+        try:
+            client.close()
+        except (ssl.SSLError, OSError):
+            pass
 
     def _client_request_handler(self, client: _usocket, request: Request):
         """
@@ -224,7 +228,8 @@ class HTTPServer:
 
         buffer = bytearray()
         size = 0
-        while not self.stop_event.is_set():
+        timer = SOCKET_TIMER
+        while not self.stop_event.is_set() and timer > 0:
             try:
                 buffer += client.recv(BUFFER_LENGTH)
                 if buffer[-4:] == b'\r\n\r\n':
@@ -235,7 +240,10 @@ class HTTPServer:
                     break
                 size = len(buffer)
             except (ssl.SSLWantReadError, BlockingIOError):
-                time.sleep(0.005)
+                time.sleep(SOCKET_ACK_INTERVAL)
+            except (ssl.SSLError, OSError):
+                break
+            timer -= 1
         return None
 
     def _send_response(self, client: _usocket, response: Response) -> None:
@@ -243,10 +251,6 @@ class HTTPServer:
         Send response to client
         """
 
-        # make blocking socket
-        blk = client.getblocking()
-        client.setblocking(True)
-
         # append connection status headers
         response.headers["Connection"] = "close"
 
@@ -257,17 +261,28 @@ class HTTPServer:
         message += b'\r\n'
 
         # send message
-        client.sendall(message)
+        is_first = True
         for packet in response.get_data_stream():
-            try:
-                client.sendall(packet)
-            except (ssl.SSLError, OSError):
-                break
-            if self.stop_event.is_set():
-                break
-
-        # return to previous state
-        client.setblocking(blk)
+            timer = SOCKET_TIMER
+            while timer > 0:
+                try:
+                    # doesn't work with 'else' or if no 'print(is_first)' is present
+                    # I have no clue as to why
+                    if is_first:
+                        client.sendall(message)
+                        is_first = False
+                    if not is_first:
+                        client.sendall(packet)
+                        break
+                except (ssl.SSLWantWriteError, BlockingIOError):
+                    pass
+                except (ssl.SSLError, OSError):
+                    return
+                time.sleep(SOCKET_ACK_INTERVAL)
+                timer -= 1
+                print(timer)
+            if self.stop_event.is_set() or timer <= 0:
+                return
 
     def _accept(self) -> _usocket | None:
         """
@@ -278,10 +293,9 @@ class HTTPServer:
             try:
                 if len(self.client_threads) < CLIENT_MAX_AMOUNT:
                     return self.sock.accept()[0]
-            except (ssl.SSLError, OSError):
+            except (ssl.SSLError, OSError, BlockingIOError):
                 pass
-            except BlockingIOError:
-                time.sleep(0.005)
+            time.sleep(SOCKET_ACK_INTERVAL)
         return None
 
     def fetch_file_headers(self, path: str) -> dict[str, Any] | None:
diff --git a/src/config.py b/src/config.py
index 077c9cc..2f9d4b0 100644
--- a/src/config.py
+++ b/src/config.py
@@ -2,9 +2,16 @@
 LOGGER_PATH = "logs"
 BUFFER_LENGTH = 2**16           # 64 KiB
 BUFFER_MAX_SIZE = 2**30 * 0.5   # 512 MiB
+
+# threading
 CLIENT_MAX_AMOUNT = 2**15       # max requests at once, after which the connections are dropped
 CLIENT_MAX_PROCESS = 64         # max processing threads at once
 
+# sockets
+SOCKET_TIMEOUT = 10.0
+SOCKET_ACK_INTERVAL = 0.005
+SOCKET_TIMER = SOCKET_TIMEOUT / SOCKET_ACK_INTERVAL
+
 # API
 API_FILE_RANDOM_MIN_SIZE_LIMIT = 1              # 1 byte
 API_FILE_RANDOM_MAX_SIZE_LIMIT = 2**30 * 5      # 5 GiB