sdkcreationmw/sdkruntimes/wsock/src/WinsockInterface.cpp
author rajpuroh
Mon, 08 Mar 2010 12:09:11 +0530
changeset 0 b26acd06ea60
child 1 ac50fd48361b
permissions -rw-r--r--
First Contribution of SDK components

/*
* Copyright (c) 2004-2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#define TRACE_PREFIX "WSOCK: Interface: "
#include "wsock.h"
#include "WinsockInterface.h"
#include "WinsockProtocolFamily.h"

const TInt KWinsockSubConnectionId = 1;
const TConnectionType EWinsockConnectionType = EConnectionEthernet;
#define super CNifIfLink 

// CWinsockInterface::CallbackQueueEntry
class CWinsockInterface::CallbackQueueEntry
{
private:
    CWinsockInterface* iInterface;
    CallbackMethod iMethod;
    TInt iParam1;
    TInt iParam2;
public:
    TSglQueLink iLink;
    CallbackQueueEntry(CWinsockInterface* aInterface, CallbackMethod aMethod,
        TInt aParam1, TInt aParam2) : iInterface(aInterface), 
        iMethod(aMethod), iParam1(aParam1), iParam2(aParam2) {}
    void Invoke() { (iInterface->*iMethod)(iParam1, iParam2); }
};

// CWinsockInterface
CWinsockInterface::CWinsockInterface(CNifIfFactory* aFactory, 
                                     MNifIfNotify* aNotify) : 
super(*aFactory),
iSignature(KWinsockInterfaceSignature),
iCallbackQueue(_FOFF(CallbackQueueEntry,iLink)),
iCallback(TCallBack(AsyncCallbackProc,this),CActive::EPriorityStandard)
{
    iNotify = aNotify;
    iTimeStarted.HomeTime();
    TRACE1("created [%08X]",this);
}

CWinsockInterface::~CWinsockInterface()
{
    CancelOutstandingCallbacks();
    TRACE1("destroyed [%08X]",this);
}

TInt CWinsockInterface::Signature() const
{
    return KWinsockInterfaceSignature;
}

TInt CWinsockInterface::AsyncCallbackProc(TAny* aPtr)
{
    CWinsockInterface* self = (CWinsockInterface*)aPtr;
    self->HandleAsyncCallback();
    return KErrNone;
}

void CWinsockInterface::HandleAsyncCallback()
{
    // Invoke the first callback in the queue
    if (!iCallbackQueue.IsEmpty()) {
        CallbackQueueEntry* entry = iCallbackQueue.First();
        iCallbackQueue.Remove(*entry);
        entry->Invoke();
        delete entry;

        // Schedule the next one
        if (!iCallbackQueue.IsEmpty()) {
            iCallback.CallBack();
        }
    }
}

void CWinsockInterface::ScheduleAsyncCallback(CallbackMethod aMethod,
                                              TInt aP1, TInt aP2)
{
    CallbackQueueEntry* entry = new CallbackQueueEntry(this,aMethod,aP1,aP2);
    if (entry) {
        iCallbackQueue.AddLast(*entry);
        iCallback.Cancel();
        iCallback.CallBack();
    }
}

void CWinsockInterface::CancelOutstandingCallbacks()
{
    iCallback.Cancel();
    while (!iCallbackQueue.IsEmpty()) {
        CallbackQueueEntry* entry = iCallbackQueue.First();
        iCallbackQueue.Remove(*entry);
        delete entry;
    }
}

void CWinsockInterface::NotifyLinkLayerUp(TInt, TInt)
{
    ScheduleAsyncCallback(NotifySubConnectionOpened);
    TRACE("firing LinkLayerUp event");
    iNotify->LinkLayerUp();
}

void CWinsockInterface::NotifyLinkLayerOpen(TInt, TInt)
{
    TRACE("firing LinkLayerOpen event");
    iNotify->IfProgress(KLinkLayerOpen, KErrNone);
}

// Sends a subconnection opened event for the entire connection
void CWinsockInterface::NotifySubConnectionOpened(TInt, TInt)
{
    ScheduleAsyncCallback(NotifyLinkLayerOpen);

    TRACE("firing TSubConnectionOpenedEvent");
    TSubConnectionOpenedEvent event;
    event.iSubConnectionUniqueId = KNifEntireConnectionSubConnectionId;
    TPckg<TSubConnectionOpenedEvent> eventPtr(event);
    iNotify->NifEvent(ESubConnectionEvent, ESubConnectionOpened, eventPtr); 
}

// Sends a subconnection Closed event for the entire connection
void CWinsockInterface::NotifySubConnectionClosed(TInt aReason, TInt)
{
    ScheduleAsyncCallback(NotifyLinkLayerClosed, aReason);

    TRACE("firing TSubConnectionClosedEvent");
    TSubConnectionClosedEvent event;
    event.iSubConnectionUniqueId = KNifEntireConnectionSubConnectionId;
    event.iTotalUplinkDataVolume = iBytesReceived;
    event.iTotalDownlinkDataVolume = iBytesSent;
    event.iTimeClosed.UniversalTime();
    TPckg<TSubConnectionClosedEvent> eventPtr(event);
    iNotify->NifEvent(ESubConnectionEvent, ESubConnectionClosed, eventPtr);
}

void CWinsockInterface::NotifyLinkLayerDown(TInt aReason, TInt aAction)
{
    ScheduleAsyncCallback(NotifySubConnectionClosed, aReason);
    TRACE("firing LinkLayerDown event");
    iNotify->LinkLayerDown(aReason, (MNifIfNotify::TAction)aAction);
}

void CWinsockInterface::NotifyLinkLayerClosed(TInt aReason, TInt)
{
    TRACE("firing LinkLayerClosed event");
    iNotify->IfProgress(KLinkLayerClosed, aReason);
}

void CWinsockInterface::DataSent(TUint aBytes)
{
    // Handle rollover?
    iBytesSent += aBytes;
    if (iBytesSentGranularity)
    {
        TUint delta = iBytesSent - iBytesSentMark;
        if (delta >= iBytesSentGranularity)
        {
            int chunks = delta/iBytesSentGranularity;
            iBytesSentMark += chunks*iBytesSentGranularity;
            iNotify->NotifyDataSent(KWinsockSubConnectionId,
                delta*iBytesSentGranularity);
        }
    }
}

void CWinsockInterface::DataReceived(TUint aBytes)
{
    // Handle rollover?
    iBytesReceived += aBytes;
    if (iBytesReceivedGranularity)
    {
        TUint delta = iBytesReceived - iBytesReceivedMark;
        if (delta >= iBytesReceivedGranularity)
        {
            int chunks = delta/iBytesReceivedGranularity;
            iBytesReceivedMark += chunks*iBytesReceivedGranularity;
            iNotify->NotifyDataReceived(KWinsockSubConnectionId,
                delta*iBytesReceivedGranularity);
        }
    }
}

// CNifIfBase
void CWinsockInterface::Info(TNifIfInfo& aInfo) const
{
    aInfo.iName = KWinsockInterface;
    aInfo.iVersion = TVersion(1,0,0);
    aInfo.iFlags = KNifIfIsBase | KNifIfIsLink | KNifIfUsesNotify | KNifIfCreatedByFactory;
    aInfo.iProtocolSupported = 0;
    for (TInt i=0; i<CWinsockProtocolFamily::ProtocolCount(); i++)
    {
        const TServerProtocolDesc* p = CWinsockProtocolFamily::ProtocolDesc(i);
        aInfo.iProtocolSupported |= p->iProtocol;
    }
}

TInt CWinsockInterface::Send(RMBufChain& /*aPdu*/, TAny* /*aSource*/)
{
    TRACE("Send()");
    return KErrNotSupported;
}

TInt CWinsockInterface::Notification(TAgentToNifEventType DEBUG_ONLY(aEvent),
                                     TAny* /*aInfo*/)
{
    TRACE1("Notification(%d)",aEvent);
    return KErrNotSupported;
}

// CNifIfLink
TInt CWinsockInterface::Start()
{
    TRACE("Start()");
    ScheduleAsyncCallback(NotifyLinkLayerUp);
    return KErrNone;
}

void CWinsockInterface::Stop(TInt aReason, MNifIfNotify::TAction aAction)
{
    TRACE2("Stop(%d,%d)",aReason, aAction);
    CancelOutstandingCallbacks();
    ScheduleAsyncCallback(NotifyLinkLayerDown, aReason, aAction);
}

CNifIfBase* CWinsockInterface::GetBinderL(const TDesC& DEBUG_ONLY(aName))
{
    TRACE1("GetBinderL(%S)",&aName);
    return this;
}

TInt CWinsockInterface::Control(TUint aLevel,TUint aName,TDes8& aOption, 
                                TAny* aSource)
{
    TRACE3("Control(%d,%08X), %d bytes",aLevel,aName,aOption.Length());
	switch (aLevel)
    {
    case KCOLInterface:
        switch (aName)
        {
        case KCOGetNifEMIPtr:
        default:
            {
                MNifIfExtendedManagementInterface** that = 
                    (MNifIfExtendedManagementInterface**)aOption.Ptr();
                if (aOption.Length() == sizeof(*that))
                {
                    MNifIfExtendedManagementInterface* This = this;
                    TRACE1("MNifIfExtendedManagementInterface = %08X",This);
                    *that = This;
                    return KErrNone;
                }
                else
                {
                    return KErrArgument;
                }
            }
            break;
        }
        break;

    case KCOLAgent:
        switch (aName)
        {
        case KCOGetAgentEMIPtr:
            {
                MNifAgentExtendedManagementInterface** that = 
                    (MNifAgentExtendedManagementInterface**)aOption.Ptr();
                if (aOption.Length() == sizeof(*that))
                {
                    MNifAgentExtendedManagementInterface* This = this;
                    TRACE1("MNifAgentExtendedManagementInterface = %08X",This);
                    *that = This;
                    return KErrNone;
                }
                else
                {
                    return KErrArgument;
                }
            }
        default:
            break;
        }
        break;

    default:
        break;
    }
    return super::Control(aLevel, aName, aOption, aSource);
}

