- set close frame

This commit is contained in:
liris
2012-01-16 10:03:51 +09:00
parent 0e4f658534
commit aedebb7ebc

View File

@@ -32,6 +32,20 @@ import logging
VERSION = 13 VERSION = 13
STATUS_NORMAL = 1000
STATUS_GOING_AWAY = 1001
STATUS_PROTOCOL_ERROR = 1002
STATUS_UNSUPPORTED_DATA_TYPE = 1003
STATUS_STATUS_NOT_AVAILABLE = 1005
STATUS_ABNORMAL_CLOSED = 1006
STATUS_INVALID_PAYLOAD = 1007
STATUS_POLICY_VIOLATION = 1008
STATUS_MESSAGE_TOO_BIG = 1009
STATUS_INVALID_EXTENSION = 1010
STATUS_UNEXPECT_CONDITION = 1011
STATUS_TLS_HANDSHAKE_ERROR = 1015
logger = logging.getLogger() logger = logging.getLogger()
class WebSocketException(Exception): class WebSocketException(Exception):
@@ -190,6 +204,7 @@ class ABNF(object):
def create_frame(data, opcode): def create_frame(data, opcode):
if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode): if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
data = data.encode("utf-8") data = data.encode("utf-8")
# mask must be set if send data from client
return ABNF(1, 0, 0, 0, opcode, 1, data) return ABNF(1, 0, 0, 0, opcode, 1, data)
def format(self): def format(self):
@@ -405,17 +420,25 @@ class WebSocket(object):
""" """
Receive utf-8 string data from the server. Receive utf-8 string data from the server.
""" """
opcode, data = self.recv_data()
return data
def recv_data(self):
while True: while True:
frame = self.recv_frame() frame = self.recv_frame()
if frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY): if frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY):
return frame.data return (frame.opcode, frame.data)
elif frame.opcode == ABNF.OPCODE_CLOSE: elif frame.opcode == ABNF.OPCODE_CLOSE:
self.send_close()
return None return None
elif frame.opcode == ABNF.OPCODE_PING: elif frame.opcode == ABNF.OPCODE_PING:
self.pong("Hi!") self.pong("Hi!")
def recv_frame(self): def recv_frame(self):
header_bytes = self._recv(2) header_bytes = self._recv(2)
if not header_bytes:
return None
b1 = ord(header_bytes[0]) b1 = ord(header_bytes[0])
fin = b1 >> 7 & 1 fin = b1 >> 7 & 1
rsv1 = b1 >> 6 & 1 rsv1 = b1 >> 6 & 1
@@ -443,20 +466,30 @@ class WebSocket(object):
frame = ABNF(fin, rsv1, rsv2, rsv3, opcode, mask, data) frame = ABNF(fin, rsv1, rsv2, rsv3, opcode, mask, data)
return frame return frame
def send_close(self, status = STATUS_NORMAL, reason = ""):
if status < 0 or status > ABNF.LENGTH_16:
raise ValueError("code is invalid range")
self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
def close(self):
def close(self, status = STATUS_NORMAL, reason = ""):
""" """
Close Websocket object Close Websocket object
""" """
if self.connected: if self.connected:
if status < 0 or status > ABNF.LENGTH_16:
raise ValueError("code is invalid range")
try: try:
self.send("bye", ABNF.OPCODE_CLOSE) self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
timeout = self.sock.gettimeout() timeout = self.sock.gettimeout()
self.sock.settimeout(1) self.sock.settimeout(3)
try: try:
result = self._recv(2) frame = self.recv_frame()
if result != "\xff\x00": print repr(frame.data)
logger.error("bad closing Handshake") if logger.isEnabledFor(logging.DEBUG):
logger.error("close status: " + repr(frame.data))
except: except:
pass pass
self.sock.settimeout(timeout) self.sock.settimeout(timeout)