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

📄 sockint.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// SOCKINT.C
//
// Object member functions for the Sock device object.
//
// These functions are called from elsewhere in the stack, and would
// not be called from the user layer.
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "sock.h"

static void SockDeqPending( SOCK *ps );
static void SockDeqReady( SOCK *ps );

//--------------------------------------------------------------------
// SockNotify()
//
// Notifies Socket of activity
//--------------------------------------------------------------------
void SockNotify( HANDLE h, int Notification )
{
    SOCK *ps = (SOCK *)h;

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

    //
    // First, special case abandoned sockets. They need to wiggle
    // (perhaps finish sending data), but they won't ever send data
    // again!
    //
    if( ps->StateFlags & SS_CLOSING )
    {
        switch( Notification )
        {
        case SOCK_NOTIFY_CLOSED:
            SockIntAbort( ps );
            break;

        case SOCK_NOTIFY_CONNECT:
        case SOCK_NOTIFY_ERROR:
        case SOCK_NOTIFY_RCVACK:
            break;

        case SOCK_NOTIFY_DISCONNECT:
            // Notification that the connection is disconnected
            ps->StateFlags &= ~SS_ISCONNECTING;
            ps->StateFlags |= (SS_CANTRCVMORE | SS_CANTSENDMORE);
            break;

        case SOCK_NOTIFY_RCVDATA:
            // Notification that Socket read data is available.
            // No one is around to read it so we flush it.
            // Note that TcpOuput has yet to be called for this
            // input data (this function was called from TcpInput).
            // Thus, we just flush the stream.
            if( ps->hSBRx )
                SBFlush( ps->hSBRx, 1 );
            break;

        case SOCK_NOTIFY_RCVFIN:
            // Notification that the Socket will receive no more data
            ps->StateFlags |= SS_CANTRCVMORE;
            break;
        }
        return;
    }

    switch( Notification )
    {
    case SOCK_NOTIFY_CONNECT:
        // Notification that Socket is fully connected

        // First, set socket state to CONNECTED
        ps->StateFlags &= ~SS_ISCONNECTING;
        ps->StateFlags |= SS_ISCONNECTED;

        // There are two cases for a connect. The first is a child of
        // a "listening" socket, and the other is an independently
        // connected socket. In the latter case, we simply wake the
        // owning task.
        if( !ps->pParent )
            FDSignalEvent( ps->hFd, FD_EVENT_READ );
        else
        {
            // When the socket is a child of a listening socket, we move
            // the socket in question from the pending queue to the ready
            // queue of the parent.

            // If its on the pending queue, we'll move it off
            if( ps->StateFlags & SS_PENDINGQ )
            {
                // Dequeue from Pending
                SockDeqPending( ps );       // ps->pParent is not cleared

                // Enqueue onto Ready
                ps->pReady = ps->pParent->pReady;
                ps->pParent->pReady = ps;
                ps->StateFlags |= SS_READYQ;
                ps->pParent->ConnTotal++;
            }

            // Now we wake the owning task of the parent socket
            FDSignalEvent( ps->pParent->hFd, FD_EVENT_READ );
        }
        break;

    case SOCK_NOTIFY_RCVACK:
        // Notification that Socket write data has been consumed

        // Wake owning task if waiting on write
        FDSignalEvent( ps->hFd, FD_EVENT_WRITE );
        break;

    case SOCK_NOTIFY_RCVDATA:
        // Notification that Socket read data is available

        // If we're shutdown, then flush it
        if( ps->StateFlags & SS_CANTRCVMORE )
        {
            if( ps->hSBRx )
                SBFlush( ps->hSBRx, 1 );
        }

        // Wake owning task if waiting on read
        FDSignalEvent( ps->hFd, FD_EVENT_READ );
        break;

    case SOCK_NOTIFY_RCVFIN:
        // Notification that the Socket will receive no more data

        // Mark the fact that we can't receive more data. This will
        // prevent the receive routine from blocking
        ps->StateFlags |= SS_CANTRCVMORE;

        // If not a child socket, wake owning task if waiting on read or on OOB
        if( !ps->pParent )
            FDSignalEvent( ps->hFd, FD_EVENT_READ | FD_EVENT_EXCEPT );
        // Else if on a ReadyQ, close it and toss it
        else if( ps->StateFlags & SS_READYQ )
        {
            // Dequeue from Ready
            SockDeqReady( ps );         // ps->pParent is not cleared

            // Close socket in the background
            ps->StateFlags |= SS_CLOSING;
            SockPrDisconnect( ps );
        }
        break;

    case SOCK_NOTIFY_DISCONNECT:
        // Notification that the connection is disconnected, but not
        // yet closed. Can not send or receive data

        // Adjust the current state
        ps->StateFlags &= ~(SS_ISCONNECTING | SS_LINGERING);
        ps->StateFlags |= (SS_CANTRCVMORE | SS_CANTSENDMORE);

        // If not a child socket, wake owning task if waiting on anything
        if( !ps->pParent )
            FDSignalEvent(ps->hFd, FD_EVENT_READ|FD_EVENT_WRITE|FD_EVENT_EXCEPT);
        // Else if on a ReadyQ move it back to PendingQ
        else if( ps->StateFlags & SS_READYQ )
        {
            // Dequeue from Ready
            SockDeqReady( ps );         // ps->pParent is not cleared

            // Enqueue onto Pending
            ps->pPending = ps->pParent->pPending;
            ps->pParent->pPending = ps;
            ps->StateFlags |= SS_PENDINGQ;
            ps->pParent->ConnTotal++;
        }
        break;

    case SOCK_NOTIFY_CLOSED:
        // Notification that the connection is fully closed.

        // Reset the socket state
        ps->StateFlags &= ~( SS_ISCONNECTING | SS_ISCONNECTED |
                             SS_CLOSING | SS_LINGERING );

        // If not a child socket, wake owning task if waiting on anything
        if( !ps->pParent )
            FDSignalEvent(ps->hFd, FD_EVENT_READ|FD_EVENT_WRITE|FD_EVENT_EXCEPT);
        else if( ps->StateFlags & (SS_READYQ | SS_PENDINGQ) )
        {
            // We simply abort any child socket

            // If on a ReadyQ, remove it
            if( ps->StateFlags & SS_READYQ )
                SockDeqReady( ps );
            // else If on a PendingQ, remove it
            if( ps->StateFlags & SS_PENDINGQ )
                SockDeqPending( ps );

            SockIntAbort( ps );
        }
        break;

    case SOCK_NOTIFY_ERROR:
        FDSignalEvent(ps->hFd, FD_EVENT_READ|FD_EVENT_WRITE|FD_EVENT_EXCEPT);
        break;
    }
}