// MNifIfExtendedManagementInterface
TInt CWinsockInterface::Stop(TSubConnectionUniqueId aId, 
                             TInt DEBUG_ONLY(aReason))
{
    TRACE2("Stop(%d,%d)", aId, aReason);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::GetDataTransferred(TSubConnectionUniqueId aId, 
                                           TUint& aSentBytes, 
                                           TUint& aReceivedBytes)
{
    TRACE1("GetDataTransferred(%d)", aId);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        aSentBytes = iBytesSent;
        aReceivedBytes = iBytesReceived;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::SetDataSentNotificationGranularity(TSubConnectionUniqueId aId, 
                                                           TUint aGranularity)
{
    TRACE2("SetDataSentNotificationGranularity(%d,%d)", aId, aGranularity);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        iBytesSentGranularity = aGranularity;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::CancelDataSentNotification(TSubConnectionUniqueId aId)
{
    TRACE1("CancelDataSentNotification(%d)", aId);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        iBytesSentGranularity = 0;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::SetDataReceivedNotificationGranularity(TSubConnectionUniqueId aId, 
                                                               TUint aGranularity)
{
    TRACE2("SetDataReceivedNotificationGranularity(%d,%d)", aId, aGranularity);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        iBytesReceivedGranularity = aGranularity;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::CancelDataReceivedNotification(TSubConnectionUniqueId aId)
{
    TRACE1("CancelDataReceivedNotification(%d)", aId);
    switch (aId)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        iBytesReceivedGranularity = 0;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

// MNifAgentExtendedManagementInterface
TInt CWinsockInterface::GetInterfaceType(TConnectionType& aConnectionType)
{
    aConnectionType = EWinsockConnectionType;
    return KErrNone;
}

TInt CWinsockInterface::EnumerateSubConnections(TUint& aCount)
{
    aCount = 1;
    return KErrNone;
}

TInt CWinsockInterface::GetSubConnectionInfo(TUint aIndex, 
                                             TDes8& aInfo)
{
    if (aInfo.Length() != sizeof(TSubConnectionInfo))
    {
        return KErrArgument;
    }

    TSubConnectionInfo* info = (TSubConnectionInfo*)aInfo.Ptr();
    switch (aIndex)
    {
    case KNifEntireConnectionSubConnectionId:
    case KWinsockSubConnectionId:
        info->iConnectionType = EWinsockConnectionType;
        info->iSubConnectionUniqueId = aIndex;
        info->iTimeStarted = iTimeStarted;
        return KErrNone;
    default:
        return KErrNotFound;
    }
}

TInt CWinsockInterface::GetSubConnectionInfo(TDes8& aInfo)
{
    if (aInfo.Length() != sizeof(TSubConnectionInfo))
    {
        return KErrArgument;
    }

    TSubConnectionInfo* info = (TSubConnectionInfo*)aInfo.Ptr();
    return GetSubConnectionInfo(info->iSubConnectionUniqueId, aInfo);
}