⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockpcb.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// SOCKPCB.C
//
// Object member functions for the Sock device object.
//
// These functions include protocol control type access to the
// SOCKET object.
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "sock.h"

static SOCK *pSockList[] = { 0, 0, 0, 0, 0 };

// Next User Port for Ephemeral Ports
static uint wUserPort = SOCK_USERPORT_FIRST;

static SOCK *SockPcbFind( SOCK *psFirst, IPN dwLIP, uint LPort,
                          IPN dwFIP, uint FPort, int *pwc, int FindAll );

static SOCK *SockPcbFindRaw( SOCK *psFirst, uint Prot, IPN dwLIP,
                             IPN dwFIP, int *pwc, int FindAll );

//--------------------------------------------------------------------
// SockPcbAttach()
//
// Adds a socket to the supplied socket list
//--------------------------------------------------------------------
int SockPcbAttach( HANDLE hSock )
{
    SOCK *ps = (SOCK *)hSock;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockPcbAttach: HTYPE %04x",ps->Type);
        return( 0 );
    }

    if( ps->SockProt > 4 )
    {
        DbgPrintf(DBG_ERROR,"SockPcbAttach: Invalid SockProt");
        return( 0 );
    }
#endif

    // We'll insert at head of list since its quicker
    ps->pProtPrev = 0;
    ps->pProtNext = pSockList[ps->SockProt];
    pSockList[ps->SockProt] = (HANDLE)ps;

    // Patch entry which follows us (if any)
    if( ps->pProtNext )
        ps->pProtNext->pProtPrev = ps;

    return(0);
}

//--------------------------------------------------------------------
// SockPcbDetach()
//
// Removes a socket to the supplied socket list
//--------------------------------------------------------------------
int SockPcbDetach( HANDLE hSock )
{
    SOCK *ps   = (SOCK *)hSock;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockPcbDetach: HTYPE %04x",ps->Type);
        return( 0 );
    }

    if( ps->SockProt > 4 )
    {
        DbgPrintf(DBG_ERROR,"SockPcbDetach: Invalid SockProt");
        return( 0 );
    }
#endif

    // Patch preceeding entry
    if( !ps->pProtPrev )
        pSockList[ps->SockProt] = (HANDLE)ps->pProtNext;
    else
        ps->pProtPrev->pProtNext = ps->pProtNext;

    // Patch following entry
    if( ps->pProtNext )
        ps->pProtNext->pProtPrev = ps->pProtPrev;

    // Just to be tidy...
    ps->pProtPrev = 0;
    ps->pProtNext = 0;

    return(0);
}

//--------------------------------------------------------------------
// SockPcbFind()
//
// Find the "best" match for the supplied parameters.
//--------------------------------------------------------------------
static SOCK *SockPcbFind
(
    SOCK   *ps,
    IPN    dwLIP,
    uint   LPort,
    IPN    dwFIP,
    uint   FPort,
    int    *pwc,
    int    FindAll
)
{
    SOCK *psBest = 0;
    int  wcBest = 9;
    int  wc;

    // Find the "best" match for the supplied parameters.

    for( ; ps; ps = ps->pProtNext )
    {
        // Clear wild cards
        wc = 0;

        // Local port NULL means socket is not bound
        if( !ps->LPort )
            continue;

        // If local ports don't match, this entry can't match
        if( ps->LPort != LPort )
            continue;

        // Local IP must match, or be wildcard
        if( ps->dwLIP != dwLIP )
        {
            if( !dwLIP || !ps->dwLIP )
                wc++;
            else
                continue;
        }

        // Foreign Port+IP must both match or both be wildcard
        if( ps->FPort != FPort || ps->dwFIP != dwFIP )
        {
            if( (!dwFIP && !FPort) || (!ps->dwFIP && !ps->FPort) )
                wc++;
            else
                continue;
        }

        if( wc < wcBest )
        {
            wcBest = wc;
            psBest = ps;
        }

        if( FindAll )
            break;
    }

    if( pwc )
        *pwc = wcBest;
    return(psBest);
}

