📄 tcpss.c
字号:
/*************************************************************************
*
* Copyright (c) 1993 - 2001 Accelerated Technology, Inc.
*
* PROPRIETARY RIGHTS of Accelerated Technology are involved in the
* subject matter of this material. All manufacturing, reproduction,
* use, and sales rights pertaining to this subject matter are governed
* by the license agreement. The recipient of this software implicitly
* accepts the terms of the license.
*
*************************************************************************/
/* Portions of this program were written by: */
/*************************************************************************
*
* part of:
* TCP/IP kernel for NCSA Telnet
* by Tim Krauskopf
*
* National Center for Supercomputing Applications
* 152 Computing Applications Building
* 605 E. Springfield Ave.
* Champaign, IL 61820
*
************************************************************************/
/*************************************************************************
*
* FILENAME VERSION
*
* TCPSS.C 4.4
*
* DESCRIPTION
*
* TCP socket services. That is those services that are used by the
* sockets layer to manage the TCP.
*
* DATA STRUCTURES
*
* NONE
*
* FUNCTIONS
*
* TCPSS_Do_Connect
* TCPSS_Net_Close
* TCPSS_Net_Listen
* TCPSS_Net_Read
* TCPSS_Net_Send
* TCPSS_Net_Write
* TCPSS_Net_Xopen
* TCPSS_Send_SYN_FIN
* TCPSS_Window_Probe
*
* DEPENDENCIES
*
* nucleus.h
* target.h
* tcp.h
* tcpdefs.h
* socketd.h
* externs.h
* ip.h
* netevent.
* nerrs.h
* arp.h
* net_extr.h
*
************************************************************************/
#include "plus/nucleus.h"
#include "net/target.h"
#include "net/inc/externs.h"
#include "net/inc/ip.h"
#include "net/inc/tcp.h"
#include "net/inc/tcpdefs.h"
#include "net/inc/socketd.h"
#include "net/inc/netevent.h"
#include "net/inc/nerrs.h"
#include "net/inc/arp.h"
#include "net/inc/net_extr.h"
#if (INCLUDE_SNMP == NU_TRUE)
#include SNMP_GLUE
#endif
extern NU_TASK NU_EventsDispatcher_ptr;
extern NU_TASK timer_task_ptr;
#if (INCLUDE_TCP == NU_TRUE)
/* Local Prototypes. */
static STATUS TCPSS_Net_Send(TCP_PORT *, NET_BUFFER *);
static STATUS TCPSS_Do_Connect(INT pnum, UINT16 service);
static INT32 TCPSS_Window_Probe(TCP_PORT *, UINT16, UINT8 HUGE *);
/*************************************************************************
*
* FUNCTION
*
* TCPSS_Net_Read
*
* DESCRIPTION
*
* Read data from the connection buffer (specified by *pnum*) into
* the user buffer for up to *n* bytes.
* Returns number of bytes read, or <0 if error. Does not block.
*
* INPUTS
*
* *sock_ptr
* *buffer
* nbytes
*
* OUTPUTS
*
* The number of bytes read or 0 if an error occurs.
*
*************************************************************************/
INT32 TCPSS_Net_Read(struct sock_struct *sock_ptr, char *buffer, UINT16 nbytes)
{
INT32 i, lowwater;
INT32 howmany;
INT pnum;
TCP_PORT *prt;
/* As long as there is data return it. It is possible for the connection to
have been closed in the event of a RESET. However, if the data is here
then it has been validated and is acceptable. So the data will be given to
the application even if the connection has been closed.
*/
if (sock_ptr->s_recvbytes > 0)
{
/* Retrieve the queue data. */
howmany = TLS_Dequeue(sock_ptr, buffer, (UINT32)nbytes);
if (sock_ptr->s_state & SS_ISCONNECTED)
{
/* Get the look up the index of the port structure. */
if ((pnum = sock_ptr->s_port_index) >= 0)
{
prt = TCP_Ports[pnum];
i = prt->in.size; /* how much before? */
prt->in.size += howmany; /* increment leftover room */
lowwater = (prt->credit >> 1);
if ((i < lowwater) && ((prt->in.size) >= lowwater))
TCP_ACK_It(prt, 1);
}
else
{
howmany = NU_NOT_CONNECTED;
}
}
}
else
{
/* There was no queued data to receive. So, check to see if the
connection still exists. */
if (sock_ptr->s_state & SS_ISCONNECTED)
howmany = 0;
else
howmany = NU_NOT_CONNECTED;
}
return (howmany);
} /* end TCPSS_Net_Read() */
/*************************************************************************
*
* FUNCTION
*
* TCPSS_Net_Write
*
* DESCRIPTION
*
* Write data into the output queue (specified by pnum).
* As long as there is buffer space and the foreign host's receive
* window has not been filled, data will be sent. The number of
* bytes actually sent is returned ( a number between 0 and nbytes).
*
* INPUTS
*
* *sockptr Pointer to a socket on which to send the data.
* *buffer Pointer to the data to be sent.
* nbytes The number of bytes of data to send.
* *status Indicates why all data could not be sent.
*
* OUTPUTS
*
* The number of bytes that were sent.
*
*************************************************************************/
INT32 TCPSS_Net_Write(struct sock_struct *sockptr, UINT8 HUGE *buffer, UINT16 nbytes,
INT *status)
{
INT nsent=0, s, temp_len;
INT32 sent_by_wp=0;
TCP_PORT *prt;
TCP_WINDOW *wind;
NET_BUFFER *buf_ptr, *work_buf;
INT32 bytes_to_move;
INT32 numbytes, bytes_left, bc;
INT pnum;
/* Assume a successful operation until we are proven wrong. */
*status = NU_SUCCESS;
if ((pnum = sockptr->s_port_index) < 0)
{
*status = NU_INVALID_PORT;
return(0);
}
if((prt = TCP_Ports[pnum]) == NU_NULL)
{
*status = NU_INVALID_PORT;
return(0);
}
/* must be established connection */
if((prt->state != SEST) && (prt->state != SCWAIT))
{
*status = NU_NOT_CONNECTED;
return(0);
}
wind = &prt->out;
numbytes = nbytes;
/* Find out what their advertised window size is. If we want to
send more bytes than they are advertising, then decrease the
amount of bytes we want to send. */
if ((wind->size - wind->contain) < numbytes)
{
numbytes = (wind->size - wind->contain);
}
if (numbytes <= 0)
{
/* Check to see if a window probe is needed. A probe is only needed if
the foreign port has advertised a window of 0 and there is no
unacknowledged data. */
if ( (wind->size == 0) && (wind->nxt == wind->ack) )
{
if ((sent_by_wp=TCPSS_Window_Probe(prt, nbytes, buffer)) == NU_NOT_ESTAB)
{
*status = NU_NOT_CONNECTED;
return(0);
}
/* Advance the buffer pointer beyond the data that has already been
sent. */
buffer += sent_by_wp;
numbytes = nbytes - sent_by_wp;
if (numbytes > (wind->size - wind->contain))
numbytes = wind->size - wind->contain;
}
else
{
*status = NU_WINDOW_FULL;
return(0);
}
}
/* Are there any packets that contain data but have not yet been sent.
Should never be more than one of these. */
if (wind->nextPacket != NU_NULL)
{
/* Get a pointer to the start of the buffer chain. */
buf_ptr = wind->nextPacket;
/* Calculate the amount of data to be put into this buffer chain. */
bytes_to_move = (numbytes < (UINT16)(MAX_SEGMENT_LEN - buf_ptr->mem_total_data_len))
? numbytes : (MAX_SEGMENT_LEN - buf_ptr->mem_total_data_len);
bytes_left = bytes_to_move;
/* Find the end of this buffer chain. */
for ( work_buf = buf_ptr;
work_buf->next_buffer != NU_NULL;
work_buf = work_buf->next_buffer);
if (work_buf == wind->nextPacket)
{
/* How much data should be added to this buffer. */
bc = (NET_PARENT_BUFFER_SIZE - NET_MAX_TCP_HEADER_SIZE)
- work_buf->data_len;
bc = (bytes_left < bc) ? bytes_left : bc;
}
else
{
/* How much data should be added to this buffer. */
bc = NET_MAX_BUFFER_SIZE - work_buf->data_len;
bc = (bytes_left < bc) ? bytes_left : bc;
}
NU_BLOCK_COPY (work_buf->data_ptr + work_buf->data_len, buffer, (unsigned int)bc);
work_buf->data_len += bc;
/* Bump up the total count for this buffer chain. */
buf_ptr->mem_total_data_len += bc;
bytes_left -= bc;
buffer += bc;
while (bytes_left)
{
/* Make sure there are enough buffers left before we take
another one. We must leave some for RX. */
if ((MAX_BUFFERS - MEM_Buffers_Used) <= NET_FREE_BUFFER_THRESHOLD)
{
/* Set the counter to reflect that we could not complete
sending all the data. */
bytes_to_move -= bytes_left;
/* Set bytes_left to zero so we can get out of this loop. */
bytes_left = 0;
/* Set the status. */
*status = NU_NO_BUFFERS;
continue;
}
work_buf->next_buffer = MEM_Buffer_Dequeue (&MEM_Buffer_Freelist);
work_buf = work_buf->next_buffer;
bc = (bytes_left < NET_MAX_BUFFER_SIZE) ?
bytes_left : NET_MAX_BUFFER_SIZE;
/* Copy the data. */
NU_BLOCK_COPY (work_buf->mem_packet, buffer, (unsigned int)bc);
/* Set the data pointer. */
work_buf->data_ptr = work_buf->mem_packet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -