1 """ 2 websocket - WebSocket client library for Python 3 4 Copyright (C) 2010 Hiroki Ohtani(liris) 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1335 USA 20 21 """ 22 import socket 23 24 import six 25 26 from ._exceptions import * 27 from ._ssl_compat import * 28 from ._utils import * 29 30 DEFAULT_SOCKET_OPTION = [(socket.SOL_TCP, socket.TCP_NODELAY, 1)] 31 if hasattr(socket, "SO_KEEPALIVE"): 32 DEFAULT_SOCKET_OPTION.append((socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)) 33 if hasattr(socket, "TCP_KEEPIDLE"): 34 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPIDLE, 30)) 35 if hasattr(socket, "TCP_KEEPINTVL"): 36 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPINTVL, 10)) 37 if hasattr(socket, "TCP_KEEPCNT"): 38 DEFAULT_SOCKET_OPTION.append((socket.SOL_TCP, socket.TCP_KEEPCNT, 3)) 39 40 _default_timeout = None 41 42 __all__ = ["DEFAULT_SOCKET_OPTION", "sock_opt", "setdefaulttimeout", "getdefaulttimeout", 43 "recv", "recv_line", "send"] 44 45 46 class sock_opt(object): 47 48 def __init__(self, sockopt, sslopt): 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 56 57 58 def setdefaulttimeout(timeout): 59 """ 60 Set the global timeout setting to connect. 61 62 timeout: default socket timeout time. This value is second. 63 """ 64 global _default_timeout 65 _default_timeout = timeout 66 67 68 def getdefaulttimeout(): 69 """ 70 Return the global timeout setting(second) to connect. 71 """ 72 return _default_timeout 73 74 75 def recv(sock, bufsize): 76 if not sock: 77 raise WebSocketConnectionClosedException("socket is already closed.") 78 79 try: 80 bytes_ = sock.recv(bufsize) 81 except socket.timeout as e: 82 message = extract_err_message(e) 83 raise WebSocketTimeoutException(message) 84 except SSLError as e: 85 message = extract_err_message(e) 86 if message == "The read operation timed out": 87 raise WebSocketTimeoutException(message) 88 else: 89 raise 90 91 if not bytes_: 92 raise WebSocketConnectionClosedException( 93 "Connection is already closed.") 94 95 return bytes_ 96 97 98 def recv_line(sock): 99 line = [] 100 while True: 101 c = recv(sock, 1) 102 line.append(c) 103 if c == six.b("\n"): 104 break 105 return six.b("").join(line) 106 107 108 def send(sock, data): 109 if isinstance(data, six.text_type): 110 data = data.encode('utf-8') 111 112 if not sock: 113 raise WebSocketConnectionClosedException("socket is already closed.") 114 115 try: 116 return sock.send(data) 117 except socket.timeout as e: 118 message = extract_err_message(e) 119 raise WebSocketTimeoutException(message) 120 except Exception as e: 121 message = extract_err_message(e) 122 if isinstance(message, str) and "timed out" in message: 123 raise WebSocketTimeoutException(message) 124 else: 125 raise 126