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