Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/websocket/_socket.py: 47%
107 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:34 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:34 +0000
1import errno
2import selectors
3import socket
5from typing import Union
7from ._exceptions import *
8from ._ssl_compat import *
9from ._utils import *
11"""
12_socket.py
13websocket - WebSocket client library for Python
15Copyright 2023 engn33r
17Licensed under the Apache License, Version 2.0 (the "License");
18you may not use this file except in compliance with the License.
19You may obtain a copy of the License at
21 http://www.apache.org/licenses/LICENSE-2.0
23Unless required by applicable law or agreed to in writing, software
24distributed under the License is distributed on an "AS IS" BASIS,
25WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26See the License for the specific language governing permissions and
27limitations under the License.
28"""
30DEFAULT_SOCKET_OPTION = [(socket.SOL_TCP, socket.TCP_NODELAY, 1)]
31if hasattr(socket, "SO_KEEPALIVE"):
32 DEFAULT_SOCKET_OPTION.append((socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1))
33if hasattr(socket, "TCP_KEEPIDLE"):
34 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPIDLE, 30))
35if hasattr(socket, "TCP_KEEPINTVL"):
36 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPINTVL, 10))
37if hasattr(socket, "TCP_KEEPCNT"):
38 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPCNT, 3))
40_default_timeout = None
42__all__ = ["DEFAULT_SOCKET_OPTION", "sock_opt", "setdefaulttimeout", "getdefaulttimeout",
43 "recv", "recv_line", "send"]
46class sock_opt:
48 def __init__(self, sockopt: list, sslopt: dict) -> None:
49 if sockopt is None:
50 sockopt = []
51 if sslopt is None:
52 sslopt = {}
53 self.sockopt = sockopt
54 self.sslopt = sslopt
55 self.timeout = None
58def setdefaulttimeout(timeout: Union[int, float, None]) -> None:
59 """
60 Set the global timeout setting to connect.
62 Parameters
63 ----------
64 timeout: int or float
65 default socket timeout time (in seconds)
66 """
67 global _default_timeout
68 _default_timeout = timeout
71def getdefaulttimeout() -> Union[int, float, None]:
72 """
73 Get default timeout
75 Returns
76 ----------
77 _default_timeout: int or float
78 Return the global timeout setting (in seconds) to connect.
79 """
80 return _default_timeout
83def recv(sock: socket.socket, bufsize: int) -> bytes:
84 if not sock:
85 raise WebSocketConnectionClosedException("socket is already closed.")
87 def _recv():
88 try:
89 return sock.recv(bufsize)
90 except SSLWantReadError:
91 pass
92 except socket.error as exc:
93 error_code = extract_error_code(exc)
94 if error_code != errno.EAGAIN and error_code != errno.EWOULDBLOCK:
95 raise
97 sel = selectors.DefaultSelector()
98 sel.register(sock, selectors.EVENT_READ)
100 r = sel.select(sock.gettimeout())
101 sel.close()
103 if r:
104 return sock.recv(bufsize)
106 try:
107 if sock.gettimeout() == 0:
108 bytes_ = sock.recv(bufsize)
109 else:
110 bytes_ = _recv()
111 except TimeoutError:
112 raise WebSocketTimeoutException("Connection timed out")
113 except socket.timeout as e:
114 message = extract_err_message(e)
115 raise WebSocketTimeoutException(message)
116 except SSLError as e:
117 message = extract_err_message(e)
118 if isinstance(message, str) and 'timed out' in message:
119 raise WebSocketTimeoutException(message)
120 else:
121 raise
123 if not bytes_:
124 raise WebSocketConnectionClosedException(
125 "Connection to remote host was lost.")
127 return bytes_
130def recv_line(sock: socket.socket) -> bytes:
131 line = []
132 while True:
133 c = recv(sock, 1)
134 line.append(c)
135 if c == b'\n':
136 break
137 return b''.join(line)
140def send(sock: socket.socket, data: Union[bytes, str]) -> int:
141 if isinstance(data, str):
142 data = data.encode('utf-8')
144 if not sock:
145 raise WebSocketConnectionClosedException("socket is already closed.")
147 def _send():
148 try:
149 return sock.send(data)
150 except SSLWantWriteError:
151 pass
152 except socket.error as exc:
153 error_code = extract_error_code(exc)
154 if error_code is None:
155 raise
156 if error_code != errno.EAGAIN and error_code != errno.EWOULDBLOCK:
157 raise
159 sel = selectors.DefaultSelector()
160 sel.register(sock, selectors.EVENT_WRITE)
162 w = sel.select(sock.gettimeout())
163 sel.close()
165 if w:
166 return sock.send(data)
168 try:
169 if sock.gettimeout() == 0:
170 return sock.send(data)
171 else:
172 return _send()
173 except socket.timeout as e:
174 message = extract_err_message(e)
175 raise WebSocketTimeoutException(message)
176 except Exception as e:
177 message = extract_err_message(e)
178 if isinstance(message, str) and "timed out" in message:
179 raise WebSocketTimeoutException(message)
180 else:
181 raise