sdkcreationmw/sdkruntimes/wsock/src/WinsockProtocol.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-2006 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: Protocol: "
#include "wsock.h"
#include "WinsockProtocol.h"
#include "WinsockProtocolFamily.h"
#include "WinsockHostResolver.h"
#include "WinsockServProvider.h"
#include "WinsockUtils.h"

CWinsockProtocol::CWinsockProtocol(const TWinProtocolDesc* aProtocolDesc) :
iProtocolDesc(aProtocolDesc)
{
    TRACE3("[%08X] created %s %S protocol",this,
        (iProtocolDesc->iAddrFamily == KAfInet6) ? _S("IPv6") : _S("IPv4"),
        &iProtocolDesc->iName);
}

CWinsockProtocol::~CWinsockProtocol()
{
    iReadPending.Reset();
    if (iIpHlpApi)
    {
        BEGIN_WIN32();
        FreeLibrary((HMODULE)iIpHlpApi);
        END_WIN32();
    }
    TRACE2("[%08X] deleted %S protocol",this,&iProtocolDesc->iName);
}

TBool CWinsockProtocol::IsStreamProtocol() const
{
    return (iProtocolDesc->iSockType == KSockStream);
}

TBool CWinsockProtocol::IsDatagramProtocol() const
{
    return (iProtocolDesc->iSockType == KSockDatagram);
}

void CWinsockProtocol::DataSent(TUint aBytes)
{
    if (iWinsockInterface)
    {
        iWinsockInterface->DataSent(aBytes);
    }
    else if (iIfNotify)
    {
        iIfNotify->NotifyDataSent(KNifEntireConnectionSubConnectionId,aBytes);
    }
}

void CWinsockProtocol::DataReceived(TUint aBytes)
{
    if (iWinsockInterface)
    {
        iWinsockInterface->DataReceived(aBytes);
    }
    else if (iIfNotify)
    {
        iIfNotify->NotifyDataReceived(KNifEntireConnectionSubConnectionId,aBytes);
    }
}

WinsockIpAdapterInfo* CWinsockProtocol::GetAdapterInfo()
{
    if (!iIpHlpApi && iIpHlpApi != INVALID_HANDLE_VALUE)
    {
        BEGIN_WIN32();
        iIpHlpApi = LoadLibraryA("IPHLPAPI.DLL");
        if (iIpHlpApi)
        {
            iGetAdapterInfo = (GetAdaptersInfoProc)GetProcAddress((HMODULE)
                              iIpHlpApi, "GetAdaptersInfo");
            if (iGetAdapterInfo)
            {
                END_WIN32();
            }
            else
            {
                FreeLibrary((HMODULE)iIpHlpApi);
                END_WIN32();
                iIpHlpApi = INVALID_HANDLE_VALUE;
                TRACE("failed to find GetAdaptersInfo in IPHLPAPI.DLL");
            }
        }
        else
        {
            END_WIN32();
            iIpHlpApi = INVALID_HANDLE_VALUE;
            TRACE1("failed to load IPHLPAPI.DLL, err %d",GetLastError());
        }
    }

    WinsockIpAdapterInfo* info = NULL;
    if (iGetAdapterInfo)
    {
        TUint len = 0;
        BEGIN_WIN32();
        TUint err = iGetAdapterInfo(NULL, &len);
        END_WIN32();
        if (err == ERROR_BUFFER_OVERFLOW && len > 0)
        {
            info = (WinsockIpAdapterInfo*)User::Alloc(len);
            if (info)
            {
                BEGIN_WIN32();
                err = iGetAdapterInfo(info, &len);
                END_WIN32();
                if (err != ERROR_SUCCESS)
                {
                    TRACE1("GetAdapterInfo err %d",err);
                    User::Free(info);
                    info = NULL;
                }
            }
        }
    }
    return info;
}

// Notifies CWinsockProtocol that there are unread data in a particular
// socket.
void CWinsockProtocol::SetReadPending(CWinsockServProvider* aSocket, 
                                      TBool aPending)
{
    TInt index = iReadPending.FindInAddressOrder(aSocket);
    if (aPending)
    {
        if (index < 0)
        {
            iReadPending.InsertInAddressOrder(aSocket);
            TRACE2("[%08X] %d socket(s) have unread data",this,
                iReadPending.Count());
        }
    }
    else
    {
        if (index >= 0)
        {
            iReadPending.Remove(index);
            TRACE2("[%08X] %d socket(s) have unread data",this,
                iReadPending.Count());
        }
    }
}

// Checks if there are any unread data in any socket associated with this
// protocol.
TBool CWinsockProtocol::ReadPending() const
{
    return (iReadPending.Count() > 0);
}

// CProtocolBase
CServProviderBase* CWinsockProtocol::NewSAPL(TUint DEBUG_ONLY(aSockType))
{
    TRACE3("[%08X] NewSAPL(%d) for %S",this,aSockType,&iProtocolDesc->iName);
    return CWinsockServProvider::NewL(this);
}

CHostResolvProvdBase* CWinsockProtocol::NewHostResolverL()
{
    return CWinsockHostResolver::NewL(iProtocolDesc);
}

void CWinsockProtocol::Identify(TServerProtocolDesc* aProtocolDesc) const
{
    *aProtocolDesc = *iProtocolDesc;
}

TInt CWinsockProtocol::GetOption(TUint aLevel, TUint aName, TDes8& aOption, 
                                 CProtocolBase* aSourceProtocol)
{
    if(aLevel == KNifOptLevel)
    {
        if(aName == KNifOptGetNifIfUser)
        {
            TNifIfUser ifuser;
            ifuser() = this;
            aOption.Copy(ifuser);
            return KErrNone;
        }
    }
    return CProtocolBase::GetOption(aLevel, aName, aOption, aSourceProtocol);
}

// MNifIfUser
void CWinsockProtocol::IfUserBindFailure(TInt /*aResult*/, TAny* /*aId*/)
{
    TRACE1("[%08X] IfUserBindFailure",this);
}

void CWinsockProtocol::IfUserNewInterfaceL(CNifIfBase* aIf, TAny* /*aId*/)
{
    TRACE1("[%08X] IfUserNewInterfaceL",this);
    ASSERT(aIf && aIf->Notify());
    if (aIf) 
    {
        iWinsockInterface = NULL;
        iIfNotify = aIf->Notify();
        CWinsockInterface* mayBeWinsockInterface = (CWinsockInterface*)aIf;
        if (mayBeWinsockInterface->Signature() == KWinsockInterfaceSignature)
        {
            iWinsockInterface = mayBeWinsockInterface;
        }
    }
}

void CWinsockProtocol::IfUserInterfaceDown(TInt /*aResult*/, 
                                           CNifIfBase* DEBUG_ONLY(aIf))
{
    TRACE1("[%08X] IfUserInterfaceDown",this);
    ASSERT(aIf && iIfNotify && (aIf->Notify() == iIfNotify));
    iIfNotify = NULL;
    iWinsockInterface = NULL;
}

void CWinsockProtocol::IfUserOpenNetworkLayer()
{
    TRACE1("[%08X] IfUserOpenNetworkLayer",this);
    Open();
}

void CWinsockProtocol::IfUserCloseNetworkLayer()
{
    TRACE1("[%08X] IfUserCloseNetworkLayer",this);
    Close();
}

CProtocolBase* CWinsockProtocol::IfUserProtocol()
{
    return this;
}

TBool CWinsockProtocol::IfUserIsNetworkLayerActive()
{
    TRACE1("[%08X] IfUserIsNetworkLayerActive",this);
    return ETrue;
}

/**
 * Local Variables:
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * End:
 */