//--------------------------------------------------------------------
// SockSetOOBMark()
//
// Notifies Socket of OOB Data, and sets synchronization mark
//--------------------------------------------------------------------
void SockSetOOBMark( HANDLE hSock, INT32 OOBMark )
{
    SOCK  *ps = (SOCK *)hSock;

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

    // Store the mark
    ps->OOBMark = OOBMark;

    // Enter OOB mode
    ps->StateFlags |= SS_OOBACTIVE;

    // Clear the held data
    ps->StateFlags &= ~SS_OOBDATAVALID;

    // Wake owning task if waiting on OOB data
    FDSignalEvent( ps->hFd, FD_EVENT_EXCEPT);
}

//--------------------------------------------------------------------
// SockSetOOBData()
//
// Sets th OOB Data byte once in OOB Mode
//--------------------------------------------------------------------
void SockSetOOBData( HANDLE hSock, UINT8 OOBData )
{
    SOCK     *ps = (SOCK *)hSock;

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

    // Store the data
    ps->OOBData = OOBData;

    // Set valid
    ps->StateFlags |= SS_OOBDATAVALID;

    // Wake owning task if waiting on OOB data
    FDSignalEvent( ps->hFd, FD_EVENT_EXCEPT);
}

//--------------------------------------------------------------------
// SockSpawnAbort()
//
// Called to abort a socket spawned via a call to SockPcbResolve
//--------------------------------------------------------------------
void SockSpawnAbort( HANDLE h )
{
    SOCK *ps = (SOCK *)h;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockSpawnAbort: HTYPE %04x",ps->Type);
        return;
    }
    if( !ps->pParent )
    {
        DbgPrintf(DBG_ERROR,"SockSpawnAbort: No Parent!");
        return;
    }
#endif

    // This is pretty simple - just dequeue and abort
    if( ps->StateFlags & SS_PENDINGQ )
        SockDeqPending( ps );
    SockIntAbort( ps );
}

//--------------------------------------------------------------------
// SockDeqPending()
//
// Dequeues a socket from the parent's Pending queue
//--------------------------------------------------------------------
static void SockDeqPending( SOCK *ps )
{
    SOCK *psTemp;

    psTemp = ps->pParent;

    // Zap this flag regardless
    ps->StateFlags &= ~SS_PENDINGQ;

    // Find the socket we're looking for or the end of the list
    while( psTemp->pPending && psTemp->pPending != ps )
        psTemp = psTemp->pPending;

    // If not the end of the list, when dequeue the socket
    if( psTemp->pPending )
    {
        psTemp->pPending = ps->pPending;
        ps->pParent->ConnTotal--;
    }
}

//--------------------------------------------------------------------
// SockDeqReady()

⌨️ 快捷键说明

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