def _handle_termination_packet(session, resp_t):
    """
    the ccd server might sent MTH_TERMINATE packets which indicate, that
    a plugin is finshed. if such a packet is received, close the
    corresponding window. these packets can be sent at anytime by the ccd
    and do not depend on any request

    input:
        session session affected by that packet
        resp_t  response tuple representing the servers response packet

    """

    try:
        rid = resp_t[2]
    except IndexError as e:
        # this actually can not happen, because we set a default value for rid
        # ... but whatever
        logger.exception(e)
        raise errors.InvalidServerResponse(
            message="No rid in terminate response", response=resp_t)

    try:
        win_state = resp_t[-1]["code"]
    except (IndexError, KeyError) as e:
        logger.exception(e)
        raise errors.InvalidServerResponse(
            message="No state in terminate response payload", response=resp_t)

    #win = window.get_win_by_rid(session, rid)
    win = session.get_win_by_rid(rid)
    win.set_state(win_state)
def _get_request_id(session):
    """ asks the ccd for a request id and returns it """
    resp_t = sendpacket(session,
                        op=ccdlib.OP_GETRID,
                        pld=dict(rid=DEFAULT_RID))[-1]
    if not "rid" in resp_t:
        raise errors.InvalidServerResponse(message="No rid found in payload.", response=resp_t)
    return resp_t["rid"]
def _handle_output_packet(session, resp_t):
    """
    the ccd server might sent MTH_OUTPUT packets that indicate packet
    containing a plugin's stdout. if such a packet is received, forward the
    corresponding output to the window.

    input:
        session session affected by that packet
        resp_t  response tuple representing the servers response packet

    """
    try:
        rid = resp_t[2]
    except (IndexError) as e:
        # this actually can not happen, because we set a default value for rid
        # ... but whatever
        logger.exception(e)
        raise errors.InvalidServerResponse(message="No rid or state in terminate response", response=resp_t)

    #win = window.get_win_by_rid(session, rid)
    win = session.get_win_by_rid(rid)
    win._write_to_output(resp_t)
def wait_for_response(session, request, maxfail=5):
    sock = session.sock
    response = None  # hold response packet on success
    req_str = ccdlib.pkt2str(request)
    tries = 0
    while not response:
        if tries >= maxfail:
            raise errors.InvalidServerResponse(
                message='Abadoning request after %d pkts' % tries,
                request=request,
                response=response)

        logger.debug("waiting for response on %s", req_str)
        # yes we do want this to block
        # if you want to be sure, that this function returns, use select
        # beforhand (like so in window.py)
        resp_t = ccdlib.recv(sock)
        res_str = ccdlib.pkt2str(resp_t)
        logger.debug("received response while waiting on %s: %s", req_str,
                     res_str)

        # check whether the incoming packet is ours, if so handle it
        # correspondingly
        if ccdlib.checkRsp(request, resp_t):
            logger.debug("validated response successfully %s", res_str)
            succ = resp_t[0]

            try:
                msg = resp_t[-1]
            except:
                pass
            if not msg and isinstance(request[-1], dict):
                msg = ', '.join(
                    ['%s: %s' % (k, str(v)) for k, v in request[-1].items()])

            if succ == ccdlib.OP_PERMISSION_DENIED:
                raise errors.PermissionDenied(message=msg,
                                              request=request,
                                              response=resp_t)

            elif succ == ccdlib.OP_NOT_FOUND:
                raise errors.NotFoundError(message=msg,
                                           request=request,
                                           response=resp_t)

            elif succ == ccdlib.OP_INVALID_INPUT:
                raise errors.InputError(message=msg,
                                        request=request,
                                        response=resp_t)

            elif succ == ccdlib.OP_ALREADY_EXISTS:
                raise errors.AlreadyExistingError(message=msg,
                                                  request=request,
                                                  response=resp_t)

            elif not succ == ccdlib.OP_SUCCESS:
                raise errors.InvalidServerResponse(message=msg,
                                                   request=request,
                                                   response=resp_t)

            response = resp_t

        # the packet is not ours. is it a termination packet, update the
        # corresponding window and continue waiting for our response
        #elif resp_t[0] == ccdlib.OP_SUCCESS and resp_t[6] == ccdlib.MTH_TERMINATE:
        # better do further checking later, is more accurate that way
        elif resp_t[6] == ccdlib.MTH_TERMINATE:
            logger.debug(
                "processing answer that failed to validate, but seems "
                "to be a MTH_TERMINATE")
            try:
                _handle_termination_packet(session, resp_t)
            except errors.ClientError as e:
                logger.warning(e)
            continue

        # the packet is not ours, but a plugin's stdout packet. update the
        # corresponding window and continue waiting for our response
        #elif resp_t[0] == ccdlib.OP_SUCCESS and resp_t[6] == ccdlib.MTH_OUTPUT:
        # better do further checking later, is more accurate that way
        elif resp_t[6] == ccdlib.MTH_OUTPUT:
            logger.debug("processing answer that failed to validate, but it "
                         "seems to be a MTH_OUTPUT")
            try:
                _handle_output_packet(session, resp_t)
            except errors.ClientError as e:
                logger.warning(e)
            continue

        # we received a packet, that is not ours and somewhat corrupted
        else:
            raise errors.InvalidServerResponse(message='Orphaned packet',
                                               request=request,
                                               response=response)

    return response