📄 connection.c
字号:
// module implementing the TCP and UDP stacks. Uses info provided in sockets.c to invoke sockets as appropriate
#include <p18cxxx.h>
#include <delays.h>
#include "nic.h"
#include "network.h"
#include "sockets.h"
#include <usart.h>
extern SOCKETINFO socketInfo[];
//void send_tcp_packet(unsigned int,unsigned int,unsigned long,unsigned long,FLAGS);
void send_tcp_packet(unsigned char *,unsigned int,unsigned int,unsigned char,FLAGS);
//******************************************************************
//* TCP Header Layout
//******************************************************************
#define TCP_srcport 0x22 //TCP source port
#define TCP_destport 0x24 //TCP destination port
#define TCP_seqnum 0x26 //sequence number
#define TCP_acknum 0x2A //acknowledgement number
#define TCP_hdrflags 0x2E //4-bit header len and flags
#define TCP_window 0x30 //window size
#define TCP_cksum 0x32 //TCP checksum
#define TCP_urgentptr 0x34 //urgent pointer
#define TCP_data 0x36 //option/data
//******************************************************************
//* TCP Flags
//* IN flags represent incoming bits
//* OUT flags represent outgoing bits
//******************************************************************
#define FIN_IN (packet[TCP_hdrflags+1]&0b00000001)
#define SYN_IN (packet[TCP_hdrflags+1]&0b00000010)
#define RST_IN (packet[TCP_hdrflags+1]&0b00000100)
#define PSH_IN (packet[TCP_hdrflags+1]&0b00001000)
#define ACK_IN (packet[TCP_hdrflags+1]&0b00010000)
#define URG_IN (packet[TCP_hdrflags+1]&0b00100000)
#define FIN_OUT (packet[TCP_hdrflags+1]|=0b00000001)
#define SYN_OUT (packet[TCP_hdrflags+1]|=0b00000010)
#define RST_OUT (packet[TCP_hdrflags+1]|=0b00000100)
#define PSH_OUT (packet[TCP_hdrflags+1]|=0b00001000)
#define ACK_OUT (packet[TCP_hdrflags+1]|=0b00010000)
#define URG_OUT (packet[TCP_hdrflags+1]|=0b00100000)
//******************************************************************
//* UDP Header
//******************************************************************
#define UDP_srcport 0x22
#define UDP_destport UDP_srcport+2
#define UDP_len UDP_destport+2
#define UDP_cksum UDP_len+2
#define UDP_data UDP_cksum+2
unsigned long makeACKOrSEQ(unsigned char *data)
{
unsigned long ret=0;
unsigned char i;
for(i=0;i<4;i++) ret=(ret<<8)|(unsigned long)data[i];
return ret;
}
unsigned int computeIPHeaderChecksum(unsigned char *packet)
{
unsigned long hdr_chksum;
unsigned int chksum16;
signed int tcplen;
//hdr_chksum=computeIPChecksum(packet+ip_srcaddr,0,0x08);
//hdr_chksum = hdr_chksum + packet[ip_proto];
hdr_chksum=computeIPContributionToChecksum(packet);
switch(getIPDatagramType(packet))
{
case TCP:
tcplen = getIPDatagramPayloadLength(packet);
hdr_chksum = hdr_chksum + tcplen;
hdr_chksum=computeIPChecksum(packet+TCP_srcport,hdr_chksum,tcplen);
break;
case UDP:
hdr_chksum=computeIPChecksum(packet+UDP_len,hdr_chksum,0x02);
hdr_chksum=computeIPChecksum(packet+UDP_srcport,hdr_chksum,(((unsigned int)packet[UDP_len])<<8)|packet[UDP_len+1]);
break;
}
chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
return chksum16;
}
//******************************************************************
//* TCP Function
//* This function uses TCP protocol to act as a Telnet server on
//* port 8088 decimal. The application function is called with
//* every incoming character.
//******************************************************************/
unsigned char matchSocket(unsigned int port)
{
unsigned char i;
for(i=0;i<NSOCKETS;i++) if(port==socketInfo[i].port) return i;
return 255;
}
unsigned char matchSocketToPacket(unsigned int port,unsigned int sourcePort,unsigned char *srcIP)
{
unsigned char i;
if(srcIP==0) // find any unused slot for this socket
{
for(i=0;i<NSOCKETS;i++) if((!socketInfo[i].est)&&(port==socketInfo[i].port)) return i;
return 255;
}
else // check that there is a used socket that maps precisely to this one
{
for(i=0;i<NSOCKETS;i++) if((matchIP(socketInfo[i].ip,srcIP))&&(sourcePort==socketInfo[i].srcPort)&&(port==socketInfo[i].port)) return i;
return 255;
}
}
// rather simple-minded Round-Robin approach to deciding which server to interrogate for data next
unsigned char getNextSocket(void)
{
static unsigned char nextSocket=0;
nextSocket=(nextSocket+1)%NSOCKETS;
return nextSocket;
}
void doSyn(unsigned char *packet,unsigned char s,unsigned char inBytes)
{
unsigned char i;
static unsigned int ISN=0x1234;
FLAGS flags;
//putrsUSART("Received SYN\r\n");
if(!socketInfo[s].est)
{
socketInfo[s].syn=1;
socketInfo[s].fin=0;
// assemble client IP
getIPDatagramSourceAddr(packet,socketInfo[s].mac,socketInfo[s].ip);
socketInfo[s].srcPort=(((unsigned int)packet[TCP_srcport])<<8)|packet[TCP_srcport+1];
}
if(++ISN == 0x0000 || ++ISN == 0xFFFF) ISN = 0x1234;
socketInfo[s].seq=(((unsigned long)ISN)<<16)|0xffff;
socketInfo[s].clientSeq=makeACKOrSEQ(packet+TCP_seqnum)+1;
if(socketInfo[s].est)
{
flags.syn=0;
flags.rst=1;
}
else
{
flags.syn=1;
flags.rst=0;
}
flags.fin=0;
flags.ack=1;
flags.push=0;
//send_tcp_packet(1,make16(packet[ip_pktlen],packet[ip_pktlen+1])-40,socketInfo[s].seq,socketInfo[s].clientSeq,flags);
send_tcp_packet(packet,1,getIPDatagramLength(packet)-40,s,flags);
}
void doAck(unsigned char *packet,unsigned char s,unsigned int inBytes)
{
unsigned int outBytes;
unsigned long ackIn;
FLAGS flags;
flags.syn=0;
flags.rst=0;
flags.fin=0;
flags.ack=1;
if(PSH_IN) flags.push=1;
else flags.push=0;
//putrsUSART("Received ACK\r\n");
if((inBytes == 0)&&(socketInfo[s].syn))
{
//assemble the acknowledgment number from the incoming packet
ackIn =makeACKOrSEQ(packet+TCP_acknum);
//if the incoming packet is a result of session establishment
flags.syn=1;
socketInfo[s].putData(0,&flags,packet+TCP_data);
outBytes=socketInfo[s].getData(&flags,packet+TCP_data);
//putrsUSART("Output ");printByte(outBytes>>8);printByte(outBytes&0xff);putrsUSART(" bytes\r\n");
//outBytes=socketInfo[s].callback(0,&flags,packet+TCP_data);
flags.syn=0;
if(flags.fin) socketInfo[s].fin=1;
// run the TCP application - if it sends a FIN, note this fact
//clear the SYN flag
socketInfo[s].syn=0;
//the incoming acknowledgment is my new sequence number
socketInfo[s].seq=ackIn;
socketInfo[s].clientSeq=makeACKOrSEQ(packet+TCP_seqnum);
//expect to get an acknowledgment of the banner message
socketInfo[s].ack=socketInfo[s].seq+outBytes;
//send the TCP/IP packet
//send_tcp_packet(inBytes,outBytes,socketInfo[s].seq,socketInfo[s].clientSeq,flags);
send_tcp_packet(packet,inBytes,outBytes,s,flags);
socketInfo[s].seq+=outBytes;
socketInfo[s].est=1;
}
else if((inBytes!=0)&&(socketInfo[s].est))
{
// run the TCP application - if it sends a FIN, note this fact
//outBytes=socketInfo[s].callback(inBytes,&flags,packet+TCP_data);
socketInfo[s].putData(inBytes,&flags,packet+TCP_data);
outBytes=socketInfo[s].getData(&flags,packet+TCP_data);
if(flags.fin) socketInfo[s].fin=1;
//assemble the acknowledgment number from the incoming packet
ackIn =makeACKOrSEQ(packet+TCP_acknum);
//check for the number of bytes acknowledged
//determine how many bytes are outstanding and adjust the outgoing sequence number accordingly
//if(ackIn <= socketInfo[s].ack) socketInfo[s].seq=socketInfo[s].ack-(socketInfo[s].ack-ackIn);
if(ackIn <= socketInfo[s].ack) socketInfo[s].seq=ackIn;
//my expected acknowledgement number
socketInfo[s].clientSeq=makeACKOrSEQ(packet+TCP_seqnum)+inBytes;
socketInfo[s].ack=socketInfo[s].seq+outBytes;
//send_tcp_packet(inBytes,outBytes,socketInfo[s].seq,socketInfo[s].clientSeq,flags);
send_tcp_packet(packet,inBytes,outBytes,s,flags);
socketInfo[s].seq+=outBytes;
}
}
void doFinAck(unsigned char *packet,unsigned char s,unsigned int inBytes)
{
unsigned long ackIn;
FLAGS flags;
//putrsUSART("Received FIN ACK\r\n");
flags.syn=0;
flags.rst=0;
flags.fin=0;
flags.ack=1;
if(PSH_IN) flags.push=1;
else flags.push=0;
socketInfo[s].clientSeq=makeACKOrSEQ(packet+TCP_seqnum)+1;
//send_tcp_packet(1,0,socketInfo[s].seq,socketInfo[s].clientSeq,flags);
send_tcp_packet(packet,1,0,s,flags);
socketInfo[s].fin=0;
socketInfo[s].est=0;
}
void doFin(unsigned char *packet,unsigned char s,unsigned int inBytes)
{
unsigned int outBytes=0;
unsigned long ackIn;
FLAGS flags;
//putrsUSART("Received FIN\r\n");
if(socketInfo[s].est)
{
flags.syn=0;
flags.rst=0;
flags.fin=1;
flags.ack=1;
flags.push=1;
//outBytes=socketInfo[s].callback(inBytes,&flags,packet+TCP_data);
socketInfo[s].putData(inBytes,&flags,packet+TCP_data);
outBytes=socketInfo[s].getData(&flags,packet+TCP_data);
ackIn =makeACKOrSEQ(packet+TCP_acknum);
//if(ackIn <= socketInfo[s].ack) socketInfo[s].seq=socketInfo[s].ack-(socketInfo[s].ack-ackIn);
if(ackIn <= socketInfo[s].ack) socketInfo[s].seq=ackIn;
socketInfo[s].ack=socketInfo[s].seq+outBytes;
socketInfo[s].clientSeq=makeACKOrSEQ(packet+TCP_seqnum)+inBytes;
//send_tcp_packet(inBytes,outBytes,socketInfo[s].seq,socketInfo[s].clientSeq,flags);
send_tcp_packet(packet,inBytes,outBytes,s,flags);
socketInfo[s].seq+=outBytes;
socketInfo[s].est=0;
}
}
void doUnsolicitedSend(unsigned char *packet,unsigned char s)
{
unsigned int outBytes;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -