📄 tcp.c
字号:
tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]); tcp_send_packet(buffer, socketnum, (TCP_FIN_FLAG), 0); #if TCP_DEBUG softuart_puts_progmem("LAST_ACK"); #endif break; ///LAST_ACK case(TCP_STATE_LAST_ACK): //socket is closed tcp_close_socket(socketnum); #if TCP_DEBUG softuart_puts_progmem("LAST_ACK->CLOSED"); #endif break; ///FIN WAIT 1 case(TCP_STATE_FIN_WAIT1): //if we receive FIN tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ])+1; #if TCP_DEBUG softuart_puts_progmem("FIN_WAIT1->"); #endif if (tcp_header_flags == TCP_FIN_FLAG){ //goto CLOSING & send an ack: tcp_sockets[socketnum].state = TCP_STATE_CLOSING; tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0); #if TCP_DEBUG softuart_puts_progmem("CLOSING"); #endif }else if(tcp_header_flags == (TCP_FIN_FLAG | TCP_ACK_FLAG)){ //FIN&ACK -> send ACK & close ! if (nic_buffer_to_seq(&buffer[TCP_POS_ACK]) == tcp_sockets[socketnum].seq){ //close socket! tcp_close_socket(socketnum); #if TCP_DEBUG softuart_puts_progmem("CLOSED !"); #endif }else{ //both have sent the connection close request, we must wait for an last ack tcp_sockets[socketnum].state = TCP_STATE_LAST_ACK; #if TCP_DEBUG softuart_puts_progmem("LAST ACK !"); #endif } tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0); }else{ //ACK -> goto FIN WAIT2 tcp_sockets[socketnum].state = TCP_STATE_FIN_WAIT2; #if TCP_DEBUG softuart_puts_progmem("FIN_WAIT2"); #endif } break; ///FIN WAIT 2 case(TCP_STATE_FIN_WAIT2): //if we receive FIN tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ])+1; //tcp_sockets[socketnum].seq = nic_buffer_to_seq(&buffer[TCP_POS_ACK]); if (tcp_header_flags & TCP_FIN_FLAG){ //FIN -> goto TIMED WAIT tcp_sockets[socketnum].state = TCP_STATE_TIMED_WAIT; tcp_send_packet(buffer, socketnum, (TCP_ACK_FLAG), 0); #if TCP_DEBUG softuart_puts_progmem("FIN_WAIT2->TIMED_WAIT"); #endif } break; ///TIMED WAIT: case(TCP_STATE_TIMED_WAIT): #if TCP_DEBUG softuart_puts_progmem("TIMED_WAIT: packet in ?! "); #endif break; ///CLOSING case(TCP_STATE_CLOSING): if (tcp_header_flags & TCP_ACK_FLAG){ tcp_sockets[socketnum].state = TCP_STATE_TIMED_WAIT; #if TCP_DEBUG softuart_puts_progmem("CLOSING->TIMED_WAIT"); #endif } break; default: #if TCP_DEBUG softuart_puts_progmem("ERROR: invalid tcp state ! socket closed!"); #endif tcp_close_socket(socketnum); } #if TCP_DEBUG softuart_putnewline(); #endif //we must set timed wait TTL here because timed wait is not packet triggered if (tcp_sockets[socketnum].state == TCP_STATE_TIMED_WAIT){ tcp_sockets[socketnum].ttl = 5; //5 seconds timeout #if TCP_DEBUG softuart_puts_progmem("TIMED_WAIT: timeout set to 5s"); softuart_putnewline(); #endif } return; } } } } //there is no active socket! -> conn request ? if (tcp_header_flags == TCP_SYN_FLAG){ //yes, connection request. find a free socket: socketnum = tcp_find_free_socket(); if (socketnum < TCP_SOCKET_COUNT){ //free socket found (:= socketnum) -> handle request tcp_sockets[socketnum].state = TCP_STATE_SYN_RECEIVED; tcp_sockets[socketnum].source_port = source_port; tcp_sockets[socketnum].source_ip = source_ip; tcp_sockets[socketnum].dest_port = dest_port; tcp_sockets[socketnum].ack = nic_buffer_to_seq(&buffer[TCP_POS_SEQ])+1; tcp_sockets[socketnum].seq = 0; tcp_sockets[socketnum].ttl = TCP_TTL_TIMEOUT; tcp_sockets[socketnum].misc_state = 0; //send SYN+ACK Packet tcp_send_packet(buffer, socketnum, (TCP_SYN_FLAG|TCP_ACK_FLAG), 0); //init seq counter: tcp_sockets[socketnum].seq = 1; //cleanup/initialise httpd connection: httpd_cleanup_conn(socketnum); #if TCP_DEBUG softuart_puts_progmem("TCP : connection request. [OK]"); softuart_putnewline(); #endif return; } } ///////////////////////////////////////////////////// //if we get here something went wrong ... // - we have no open socket for this packet // - this is not an connection request // - we have no more free sockets left (!) //tcp_send_packet(buffer, socketnum, TCP_RST_FLAG, 0);//NO! WE HAVE NO SOCKNUM! #if TCP_DEBUG softuart_puts_progmem("TCP : WARN: ignoring packet (no socket open)"); softuart_putnewline(); #endif return;}//called ~every second, removes dead tcp sockets// - decrement ttl (starts with TCP_TTL_TIMEOUT -> TCP_TTL_TIMEOUT seconds inactivity = timeout)// - if ttl==0 -> mark socket as closed !void tcp_ttl_cleanup(){ unsigned char i; for(i=0; i<TCP_SOCKET_COUNT; i++){ //decrement ttl: if (tcp_sockets[i].state != TCP_STATE_CLOSED){ tcp_sockets[i].ttl--; //if socket TTL count is zero, close this socket! if (tcp_sockets[i].ttl == 0){ tcp_close_socket(i); #if TCP_DEBUG softuart_puts_progmem("TCP : TTL timeout for socket ["); softuart_put_uint8(i); softuart_puts_progmem("]. socket closed."); softuart_putnewline(); #endif } } }}void tcp_close_socket(unsigned char socketnum){ tcp_sockets[socketnum].state = TCP_STATE_CLOSED; httpd_cleanup_conn(socketnum);}//send a tcp packet:void tcp_send_packet(unsigned char *buffer, unsigned char socketnum, unsigned char flags, unsigned int len){ unsigned int arp_idx; unsigned int tmp; unsigned long *ip; if ((tcp_sockets[socketnum].source_ip & NIC_IP_NETMASK) != (nic_ip & NIC_IP_NETMASK)){ #if TCP_DEBUG softuart_puts_progmem("TCP : ip "); softuart_put_ip(tcp_sockets[socketnum].source_ip); softuart_puts_progmem(" outside home net -> use gateway\r\n"); #endif ip = &nic_gateway_ip; }else{ ip = &tcp_sockets[socketnum].source_ip; } arp_idx = arp_search_by_ip(*ip); if (arp_idx == -1){ //target ip (gateway) unknown #if TCP_DEBUG softuart_puts_progmem("TCP : ERR ARP UKNWN: "); softuart_put_ip(tcp_sockets[socketnum].source_ip); #endif //normal solution: //arp_send_request(buffer, ip); //return; //<- must be called again !!! ///FIXME #if TCP_DEBUG softuart_puts_progmem("-> calling arp'hack to add mac<->ip mapping"); softuart_putnewline(); #endif //but we do not want to wait for arp request etc //we received an ip packet and we did not touch the mac header etc yet! //-> the source mac is still in buffer! -> use this ! arp_idx = arp_add_mac2ip(&buffer[ETHERNET_POS_SRC_MAC], tcp_sockets[socketnum].source_ip); } ///softuart_puts_progmem("<tcp packet sent> "); //generate ip packet: ip_generate_packet(buffer, &(tcp_sockets[socketnum].source_ip), (arp_table[arp_idx].mac), tcp_sockets[socketnum].dest_port, tcp_sockets[socketnum].source_port, IP_PROTOCOL_TCP, 20+len ); //setup source port (our port) buffer[TCP_POS_SRC_PORT+0] = (tcp_sockets[socketnum].dest_port)>>8; buffer[TCP_POS_SRC_PORT+1] = (tcp_sockets[socketnum].dest_port) & 0xFF; //setup destination port (client port) buffer[TCP_POS_DST_PORT+0] = (tcp_sockets[socketnum].source_port)>>8; buffer[TCP_POS_DST_PORT+1] = (tcp_sockets[socketnum].source_port) & 0xFF; //setup seq nr: FIXME nic_seq_to_buffer(&buffer[TCP_POS_SEQ], (tcp_sockets[socketnum].seq)); /*buffer[TCP_POS_SEQ+0] = 0x00; buffer[TCP_POS_SEQ+1] = 0x00; buffer[TCP_POS_SEQ+2] = 0x00; buffer[TCP_POS_SEQ+3] = 0x00;*/ //setup ack nr: FIXME nic_seq_to_buffer(&buffer[TCP_POS_ACK], (tcp_sockets[socketnum].ack)); //setup header offset buffer[TCP_POS_DATA_OFFSET] = 0x05<<4; //setup flags: buffer[TCP_POS_HEADERFLAGS] = flags; //setup window buffer[TCP_POS_WINDOWSIZE+0] = (NIC_BUFFERSIZE-20-14)>>8; buffer[TCP_POS_WINDOWSIZE+1] = (NIC_BUFFERSIZE-20-14)&0xFF; //setup checksum -> set 0x0000, will be replaced later! buffer[TCP_POS_CHECKSUM+0] = 0x00; buffer[TCP_POS_CHECKSUM+1] = 0x00; //setup urgend pointer (not used -> 0) buffer[TCP_POS_URGENT_PTR+0] = 0x00; buffer[TCP_POS_URGENT_PTR+1] = 0x00; //calc checksum: we use some tricks to do it faster: //step0: calculate checksum for pseudoheader (0x00 TYPE TCPLEN) tmp = IP_PROTOCOL_TCP + 20 + len; //step1: calculate checksum IP_SRC+IP_DST + TCP header&data // (-2*4 -> include the 8 bytes source+dest ip) // -> we calculated the checksum over the "pseudoheder" and tcp header+data tmp = nethelp_checksum(&buffer[TCP_POS_SRC_PORT-2*4], 20+2*4 + len, tmp); //set checksum: buffer[TCP_POS_CHECKSUM+0] = tmp>>8; buffer[TCP_POS_CHECKSUM+1] = tmp & 0xFF; //send packet nic_send_packet(buffer, TCP_POS_URGENT_PTR+2+len); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -