OBPRequestSpectrumExchange::OBPRequestSpectrumExchange() {
    OBPMessage message;
    vector<byte> *stream;
    unsigned int i;

    this->hints->push_back(new OBPSpectrumHint());

    this->direction = Transfer::TO_DEVICE;

    message.setMessageType(OBPMessageTypes::OBP_GET_SPECTRUM_NOW);
    stream = message.toByteStream();

    this->length = (unsigned) stream->size();
    this->buffer->resize(stream->size());

    for(i = 0; i < stream->size(); i++) {
        (*(this->buffer))[i] = (*stream)[i];
    }
    delete stream;

    checkBufferSize();
}
vector<byte> *OBPTransaction::queryDevice(TransferHelper *helper,
                    unsigned int messageType,
                    vector<byte> &data) throw (ProtocolException) {
    int flag = 0;
    vector<byte> *bytes = NULL;
    vector<byte> *fullVector = NULL;
    OBPMessage *message = new OBPMessage();
    OBPMessage *response = NULL;

    message->setMessageType(messageType);

    /* Need a copy of the input data that can be given to the message. */
    /* Note: copy will be deleted by message when appropriate. */
    message->setData(new vector<byte>(data));

    try {
        bytes = message->toByteStream();
        flag = helper->send(*bytes, (unsigned) bytes->size());
        if(((unsigned int)flag) != bytes->size()) {
            /* FIXME: retry, throw exception, something here */
        }
    } catch (BusException &be) {
        if(NULL != bytes) {
            delete bytes;
        }
        delete message;
        string error("Failed to write to bus.");
        /* FIXME: previous exception should probably be bundled up into the new exception */
        /* FIXME: there is probably a more descriptive type for this than ProtocolException */
        throw ProtocolException(error);
    }

    delete message;
    delete bytes;
    bytes = NULL;

    try {
        /* Read the 64-byte OBP header.  This may indicate that more data
         * must be absorbed afterwards.
         */
        bytes = new vector<byte>(64);
        flag = helper->receive(*bytes, (unsigned) bytes->size());
        if(((unsigned int)flag) != bytes->size()) {
            /* FIXME: retry, throw exception, something here */
        }

        /* Parse out the header and see if there is an extended payload. */
        try {
            response = OBPMessage::parseHeaderFromByteStream(bytes);
        } catch (IllegalArgumentException &iae) {
            response = NULL;
        }
        if(NULL == response || true == response->isNackFlagSet()
                || response->getMessageType() != messageType) {
            if(NULL != bytes) {
                delete bytes;
            }

            if(NULL != response) {
                delete response;
            }
            /* There may be a legitimate reason to not return a message
             * (e.g. tried to read an unprogrammed value).  Just return
             * NULL here instead of throwing an exception and let the
             * caller figure it out.
             */
            return NULL;
        }
        unsigned int bytesToRead = response->getBytesRemaining() - 20; /* omit footer and checksum */
        if(bytesToRead > 0) {
            fullVector = new vector<byte>(bytesToRead + bytes->size());
            /* Safely stl::copy() the header into a full-sized block and
             * delete the existing buffer
             */
            vector<byte>::iterator iter = copy(bytes->begin(), bytes->end(), fullVector->begin());
            delete bytes;
            bytes = NULL;
            /* TransferHelper expects a vector, so create a new one for it */
            vector<byte> *remainder = new vector<byte>(bytesToRead);
            flag = helper->receive(*remainder, (unsigned) remainder->size());
            if(((unsigned int)flag) != bytesToRead) {
                /* FIXME: retry, throw exception, something here */
            }
            copy(remainder->begin(), remainder->end(), iter);
            delete remainder;
        } else {
            fullVector = bytes;
            bytes = NULL;  /* To prevent double deletion */
        }
        /* Delete and recreate response using the full message */
        delete response;
        try {
            response = OBPMessage::parseByteStream(fullVector);
        } catch (IllegalArgumentException &iae) {
            response = NULL;
        }
        delete fullVector;
        fullVector = NULL;
    } catch (BusException &be) {
        if(NULL != bytes) {
            delete bytes;
        }
        if(NULL != fullVector) {
            delete fullVector;
        }
        string error("Failed to read from bus.");
        /* FIXME: previous exception should probably be bundled up into the new exception */
        /* FIXME: there is probably a more descriptive type for this than ProtocolException */
        throw ProtocolException(error);
    }
    if(NULL == response) {
        /* This could happen if the footer or checksum failed for
         * some reason, but that would be very unusual.  This can only happen
         * if the header was already verified, but there was some error in the
         * rest of the payload.
         */
        string error("Failed to parse extended message");
        throw ProtocolException(error);
    }

    /* Make a copy of the response buffer so response can be deleted */
    bytes = new vector<byte>(*response->getData());
    delete response;
    return bytes;
}
bool OBPTransaction::sendCommandToDevice(TransferHelper *helper,
                    unsigned int messageType,
                    vector<byte> &data) throw (ProtocolException) {

    bool retval = false;
    int flag = 0;
    vector<byte> *bytes = NULL;
    OBPMessage *message = new OBPMessage();
    OBPMessage *response = NULL;

    message->setMessageType(messageType);
    message->setAckRequestedFlag();

    /* Need a copy of the input data that can be given to the message. */
    /* Note: copy will be deleted by message when appropriate. */
    message->setData(new vector<byte>(data));

    try {
        bytes = message->toByteStream();
        flag = helper->send(*bytes, (unsigned) bytes->size());
        if(((unsigned int)flag) != bytes->size()) {
            /* FIXME: retry, throw exception, something here */
        }
    } catch (BusException &be) {
        if(NULL != bytes) {
            delete bytes;
        }
        delete message;
        string error("Failed to write to bus.");
        /* FIXME: previous exception should probably be bundled up into the new exception */
        /* FIXME: there is probably a more descriptive type for this than ProtocolException */
        throw ProtocolException(error);
    }

    delete message;
    delete bytes;
    bytes = NULL;

    try {
        /* Read the 64-byte OBP header. */
        bytes = new vector<byte>(64);
        flag = helper->receive(*bytes, (unsigned) bytes->size());
        if(((unsigned int)flag) != bytes->size()) {
            /* FIXME: retry, throw exception, something here */
        }

        /* Parse out the header. */
        try {
            response = OBPMessage::parseHeaderFromByteStream(bytes);
        } catch (IllegalArgumentException &iae) {
            response = NULL;
        }
    } catch (BusException &be) {
        if(NULL != bytes) {
            delete bytes;
        }
        string error("Failed to read from bus.");
        /* FIXME: previous exception should probably be bundled up into the new exception */
        /* FIXME: there is probably a more descriptive type for this than ProtocolException */
        throw ProtocolException(error);
    }

    delete bytes;

    if(NULL == response || true == response->isNackFlagSet()
            || response->getMessageType() != messageType) {
        retval = false;
    } else if(true == response->isAckFlagSet()) {
        retval = true;
    } else {
        delete response;
        string error("Illegal device response");
        throw ProtocolException(error);
    }
    delete response;
    return retval;
}