//--------------------------------------------------------------------
// SockPcbFindRaw()
//
// Find the "best" match for the supplied parameters.
//--------------------------------------------------------------------
static SOCK *SockPcbFindRaw
(
    SOCK   *ps,
    uint   Prot,
    IPN    dwLIP,
    IPN    dwFIP,
    int    *pwc,
    int    FindAll
)
{
    SOCK *psBest = 0;
    int  wcBest = 9;
    int  wc;

    // Find the "best" match for the supplied parameters.

    for( ; ps; ps = ps->pProtNext )
    {
        // Clear wild cards
        wc = 0;

        // Protocol must match, or be wildcard
        if( ps->Protocol && ps->Protocol != Prot )
            continue;

        // Local IP must match, or be wildcard
        if( ps->dwLIP != dwLIP )
        {
            if( !dwLIP || !ps->dwLIP )
                wc++;
            else
                continue;
        }

        // Foreign IP must match, or be wildcard
        if( ps->dwFIP != dwFIP )
        {
            if( !dwFIP || !ps->dwFIP )
                wc++;
            else
                continue;
        }

        if( wc < wcBest )
        {
            wcBest = wc;
            psBest = ps;
        }

        if( FindAll )
            break;
    }

    if( pwc )
        *pwc = wcBest;
    return(psBest);
}

//--------------------------------------------------------------------
// SockPcbBind()
//
// Binds a socket to specified local LIP and LPort
//
// Note: LIP can be NULL (wildcard), but in this implementaion, LPort
//       is never a wildcard. When not specified, LPort is assigned to
//       an ephemeral port.
//--------------------------------------------------------------------
int SockPcbBind( HANDLE hSock, IPN dwLIP, uint LPort )
{
    SOCK   *ps    = (SOCK *)hSock;
    SOCK   *psTmp;
    int    fEphem = 0;
    uint   SockOpts;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockPcbBind: HTYPE %04x",ps->Type);
        return( 0 );
    }

    if( ps->SockProt > 4 )
    {
        DbgPrintf(DBG_ERROR,"SockPcbBind: Invalid SockProt");
        return( 0 );
    }
#endif

    // Anything goes with Raw sockets
    if( ps->SockProt == SOCKPROT_RAW )
    {
        SockOpts = 0;
        goto SockPcbBindOk;
    }

    // On multicast addrs, REUSEADDR is the same as REUSEPORT
    SockOpts = ps->OptionFlags & (SO_REUSEPORT|SO_REUSEADDR);
    if( SockOpts == SO_REUSEADDR )
    {
        if( IN_MULTICAST( dwLIP ) )
            SockOpts = (SO_REUSEADDR|SO_REUSEPORT);
    }

    // If LPort is NULL, and we are already bound to an LPort,
    // then we'll use the previously bound value.
    if( !LPort && ps->LPort )
        LPort = ps->LPort;

    // OPTION: We *may* want to restrict IP addresses to those actually
    // available on our system.
    // OPTION: We *may* want to restrict reserved ports to some "system"
    // class user.

    // Check for ephemeral port
SockPcbBindEphem:
    if( !LPort )
    {
        if( ++wUserPort > SOCK_USERPORT_LAST )
              wUserPort = SOCK_USERPORT_FIRST;
        LPort = HNC16(wUserPort);
        fEphem = 1;
    }

    // Find the best match
    psTmp = SockPcbFind( pSockList[ps->SockProt], dwLIP, LPort, 0, 0, 0, 0 );

    // Check for conflict (and that we didn't match ourselves)
    if( psTmp && psTmp != ps && LPort == psTmp->LPort )
    {
        // If the IP's are different, we're OK
        if( dwLIP && psTmp->dwLIP && dwLIP != psTmp->dwLIP )
            goto SockPcbBindOk;

        // We don't allow conflicts on ephemeral ports
        if( fEphem )
        {
            LPort = 0;
            goto SockPcbBindEphem;
        }

        // We have a port conflict. See if we keep going anyway

        // Address Conflict

        // Exception 1: Check for "REUSEPORT" on both sockets
        if( psTmp->OptionFlags & SockOpts & SO_REUSEPORT )
            goto SockPcbBindOk;

        // Exception 2: One or the other Local IP is "wildcard", but not both,
        //              and both have REUSEADDR set.
        if( ((!dwLIP && psTmp->dwLIP) || (dwLIP && !psTmp->dwLIP)) &&
                      (psTmp->OptionFlags & SockOpts & SO_REUSEADDR) )
            goto SockPcbBindOk;

        return( EADDRINUSE );
    }

SockPcbBindOk:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -