def hasReceivedPing(self, timeout=1.0):
        """
		Waits to receive "ping" event until the end of the timeout.
		
		@param timeout: time to wait response in second (default=1s)
		@type timeout: float
		
		@return: an event matching with the template or None otherwise
		@rtype: templatemessage
		"""
        TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(),
                                     timeout=timeout)

        tpl_rsp = TestTemplatesLib.TemplateMessage()

        if self.cfg['agent-support']:
            layer_agent = TestTemplatesLib.TemplateLayer('AGENT')
            layer_agent.addKey(name='name', data=self.cfg['agent']['name'])
            layer_agent.addKey(name='type', data=self.cfg['agent']['type'])
            tpl_rsp.addLayer(layer_agent)

        tpl_rsp.addLayer(AdapterIP.ip(more=AdapterIP.received()))
        tpl_rsp.addLayer(AdapterTCP.tcp(more=AdapterTCP.received()))
        if self.cfg['ssl-support']:
            tpl_rsp.addLayer(AdapterSSL.ssl(more=AdapterSSL.received()))
        tpl_rsp.addLayer(
            templates.ws(opcode=codec.WEBSOCKET_OPCODE_PING,
                         more=templates.received()))
        return self.received(expected=tpl_rsp, timeout=timeout)
    def isHandshakeSuccessful(self, timeout=1.0):
        """
		Wait to receive "handshake successful" event until the end of the timeout.
		
		@param timeout: time to wait response in second (default=1s)
		@type timeout: float
		
		@return: an event matching with the template or None otherwise
		@rtype: templatemessage
		"""
        TestAdapterLib.check_timeout(caller=TestAdapterLib.caller(),
                                     timeout=timeout)

        tpl_rsp = TestTemplatesLib.TemplateMessage()

        if self.cfg['agent-support']:
            layer_agent = TestTemplatesLib.TemplateLayer('AGENT')
            layer_agent.addKey(name='name', data=self.cfg['agent']['name'])
            layer_agent.addKey(name='type', data=self.cfg['agent']['type'])
            tpl_rsp.addLayer(layer_agent)

        tpl_rsp.addLayer(AdapterIP.ip(more=AdapterIP.received()))
        tpl_rsp.addLayer(AdapterTCP.tcp(more=AdapterTCP.received()))
        if self.cfg['ssl-support']:
            tpl_rsp.addLayer(AdapterSSL.ssl(more=AdapterSSL.received()))
        tpl_rsp.addLayer(AdapterHTTP.response())
        tpl_rsp.addLayer(templates.ws(more=templates.handshake_ok()))
        return self.received(expected=tpl_rsp, timeout=timeout)
    def sendBinary(self, data):
        """
		Send binary data
		
		@param data: data to send
		@type data: string
		"""
        if not self.wsHanshakeSuccess:
            return

        # make chunk
        chunks = [
            data[x:x + self.wsMaxPayloadSize]
            for x in xrange(0, len(data), self.wsMaxPayloadSize)
        ]

        # encode data in the websocket packet and enqueue it
        for chunk in chunks:
            ws_tpl = templates.ws(fin=1,
                                  mask=0,
                                  rsv1=0,
                                  rsv2=0,
                                  rsv3=0,
                                  opcode=codec.WEBSOCKET_OPCODE_BINARY,
                                  data=chunk,
                                  data_length=len(chunk),
                                  more=templates.sent())
            wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl)

            # Send websocket data
            try:
                lower = self.ADP_HTTP.tcp().sendData(data=wsdata)
            except Exception as e:
                #raise Exception("send request: tcp failed: %s" % str(e))
                raise TestAdapterLib.AdapterException(
                    TestAdapterLib.caller(),
                    "send request: tcp failed: %s" % str(e))

            lower.addLayer(ws_tpl)

            # Log event
            if self.logEventSent:
                lower.addRaw(raw=wsdata)
                self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_BINARY_STR,
                                  tplEvt=lower)
    def sendRaw(self,
                opcode=0,
                fin=1,
                mask=0,
                rsv1=0,
                rsv2=0,
                rsv3=0,
                data=''):
        """
		Send raw data
		"""
        if not self.wsHanshakeSuccess:
            return

        ws_tpl = templates.ws(fin=fin,
                              mask=mask,
                              rsv1=rsv1,
                              rsv2=rsv2,
                              rsv3=rsv3,
                              opcode=opcode,
                              data=data,
                              data_length=len(data),
                              more=templates.sent())
        wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl)

        # Send websocket data
        try:
            lower = self.ADP_HTTP.tcp().sendData(data=wsdata)
        except Exception as e:
            #raise Exception("send request: tcp failed: %s" % str(e))
            raise TestAdapterLib.AdapterException(
                TestAdapterLib.caller(),
                "send request: tcp failed: %s" % str(e))

        lower.addLayer(ws_tpl)

        # Log event
        if self.logEventSent:
            lower.addRaw(raw=wsdata)
            self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_TEXT_STR,
                              tplEvt=lower)
    def sendPong(self, data=None):
        """
		Send pong 
		
		@param data: data included on the pong (default=None)
		@type data: string
		"""
        if data is None:
            dataLength = 0
        else:
            dataLength = len(data)

        ws_tpl = templates.ws(fin=1,
                              mask=0,
                              rsv1=0,
                              rsv2=0,
                              rsv3=0,
                              opcode=codec.WEBSOCKET_OPCODE_PONG,
                              data=data,
                              data_length=dataLength,
                              more=templates.sent())
        wsdata = self.wsCodec.encodeWsData(tpl=ws_tpl)

        # Send websocket data
        try:
            lower = self.ADP_HTTP.tcp().sendData(data=wsdata)
        except Exception as e:
            #raise Exception("send request: tcp failed: %s" % str(e))
            raise TestAdapterLib.AdapterException(
                TestAdapterLib.caller(),
                "send request: tcp failed: %s" % str(e))

        lower.addLayer(ws_tpl)

        # Log event
        if self.logEventSent:
            lower.addRaw(raw=wsdata)
            self.logSentEvent(shortEvt=codec.WEBSOCKET_OPCODE_PONG_STR,
                              tplEvt=lower)
    def handshake(self, resource, origin):
        """
		Do hanshake
		"""
        self.wsHanshakeSuccess = False
        self.wsKey = self.wsCodec.createSecWsKey()

        req = ["GET %s HTTP/1.1" % resource]
        req.append("Upgrade: websocket")
        req.append("Connection: keep-alive, upgrade")
        req.append("Host: %s" % self.cfg['dest-ip'])
        req.append("Origin: http://%s" % origin)
        req.append("Sec-WebSocket-Key: %s" % self.wsKey)
        req.append("Sec-WebSocket-Version: %s" % codec.WEBSOCKET_VERSION)
        req.append("")

        req_tpl = self.ADP_HTTP.constructTemplateRequest(rawHttp=req)
        lower_tpl = self.ADP_HTTP.sendRequest(tpl=req_tpl)
        if self.logEventSent:
            tpl = templates.ws(more=templates.handshake())
            lower_tpl.addLayer(tpl)
            self.logSentEvent(shortEvt='Handshake', tplEvt=lower_tpl)
    def handleIncomingHttpResponse(self, data, lower):
        """
		On http response
		"""
        http_rsp = lower.get('HTTP', 'response')
        http_hdrs = lower.get('HTTP', 'headers')
        http_code = http_rsp.get('code')

        if str(http_code) != '101':
            if self.logEventReceived:
                tpl = templates.ws(more=templates.handshake_error(
                    details="bad http response: %s" % http_code))
                lower.addLayer(tpl)
                self.logRecvEvent(shortEvt='Handshake Error', tplEvt=lower)
            else:
                self.error('hanshake failed bad http response: %s' % http_code)
        else:
            # decode specific ws headers
            hdrUpgrade = False
            hdrConnection = False
            wsAccept = False
            try:
                for k, v in http_hdrs.getItems():
                    if k.lower().strip() == 'upgrade' and v.lower().strip(
                    ) == 'websocket':
                        hdrUpgrade = True
                    if k.lower().strip() == 'connection' and v.lower().strip(
                    ) == 'upgrade':
                        hdrConnection = True
                    if k.lower().strip() == 'sec-websocket-accept':
                        v = v.lower().strip()
                        # rfc6455 1.3. Opening Handshake
                        value = (self.wsKey + codec.GUID).encode('utf-8')
                        sha1 = sha1_constructor()
                        sha1.update(value)
                        hashed = base64.encodestring(
                            sha1.digest()).strip().lower()
                        if hashed == v:
                            wsAccept = True
                        else:
                            if self.logEventReceived:
                                tpl = templates.ws(
                                    more=templates.handshake_error(
                                        details=
                                        "key incorrect computed=%s received=%s key=%s"
                                        % (hashed, v, self.wsKey)))
                                lower.addLayer(tpl)
                                self.logRecvEvent(shortEvt='Handshake Error',
                                                  tplEvt=lower)
                            else:
                                self.error(
                                    'web socket key incorrect computed=%s received=%s key=%s'
                                    % (hashed, v, self.wsKey))
            except Exception as e:
                self.error('unable to check websocket headers: %s' % e)
            else:
                if hdrUpgrade and hdrConnection and wsAccept:
                    self.wsHanshakeSuccess = True
                    if self.logEventReceived:
                        tpl = templates.ws(more=templates.handshake_ok())
                        lower.addLayer(tpl)
                        self.logRecvEvent(shortEvt='Handshake OK',
                                          tplEvt=lower)
                    else:
                        self.info('handshake ok')
                    self.ADP_HTTP.activeWebsocket()
                else:
                    if self.logEventReceived:
                        tpl = templates.ws(more=templates.handshake_error())
                        lower.addLayer(tpl)
                        self.logRecvEvent(shortEvt='Handshake Error',
                                          tplEvt=lower)
                    else:
                        self.error('hanshake failed')
示例#8
0
    def decodeWsData(self, buffer):
        """
		Decode ws message

		@param buffer: buffer
		@type buffer: string
		"""
        tpl = None
        payload = ''
        opcode = None
        left = ''
        needMore = False
        try:
            try:
                hdrs_len = 2
                # B = 1 octet
                # H = 2 octets
                # I = 4 octets
                fixed_hdr = struct.unpack('!2B', buffer[:hdrs_len])
                remaining = buffer[hdrs_len:]
            except struct.error as e:
                left = buffer  # need more data
                needMore = True
                self.debug("ws need more data in header")
            else:

                fin = fixed_hdr[0] >> 7 & 1
                rsv1 = fixed_hdr[0] >> 6 & 1
                rsv2 = fixed_hdr[0] >> 5 & 1
                rsv3 = fixed_hdr[0] >> 4 & 1
                opcode = fixed_hdr[0] & 0xf

                has_mask = fixed_hdr[1] >> 7 & 1
                length = fixed_hdr[1] & 0x7f
                self.debug("ws header: %s, %s, %s, %s, %s, %s, %s" %
                           (fin, rsv1, rsv2, rsv3, opcode, has_mask, length))

                if length == 126:
                    try:
                        hdrs_extended_len = 2
                        size = buffer[hdrs_len:hdrs_len + hdrs_extended_len]
                        ext_lenght_hdr = struct.unpack(
                            '!H',
                            buffer[hdrs_len:hdrs_len + hdrs_extended_len])
                    except struct.error as e:
                        left = buffer  # need more data
                        needMore = True
                        self.debug("ws need more data in data")
                    else:
                        length_ext = ext_lenght_hdr[0]
                        self.debug("ws lenght extended: %s" % length_ext)
                        if fin:
                            if len(
                                    buffer
                            ) < hdrs_len + hdrs_extended_len + length_ext:
                                self.debug(
                                    "data extended, need more data (%s/%s)" %
                                    (len(buffer), length_ext))
                                left = buffer  # need more data
                                needMore = True
                            else:
                                payload = buffer[hdrs_len +
                                                 hdrs_extended_len:hdrs_len +
                                                 hdrs_extended_len +
                                                 length_ext]
                                left = buffer[hdrs_len + hdrs_extended_len +
                                              length_ext:]
                        else:
                            left = buffer  # need more data
                            needMore = True
                else:
                    if fin:
                        if len(buffer) < hdrs_len + length:
                            self.debug(
                                "fin=1 but insufficient data in buffer, need more (%s/%s)"
                                % (len(buffer), length))
                            left = buffer  # need mode data
                            needMore = True
                        else:
                            payload = buffer[hdrs_len:hdrs_len + length]
                            left = buffer[hdrs_len + length:]
                    else:
                        self.debug("ws need more data fin=0")
                        left = buffer  # need mode data
                        needMore = True
                if not needMore:
                    self.debug('decode complete')
                    tpl = templates.ws(fin=fin,
                                       mask=has_mask,
                                       rsv1=rsv1,
                                       rsv2=rsv2,
                                       rsv3=rsv3,
                                       opcode=opcode,
                                       data=payload,
                                       data_length=len(payload),
                                       more=templates.received())
                    tpl.addRaw(buffer)
        except Exception as e:
            self.error('unable to decode ws data: %s' % e)
        return (payload, left, needMore, tpl)