📄 tcpss.c
字号:
/* Store the number of bytes in this buffer. */
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;
}
/* Update various conters and statistics. */
prt->out.contain += (UINT16) bytes_to_move;
nsent += (UINT16) bytes_to_move;
numbytes -= bytes_to_move;
/* Update the number of actual TCP data held in this packet. This will
only be used if this packet is retransmitted. */
buf_ptr->mem_tcp_data_len = (UINT16) buf_ptr->mem_total_data_len;
/* Now that the data has been broken up into packets, send it. If some
data was sent and there was a timer event set to transmit data, then
clear the event. The data that the event was intended for has just
been sent. */
if ( (TCPSS_Net_Send(prt, buf_ptr) > 0) && (prt->xmitFlag) )
{
UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);
prt->xmitFlag = NU_CLEAR;
/* Clear the next packet pointer since this packet was sent. */
wind->nextPacket = NU_NULL;
}
}
/* While there is more data to send break it up into individual packets
and send it. */
while (numbytes > 0)
{
/* If there is not enough data left to fill a complete buffer,
update bytes_to_move with the number of bytes left. */
if (numbytes <= MAX_SEGMENT_LEN)
bytes_left = numbytes;
else
bytes_left = MAX_SEGMENT_LEN;
/* 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)
{
/* Get out of the loop. */
numbytes = 0;
/* Set the status. */
*status = NU_NO_BUFFERS;
continue;
}
/* Allocate a buffer chain to stick the data in. */
buf_ptr = MEM_Buffer_Chain_Dequeue (&MEM_Buffer_Freelist,
(INT32)(bytes_left + NET_MAX_TCP_HEADER_SIZE));
/* Compute the data size with the TCP header. */
buf_ptr->mem_total_data_len = bytes_left;
buf_ptr->mem_tcp_data_len = (UINT16) bytes_left;
/* Clear the flags field. */
buf_ptr->mem_flags = 0;
work_buf = buf_ptr;
/* Copy the data into the buffer chain. */
while (bytes_left && work_buf)
{
/* Check to see if the current buffer is the first one in the chain.
The first one is treated differntly from the rest. */
if (work_buf == buf_ptr)
{
/* Set the number of bytes to copy to the minimum of the space
available or the bytes left. */
bc = (bytes_left < (NET_PARENT_BUFFER_SIZE - NET_MAX_TCP_HEADER_SIZE))
? bytes_left : (NET_PARENT_BUFFER_SIZE - NET_MAX_TCP_HEADER_SIZE);
/* Point to where the data will begin. */
work_buf->data_ptr = (work_buf->mem_parent_packet + NET_MAX_TCP_HEADER_SIZE);
}
else
{
/* Set the number of bytes to copy to the minimum of the space
available or the bytes left. */
bc = (bytes_left < NET_MAX_BUFFER_SIZE) ? bytes_left : NET_MAX_BUFFER_SIZE;
/* Point to where the data will begin. */
work_buf->data_ptr = work_buf->mem_packet;
}
/* Copy the data into the buffer. */
NU_BLOCK_COPY(work_buf->data_ptr, buffer, (unsigned int)bc);
/* update the number of bytes still to be copied. */
bytes_left -= bc;
/* Initialize the number of bytes of data in this buffer. */
work_buf->data_len = bc;
/* Advance the pointer to the userd data. */
buffer += bc;
/* Point to the next buffer in the chain. */
work_buf = work_buf->next_buffer;
}
/* Initialize the list that this packet will be deallocated to when
transmission is complete.
*/
buf_ptr->mem_dlist = &prt->out.packet_list;
buf_ptr->mem_port_index = prt->pindex;
/* Initialize the data length of this buffer. */
buf_ptr->mem_option_len = 0;
/* Preserve the number of bytes that we will attempt to send. */
temp_len = (UINT16) buf_ptr->mem_total_data_len;
/* Now that the data has been broken up into packets, send it. If some
data was sent and there was a timer event set to transmit data, then
clear the event. The data that the event was intended for has just
been sent. */
if ( ((s = TCPSS_Net_Send(prt, buf_ptr)) > 0) && (prt->xmitFlag) )
{
UTL_Timerunset (CONTX, (UNSIGNED)prt->pindex, (INT32)1);
prt->xmitFlag = NU_CLEAR;
/* Clear the next packet pointer since this packet was sent. */
wind->nextPacket = NU_NULL;
}
else if (s == 0)
wind->nextPacket = buf_ptr;
else if (s < 0)
{
/* Return the error code. */
*status = s;
break;
}
/* Now that the data has been successfully sent update the various
counters. */
/* Update the amount of data in this port. */
prt->out.contain += temp_len;
/* Update the number of packets in this port. */
prt->out.num_packets++;
/* Increment the number of bytes we have sent so far. */
nsent += temp_len;
/* Decrease the amount of data left before the caller's request has
* been filled. */
numbytes -= temp_len;
if(wind->nextPacket != NU_NULL)
{
prt->xmitFlag = NU_SET;
UTL_Timerset(CONTX, (UNSIGNED)prt->pindex, SWSOVERRIDE, (INT32)0);
}
}
/* If the other side has sent a FIN then indicate that the connection is
closing. */
if (prt->state == SCWAIT)
*status = NU_CLOSING;
return(nsent+sent_by_wp);
} /* end TCPSS_Net_Write() */
/*************************************************************************
*
* FUNCTION
*
* TCPSS_Net_Listen
*
* DESCRIPTION
*
* Listen to a TCP port number and make the connection automatically
* when the SYN packet comes in. The TCP layer will notify the
* higher layers with a CONOPEN event. Save the port number returned
* to refer to this connection.
*
* example usage : portnum=netlisten ( service )
*
* Returns < 0 if error
*
* INPUTS
*
* serv
* *tcp_check
*
* OUTPUTS
*
* -1
* -2
* The port number
*
*************************************************************************/
STATUS TCPSS_Net_Listen(UINT16 serv, struct pseudotcp *tcp_check)
{
INT pnum;
INT16 i, pos;
TCP_PORT *prt;
INT32 tval, tmp, tmnc;
SCK_SOCKADDR_IP *dest;
/* Init */
pos = NU_IGNORE_VALUE;
tval = NU_NULL;
/* Try to make a new port. */
if((pnum = TCP_Make_Port())<0)
{
/* If make port failed we will try to reuse one that is in the
time wait state and has timedout. */
if (pnum == -1)
{
/* Get the current clock value. */
tmnc = NU_Retrieve_Clock();
/* Loop through the port list checking for timedout ports.
Note we will use the oldest timedout port. */
for(i = 0; (!(i >= TCP_MAX_PORTS) && (TCP_Ports[i] != NU_NULL)); i++)
{
/* Is this port in the time wait state. */
if (TCP_Ports[i]->state == STWAIT)
{
/* Compare the timeout time and the current time. */
tmp = labs(INT32_CMP(tmnc, TCP_Ports[i]->out.lasttime));
/* Has this port timedout. */
if (tmp > tval)
{
/* Save this ports time value. This is used in finding
the oldeset timedout port. */
tval = tmp;
/* Store it position for use below. */
pos = i;
} /* end if the port timedout */
} /* end if the port is in the time wait state */
} /* end loop search through the ports */
/* Did we loop through all the ports or not find one that
has timedout. */
if((pos >= TCP_MAX_PORTS) || (pos == NU_IGNORE_VALUE))
{
NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
return(-2);
}
/* Save the position in the port list. */
pnum = pos;
}
} /* end if there was no port returned from TCP_Make_Port */
/* Make sure this port entry is valid. */
if(NU_NULL==(prt=TCP_Ports[pnum]))
return(-2);
/* Create the socket that will be used by the application that accepts
this connection. */
if ( (prt->p_socketd = SCK_Create_Socket(NU_PROTO_TCP)) < 0)
{
prt->state = SCLOSED;
return (-2);
}
/* Store the port index. */
SCK_Sockets[prt->p_socketd]->s_port_index = pnum;
/* Point to the destination. */
dest = (SCK_SOCKADDR_IP *) &prt->tp_route.rt_ip_dest;
dest->sck_family = SK_FAM_IP;
dest->sck_len = sizeof (*dest);
dest->sck_addr = LONGSWAP(tcp_check->source);
IP_Find_Route(&prt->tp_route);
if (prt->tp_route.rt_route == NU_NULL)
{
prt->state = SCLOSED;
return -1;
}
prt->tcp_laddr = LONGSWAP(tcp_check->dest);
prt->in.port=serv;
prt->out.port=0; /* accept any outside port #*/
prt->in.lasttime=NU_Retrieve_Clock(); /* set time we started */
prt->state = SLISTEN;
prt->credit = WINDOW_SIZE; /* default value until changed */
return(pnum);
} /* end TCPSS_Net_Listen() */
/*************************************************************************
*
* FUNCTION
*
* TCPSS_Net_Xopen
*
* DESCRIPTION
*
* Open a network socket for the user to *machine* using
* port *service*. The rest of the parameters are self-explanatory.
*
* INPUTS
*
* *machine
* service
* socketd
*
* OUTPUTS
*
* pnum
* NU_NO_PORT_NUMBER
* -1
* -4
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -