def __init__(self):
     MessageIdentifyProtocol.__init__(self,True,True,True)
     self._wsFrame=WSFrame()
     self._wsStartFrame=WSFrame()
     self._msgLen=0
     self._uri=b""
 def sendWSFrame(self,payload):
     self.rawSend(WSFrame.generateResponseFrame(payload))
class WebSocketHandler(MessageIdentifyProtocol):


    def __init__(self):
        MessageIdentifyProtocol.__init__(self,True,True,True)
        self._wsFrame=WSFrame()
        self._wsStartFrame=WSFrame()
        self._msgLen=0
        self._uri=b""

        
    

    def _recvHeader(self,bytes):
        '''
           @return: a tuple with 2 bytestrings and 1 boolean (headerPart,messagePart,headerSend)
           headerPart are bytes that are part of the header
           messagePart are bytes that are part of a message
           headerSend is True, if the header is complete
           
        '''
        
        self._wsFrame.setBytes(bytes)
         
        
        try:
            pStartIndex = self._wsFrame.getPayloadStartIndex()
            header=bytes[:pStartIndex]
            rest = bytes[pStartIndex:]
            self._wsFrame.getMaskKey()
            self._msgLen=self._wsFrame.getPayloadLen()
            return (header,rest,True)    
        except FrameHeaderIncomplete:
            return (bytes,b"",False)
        

    def sendWSFrame(self,payload):
        self.rawSend(WSFrame.generateResponseFrame(payload))
        
    
    def _recvMessage(self,bytes):
        '''
           @return: a tuple with 2 bytestring and one boolean (c_message,o_messages,cmDone)
           c_message are bytes that are part of the current message
           o_message are bytes that are part of other messages
           cmDone is True if the current message is complete
        '''
        
        pl=self._wsFrame.getPayloadLen()
        
        return (bytes[:pl],bytes[pl:],len(bytes)>=pl)
        

    
    def _recvHandshake(self,bytes):
        '''
           @return: a tuple with 2 bytestrings and 1 boolean (handshakePart,restPart,handshake complete)    
        '''
        httpHeaderSeparatorPosition = bytes.find(b"\r\n\r\n")
        if httpHeaderSeparatorPosition == -1:
            return (bytes,b"",False)
        else:
            return (bytes[:httpHeaderSeparatorPosition],bytes[httpHeaderSeparatorPosition+4:],True)
        
  
    
    def aMessage(self,message):
        pass
        
    def aHeader(self,header):
        
        pass

    
        
    def aHandshake(self,handshake):
        try:
            headerLines=handshake.rsplit(b"\r\n")
            
            if not headerLines[0].startswith(b"GET /"):
                self.resetState()
                self.doDisconnect()
                return
            
            
            
            if b"\n" in headerLines[0]: #malformed request, prevent evil Header manipulations 
                self.resetState()
                self.doDisconnect()
                return
            
            end=headerLines[0].rfind(b" ")
            self.uri = headerLines[0][5:end]
            
            handshakeDict = {}
            for kv in headerLines:
                dbl=kv.find(b":")
                if dbl>0:
                    handshakeDict[kv[:dbl]]=kv[dbl+1:].lstrip()
    
            self.requestHeader=handshakeDict        
            if not handshakeDict[b"Sec-WebSocket-Version"]==b"13":
                self.resetState()
                self.doDisconnect()
                
            self.handshakeSuccessful(self.generateResponseHeader(handshakeDict),handshakeDict[b'Sec-WebSocket-Protocol'])
        except Exception as e:
            #self.errorMessage(b"unable to establish a socket tunnel")
            #print("error on establishing connection: ",e)
            self.resetState()
            self.doDisconnect()
            #raise e
    
    def handshakeSuccessful(self,respHeader,protocol):
        self.rawSend(respHeader)
            
    
    def generateResponseHeader(self,header):
        def generateAcceptChallenge(secWebSocketKey):
            hash = hashlib.sha1()
            hash.update(secWebSocketKey+b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
            hash = hash.digest() 
            ret=base64.b64encode(hash)
            return ret
        
        resp=b"HTTP/1.1 101 Switching Protocols\r\n"
        resp=b"".join([resp,b"Upgrade: websocket\r\n"])
        resp=b"".join([resp,b"Connection: Upgrade\r\n"])
        resp=b"".join([resp,b"Sec-WebSocket-Accept: "+generateAcceptChallenge(header[b'Sec-WebSocket-Key'])+b"\r\n\r\n"])
        
        return resp