📄 sockint.c
字号:
//--------------------------------------------------------------------------
// 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 + -