root/src/add-ons/kernel/network/ppp/modem/ACFCHandler.cpp
/*
 * Copyright 2003-2004, Waldemar Kornewald <wkornew@gmx.net>
 * Distributed under the terms of the MIT License.
 */

#include "ACFCHandler.h"

#include <KPPPConfigurePacket.h>


static const uint8 kACFCType = 0x8;


ACFCHandler::ACFCHandler(uint32 options, KPPPInterface& interface)
        : KPPPOptionHandler("ACFC Handler", kACFCType, interface, NULL),
        fOptions(options),
        fLocalState(ACFC_DISABLED),
        fPeerState(ACFC_DISABLED)
{
}


status_t
ACFCHandler::AddToRequest(KPPPConfigurePacket& request)
{
        // is ACFC not requested or was it rejected?
        if (fLocalState == ACFC_REJECTED
                        || (Options() & REQUEST_ACFC) == 0)
                return B_OK;

        // add ACFC request
        ppp_configure_item item;
        item.type = kACFCType;
        item.length = 2;
        return request.AddItem(&item) ? B_OK : B_ERROR;
}


status_t
ACFCHandler::ParseNak(const KPPPConfigurePacket& nak)
{
        // naks do not contain ACFC items
        if (nak.ItemWithType(kACFCType))
                return B_ERROR;

        return B_OK;
}


status_t
ACFCHandler::ParseReject(const KPPPConfigurePacket& reject)
{
        if (reject.ItemWithType(kACFCType)) {
                fLocalState = ACFC_REJECTED;

                if (Options() & FORCE_ACFC_REQUEST)
                        return B_ERROR;
        }

        return B_OK;
}


status_t
ACFCHandler::ParseAck(const KPPPConfigurePacket& ack)
{
        if (ack.ItemWithType(kACFCType))
                fLocalState = ACFC_ACCEPTED;
        else {
                fLocalState = ACFC_DISABLED;

                if (Options() & FORCE_ACFC_REQUEST)
                        return B_ERROR;
        }

        return B_OK;
}


status_t
ACFCHandler::ParseRequest(const KPPPConfigurePacket& request,
        int32 index, KPPPConfigurePacket& nak, KPPPConfigurePacket& reject)
{
        if (!request.ItemWithType(kACFCType))
                return B_OK;

        if ((Options() & ALLOW_ACFC) == 0) {
                ppp_configure_item item;
                item.type = kACFCType;
                item.length = 2;
                return reject.AddItem(&item) ? B_OK : B_ERROR;
        }

        return B_OK;
}


status_t
ACFCHandler::SendingAck(const KPPPConfigurePacket& ack)
{
        ppp_configure_item *item = ack.ItemWithType(kACFCType);

        if (item && (Options() & ALLOW_ACFC) == 0)
                return B_ERROR;

        if (item)
                fPeerState = ACFC_ACCEPTED;
        else
                fPeerState = ACFC_DISABLED;

        return B_OK;
}


void
ACFCHandler::Reset()
{
        fLocalState = fPeerState = ACFC_DISABLED;
}