Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # module ws_utils.py
- # Joshua Marshall Moore
- # 7/14/2010
- def getHeaderValue(request, header):
- """ Returns the value of a header specified header field. """
- delim = ': '
- start = request.index(header.strip() + ': ')
- end = request.index('\r\n', start)
- return request[start+len(header)+len(delim):end]
- def handshake(s):
- request = s.recv(1024)
- print 'Request: \n', request, 'END\n'
- # skip: 1. If the user agent already has a websocket connection to the remote host (IP address) identified by host even if known by another name, wait until that connection has been established or for that connection to have failed.
- # 2. establish the following information
- # hostname or ip address of the websocket server, as it is to be addressed by clients.
- host = ' localhost'
- # the port number on which the server expected and/or received the connection
- port = 8888
- # an identifier for hte service provided by the server. if the server provides multiple services, then the value should be derived from the resource name given in hte client's handshake
- resource_name = ''
- # true if the connection is encrypted or if the server expected it to be encrypted; false otherwise
- secure_flag = False
- # the asci serialization of the origin that the server is willing to communicate with, converted to ascii lowercase.
- origin = getHeaderValue(request, "Origin").lower()
- # either null, or a string representing the subprotocol the server is ready to use. if the server supports multipe subprotocls then the value should be derived from the client's handshake, specifically from the "Sec-WebSocket-Protocol" field. The absence of such a field is equivalent to the null value. The empty string is not the same as the null value for these purposes
- subprotocol = 'null'
- # the value of the "Sec-WebSocket_Key1" field in the client's handshake
- key_1 = getHeaderValue(request, 'Sec-WebSocket-Key1')
- # the value of the "Sec-WebSocket-Key2" field in the client's handshake
- key_2 = getHeaderValue(request, 'Sec-WebSocket-Key2')
- # the eight random bytes sent after the first 0x0D 0x0A 0x0D 0x0A sequence in the client's handshake
- key_3 = request[-8:]
- # 3. Let location be the string that results from construct a websocket URL from host, port resource name and secure flag
- location = "ws://localhost:8888/"
- # 4. Let key-number_1 be the digits in key1 be the digits in key_1, interpreted as a base ten integer ignoring all other characters in key1
- keynumber_1 = ""
- for char in key_1:
- if char.isdigit():
- keynumber_1 += char
- keynumber_1 = int(keynumber_1)
- # similar for key-number_2
- keynumber_2 = ""
- for char in key_2:
- if char.isdigit():
- keynumber_2 += char
- keynumber_2 = int(keynumber_2)
- # Let spaces_1 be the number of SPACE characters in key1
- spaces_1 = 0
- for char in key_1:
- if char is ' ':
- spaces_1 += 1
- # 5. Let spaces_2 be the number of SPACE characters in key2
- spaces_2 = 0
- for char in key_2:
- if char is ' ':
- spaces_2 += 1
- # If either spaces_1 or spaces_2 is zero, then abort the WebSocket connection. This is a symptom of a cross-protocol attak
- if not spaces_1 or not spaces_2:
- s.close()
- return False
- # 6. if key-number_1 is not an integral multiple of spaces_1 then abort the websocket connection
- if keynumber_1 % spaces_1 or keynumber_2 % spaces_2:
- s.close
- return False
- # 7. Let part one bw key-number_1 divided by spaces_1
- part_1 = keynumber_1 / spaces_1
- part_2 = keynumber_2 / spaces_2
- # 8. Let challenge be the concatenation of part_1, expressed as a big-endian 32bit integer, part_2, expressed as a big endian 32bit integer and the eight bytes of key3 in the order they were sent on the wire
- index_key1 = request.index("Sec-WebSocket-Key1: ")
- index_key2 = request.index("Sec-WebSocket-Key2: ")
- challenge = ''
- if index_key1 < index_key2:
- challenge = str(part_1) + str(part_2) + key_3
- else:
- challenge = str(part_2) + str(part_1) + key_3
- # 9. Let response be the md5 fingerprint of challenge as a big-endian 128 bit string
- response = md5.new(challenge).digest()
- serverHandshake = ''
- # 10. Send the following line, termined by CRLF and encoded as UTF-8 to the client:
- # s.send(u"HTTP/1.1 101 WebSocket Protocol Handshake")
- serverHandshake += "HTTP/1.1 101 WebSocket Protocol Handshake"
- # 11. Send the following line to the client. each field must be sent as a line consisting of the field name, which must be an ASCII case insensitive match for the field name in the list below, followoed by a COLON and a SPACE character, followed by the field value as specified in the list below, followed by CRLF. The lines must be encoded as UTF-8
- # s.send(u"Upgrade: Websocket\r\n")
- # s.send(u"Sec-WebSocket-Location: %s\r\n" % location)
- # s.send(u"Sec-WebSocket-Origin: %s\r\n" % origin)
- # s.send(u"Sec-WebSocket-Protocol: %s" % subprotocol)
- serverHandshake += "Upgrade: WebSocket\r\n"
- serverHandshake += "Sec-WebSocket-Location: %s\r\n" % location
- serverHandshake += "Sec-WebSocket-Origin: %s\r\n" % origin
- serverHandshake += "Sec-WebSocket-Protocol: %s\r\n" % subprotocol
- # 12. send CRLF
- # s.send(u"\r\n")
- serverHandshake += "\r\n"
- # 13. send response
- # s.send(response)
- serverHandshake += response
- unicodeString = unicode(serverHandshake, "utf-8")
- s.send(unicodeString)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement