Čeština / English
Login

SVN Repository / Prohlížení

Aktuální adresář: FITkit / trunk / mcu / libs / enc28j60 /

enc28j60_tcp_fsm.c

   1  /*******************************************************************************
   2     enc28j60_tcp_fsm.c: Stavovy automat TCP
   3     Copyright (C) 2010 Brno University of Technology,
   4                        Faculty of Information Technology
   5     Author(s): Martin Musil <xmusil34 AT fit.vutbr.cz>
   6  
   7     LICENSE TERMS
   8  
   9     Redistribution and use in source and binary forms, with or without
  10     modification, are permitted provided that the following conditions
  11     are met:
  12     1. Redistributions of source code must retain the above copyright
  13        notice, this list of conditions and the following disclaimer.
  14     2. Redistributions in binary form must reproduce the above copyright
  15        notice, this list of conditions and the following disclaimer in
  16        the documentation and/or other materials provided with the
  17        distribution.
  18     3. All advertising materials mentioning features or use of this software
  19        or firmware must display the following acknowledgement:
  20  
  21          This product includes software developed by the University of
  22          Technology, Faculty of Information Technology, Brno and its
  23          contributors.
  24  
  25     4. Neither the name of the Company nor the names of its contributors
  26        may be used to endorse or promote products derived from this
  27        software without specific prior written permission.
  28  
  29     This software or firmware is provided ``as is'', and any express or implied
  30     warranties, including, but not limited to, the implied warranties of
  31     merchantability and fitness for a particular purpose are disclaimed.
  32     In no event shall the company or contributors be liable for any
  33     direct, indirect, incidental, special, exemplary, or consequential
  34     damages (including, but not limited to, procurement of substitute
  35     goods or services; loss of use, data, or profits; or business
  36     interruption) however caused and on any theory of liability, whether
  37     in contract, strict liability, or tort (including negligence or
  38     otherwise) arising in any way out of the use of this software, even
  39     if advised of the possibility of such damage.
  40  
  41     $Id$
  42  
  43  *******************************************************************************/
  44  
  45  #include "enc28j60_spi.h"
  46  #include "enc28j60_ip.h"
  47  #include "enc28j60_tcp.h"
  48  
  49  extern unsigned long dest_seq_num;
  50  extern unsigned long local_seq_num;
  51  extern unsigned long expected_ack_num;
  52  unsigned int dest_window_size;
  53  unsigned int tcp_retransmit_timer;
  54  unsigned int tcp_fsm_timer;
  55  
  56  struct ip_h* ip_header_ptr;
  57  
  58  extern struct tcp_socket socket;
  59  
  60  //************************************
  61  //TCP stavovy automat
  62  //************************************
  63  /**
  64  
  65   **/
  66  char tcp_fsm(struct tcp_h * tcp_header){
  67  
  68  	switch(socket.state){
  69  
  70  		case FSM_IDLE:
  71  				tcp_fsm_timer = SYN_TIMEOUT;
  72  			break;
  73  
  74  		//***************************************
  75  		case FSM_NOT_CONNECTED:
  76  
  77  			if(tcp_header != NULL){
  78  
  79  				if( tcp_header->flags == (TCP_SYN | TCP_ACK)){
  80  
  81  					dest_seq_num = NTOHL(tcp_header->seq_num);
  82  					dest_window_size = NTOHS(tcp_header->window_size);
  83  
  84  					//prechod do stavu SYN
  85  					tcp_retransmit_timer = MAX_RETRANSMIT;
  86  					socket.state = FSM_ESTABILISHED;
  87  					dest_seq_num++;
  88  					local_seq_num++;
  89  					expected_ack_num = local_seq_num;
  90  
  91  					tcp_retransmit_timer = MAX_RETRANSMIT;
  92  					//poslani ACK
  93  					return tcp_send_header(TCP_ACK);
  94  				}
  95  				else if( ((tcp_header->flags) & TCP_RST) > 0 ){
  96  					tcp_fsm_reset();
  97  					return -1;
  98  				}
  99  				else{
 100  					return tcp_send_header(TCP_RST);
 101  				}
 102  
 103  			}
 104  
 105  			else{
 106  				tcp_fsm_timer--;
 107  				if(tcp_fsm_timer == 0 ){
 108  					tcp_fsm_reset();
 109  				}
 110  
 111  				local_seq_num = 0;
 112  				dest_seq_num = 0;
 113  
 114  				//poslani SYN
 115  
 116  				return tcp_send_header(TCP_SYN);
 117  
 118  			}
 119  
 120  			break;
 121  
 122  		//***************************************
 123  		case FSM_LISTEN:
 124  
 125  			if(tcp_header != NULL){
 126  				//prijeti SYN paketu
 127  				if( tcp_header->flags == TCP_SYN ){
 128  
 129  					socket.dest_port = NTOHS(tcp_header->src_port);
 130  					socket.dest_ip = NTOHL(ip_header_ptr->src_ip);
 131  					dest_seq_num = NTOHL(tcp_header->seq_num);
 132  					local_seq_num = 0;
 133  					dest_window_size = NTOHS(tcp_header->window_size);
 134  
 135  					//prechod do stavu SYN
 136  					socket.state = FSM_SYN;
 137  					dest_seq_num++;
 138  
 139  					tcp_fsm_timer = SYN_TIMEOUT;
 140  					//poslani SYN_ACK
 141  					return tcp_send_header(TCP_SYN | TCP_ACK);
 142  				}
 143  				else{
 144  					return tcp_send_header(TCP_RST);
 145  				}
 146  			}
 147  
 148  			else return 0;
 149  
 150  			break;
 151  
 152  		//***************************************
 153  		case FSM_SYN:
 154  			if(tcp_header != NULL){
 155  
 156  				tcp_fsm_timer = SYN_TIMEOUT;
 157  				if( tcp_header->flags == TCP_ACK ){
 158  					local_seq_num++;
 159  
 160  					tcp_retransmit_timer = MAX_RETRANSMIT;
 161  					socket.state = FSM_ESTABILISHED;
 162  					expected_ack_num = local_seq_num;
 163  					tx_unlock(TX3);
 164  					return 0;
 165  				}
 166  				//prichod RST
 167  				if( ((tcp_header->flags) & TCP_RST) > 0 ){
 168  					tcp_fsm_reset();
 169  					return -1;
 170  				}
 171  
 172  			}
 173  
 174  			else{
 175  				tcp_fsm_timer--;
 176  				if(tcp_fsm_timer == 0 ){
 177  					tcp_fsm_reset();
 178  				}
 179  
 180  				//poslani SYN_ACK
 181  				return tcp_send_header(TCP_SYN | TCP_ACK);
 182  
 183  			}
 184  			break;
 185  
 186  		//***************************************
 187  		//spojeni navazano
 188  		case FSM_ESTABILISHED:
 189  
 190  		//***************************************
 191  		//polouzavrene spojeni - protejsek jeste smi posilat data
 192  		case FSM_HALF_OPEN:
 193  
 194  			//prichozi paket
 195  			if(tcp_header != NULL){
 196  
 197  				//preposilani paketu, druha strana nedostala ACK, poslu ACK znovu
 198  				if(HTONL(tcp_header->seq_num) < dest_seq_num){
 199  
 200  					return tcp_send_header(TCP_ACK);
 201  				}
 202  
 203  				//trideni podle flagu
 204  				switch(tcp_header->flags){
 205  
 206  					//prichozi SYN ACK  - ACK paket z 3-way handshake nebyl dorucen
 207  					case (TCP_SYN | TCP_ACK):
 208  
 209  						if(socket.state == FSM_ESTABILISHED){
 210  
 211  							return tcp_send_header(TCP_ACK);
 212  
 213  						}
 214  						else if(socket.state == FSM_HALF_OPEN){
 215  
 216  							return tcp_send_header(TCP_RST);
 217  						}
 218  						break;
 219  
 220  					case TCP_ACK:
 221  
 222  						//datova cast paketu je vetsi jak 0 -> prichozi data
 223  						if(rx_left() > 0){
 224  							if(dest_seq_num != NTOHL(tcp_header->seq_num)){
 225  								//sekvencni cisla nesedi, data nedosla v poradi, odeslu potvrzeni poslednich prijatych dat
 226  								return tcp_send_header(TCP_ACK);
 227  							}
 228  							dest_seq_num += rx_left();
 229  							//odeslani ACK
 230  							tcp_send_header(TCP_ACK);
 231  							//zavolani handleru
 232  							(*(socket.app_handler))((struct ip_h *)&ip_header_ptr,(struct tcp_h *) &tcp_header);
 233  						}
 234  
 235  						if(expected_ack_num == NTOHL(tcp_header->ack_num)){		//ACK cislo sedi, posledni paket potvrzen
 236  							tcp_retransmit_timer = MAX_RETRANSMIT;
 237  							local_seq_num = expected_ack_num;
 238  							tx_unlock(TX3);
 239  						}
 240  						//patri ke stavu FSM_HALF_OPEN - potvrzeni posledniho datoveho paketu v pripade, ze jiz byl poslan i paket FIN ACK(ten se totiz pocita za 1 bajt)
 241  						else if((socket.state == FSM_HALF_OPEN) & ((expected_ack_num - 1) == NTOHL(tcp_header->ack_num))){
 242  							tcp_fsm_timer = FIN_WAIT1_TIMEOUT;
 243  							local_seq_num = expected_ack_num - 1;
 244  							tx_unlock(TX3);
 245  						}
 246  						else{
 247  							return -1;
 248  						}
 249  
 250  
 251  						break;
 252  
 253  					//prichod RST - okamzite ukonceni spojeni
 254  					case TCP_RST:
 255  					case (TCP_RST | TCP_ACK):
 256  
 257  						tcp_fsm_reset();
 258  						return 0;
 259  
 260  
 261  					case (TCP_PSH | TCP_ACK):
 262  
 263  						//kontrola,zda ocekavane ACK cislo bylo prijato
 264  						if(expected_ack_num == NTOHL(tcp_header->ack_num)){		//ACK cislo sedi, posledni paket potvrzen
 265  							tcp_retransmit_timer = MAX_RETRANSMIT;
 266  							local_seq_num = expected_ack_num;
 267  							tx_unlock(TX3);
 268  						}
 269  						//patri ke stavu FSM_HALF_OPEN - potvrzeni posledniho datoveho paketu v pripade, ze jiz byl poslan i paket FIN ACK(ten se totiz pocita za 1 bajt)
 270  						else if((socket.state == FSM_HALF_OPEN) & ((expected_ack_num - 1) == NTOHL(tcp_header->ack_num))){
 271  							tcp_fsm_timer = FIN_WAIT1_TIMEOUT;
 272  							local_seq_num = expected_ack_num - 1;
 273  							tx_unlock(TX3);
 274  						}
 275  						else{
 276  							return -1;
 277  						}
 278  
 279  
 280  					case TCP_PSH:
 281  
 282  						if(dest_seq_num != NTOHL(tcp_header->seq_num)){
 283  							return tcp_send_header(TCP_ACK);
 284  						}
 285  
 286  						dest_seq_num += rx_left();
 287  
 288  						//odeslani ACK
 289  						tcp_send_header(TCP_ACK);
 290  						//zavolani handleru
 291  						(*(socket.app_handler))((struct ip_h *)&ip_header_ptr,(struct tcp_h *) &tcp_header);
 292  						break;
 293  
 294  
 295  					case (TCP_PSH | TCP_ACK | TCP_FIN):
 296  					case (TCP_FIN | TCP_ACK):
 297  
 298  						//datova cast paketu je vetsi jak 0 -> prichozi data
 299  						if(rx_left() > 0){
 300  							if(dest_seq_num != NTOHL(tcp_header->seq_num)){
 301  								//sekvencni cisla nesedi, data nedosla v poradi, odeslu potvrzeni poslednich prijatych dat
 302  								return tcp_send_header(TCP_ACK);
 303  							}
 304  							dest_seq_num += rx_left();
 305  							//zavolani handleru
 306  							(*(socket.app_handler))((struct ip_h *)&ip_header_ptr,(struct tcp_h *) &tcp_header);
 307  						}
 308  
 309  
 310  						if(expected_ack_num != NTOHL(tcp_header->ack_num)){
 311  							if( dest_seq_num == NTOHL(tcp_header->seq_num)){
 312  								//return tcp_send_header(TCP_ACK);
 313  								return -1;
 314  							}
 315  						}
 316  						else{
 317  							tcp_retransmit_timer = MAX_RETRANSMIT;
 318  							local_seq_num = expected_ack_num;
 319  							tx_unlock(TX3);
 320  						}
 321  
 322  
 323  					case TCP_FIN:
 324  
 325  						dest_seq_num++;
 326  
 327  						if(socket.state == FSM_ESTABILISHED){
 328  
 329  							socket.state = FSM_CLOSE_WAIT;
 330  							tcp_fsm_timer = CLOSE_WAIT_TIMEOUT;
 331  							expected_ack_num = local_seq_num +1;		//+1 za odesilany FIN
 332  							//odeslani FIN ACK
 333  							tcp_send_header(TCP_FIN | TCP_ACK);
 334  						}
 335  						else if(socket.state == FSM_HALF_OPEN){
 336  						//odesle posledni potvrzovaci paket
 337  							tcp_send_header(TCP_ACK);
 338  
 339  							expected_ack_num = local_seq_num;
 340  							tcp_fsm_timer = TIME_WAIT_TIMEOUT;
 341  							socket.state = FSM_TIME_WAIT;
 342  						}
 343  						break;
 344  				}
 345  			}
 346  
 347  
 348  
 349  			else{
 350  				if(socket.state == FSM_ESTABILISHED){
 351  					// preposlani nepotvrzeneho paketu
 352  					if(expected_ack_num != local_seq_num){
 353  						if(tcp_retransmit_timer-- == 0)			//paket se delsi dobu nedari dorucit - ukonceni spojeni
 354  							tcp_fsm_reset();
 355  
 356  						tx_load(TX3);
 357  						return tcp_out(local_seq_num, dest_seq_num, TCP_PSH | TCP_ACK);
 358  					}
 359  				}
 360  				else if(socket.state == FSM_HALF_OPEN){
 361  					// preposlani nepotvrzenych paketu
 362  					if(expected_ack_num != local_seq_num){
 363  
 364  						if((expected_ack_num - 1) != local_seq_num ){	//nepotvrzena data
 365  							if(tcp_retransmit_timer-- == 0)			//paket se delsi dobu nedari dorucit - ukonceni spojeni
 366  								tcp_fsm_reset();
 367  
 368  							tx_load(TX3);
 369  							tcp_out(local_seq_num, dest_seq_num, TCP_PSH | TCP_ACK);
 370  						}
 371  
 372  						//nepotvrzen FIN
 373  						tcp_fsm_timer--;
 374  						if(tcp_fsm_timer == 0 ){
 375  							tcp_fsm_reset();
 376  						}
 377  						//odeslani FIN/ACK zpravy, aktivni ukonceni spojeni
 378  						tcp_send_header(TCP_FIN | TCP_ACK);
 379  
 380  					}
 381  
 382  				}
 383  			}
 384  			break;
 385  
 386  
 387  
 388  		//***************************************
 389  		case FSM_CLOSE_WAIT:
 390  
 391  			//prichozi paket
 392  			if(tcp_header != NULL){
 393  				tcp_fsm_timer = CLOSE_WAIT_TIMEOUT;
 394  				//konec spojeni
 395  				if( tcp_header->flags == TCP_ACK){
 396  
 397  					if(expected_ack_num != NTOHL(tcp_header->ack_num)){		//ACK cislo nesedi, posledni paket nepotvrzen
 398  							return -1;
 399  						}
 400  					tcp_retransmit_timer = MAX_RETRANSMIT;
 401  					local_seq_num = expected_ack_num;
 402  					tx_unlock(TX3);
 403  
 404  					tcp_fsm_reset();
 405  					break;
 406  				}
 407  
 408  				else if( ((tcp_header->flags) & TCP_RST) > 0 ){
 409  
 410  					tcp_fsm_reset();
 411  					break;
 412  				}
 413  
 414  			}
 415  
 416  			else{
 417  				// preposlani nepotvrzeneho paketu
 418  				if(expected_ack_num != (local_seq_num + 1)){		//kvuli expected_ack_num = local_seq_num+1; ve TCP_ESTABILISHED, prijem FIN paketu
 419  					if(tcp_retransmit_timer-- == 0)			//paket se delsi dobu nedari dorucit - ukonceni spojeni
 420  						tcp_fsm_reset();
 421  
 422  					tx_load(TX3);
 423  					return tcp_out(local_seq_num, dest_seq_num, TCP_PSH | TCP_ACK);
 424  				}
 425  				else{
 426  					tcp_fsm_timer--;
 427  					if(tcp_fsm_timer == 0 ){
 428  						tcp_fsm_reset();
 429  					}
 430  					return tcp_send_header(TCP_FIN | TCP_ACK);
 431  				}
 432  			}
 433  
 434  
 435  
 436  		//***************************************
 437  		case FSM_TIME_WAIT:
 438  
 439  			//dosel paket od protejsku, musime preposlat ACK paket
 440  			if(tcp_header != NULL){
 441  
 442  				tcp_fsm_timer = TIME_WAIT_TIMEOUT;
 443  
 444  				if( ((tcp_header->flags) & TCP_RST) > 0 ){
 445  					tcp_fsm_reset();
 446  					return 0;
 447  				}
 448  				//odesle posledni potvrzovaci paket
 449  				return tcp_send_header(TCP_ACK);
 450  			}
 451  
 452  			else{
 453  				//timeout, az vyprsi,muzeme ukoncit spojeni
 454  				tcp_fsm_timer--;
 455  				if(tcp_fsm_timer == 0 ){
 456  					tcp_fsm_reset();
 457  				}
 458  			}
 459  			break;
 460  
 461  		default:
 462  				return -1;
 463  	}
 464  
 465  return 0;
 466  }
 467  
Zobrazeno: 597155x Naposledy: 27.1.2022 15:43:55