FITkit
Fakulta informačních technologií

enc28j60_tcp.c

Zobrazit dokumentaci tohoto souboru.
00001 /*******************************************************************************
00002    enc28j60_tcp.c: Transportní vrstva modelu TCP/IP
00003    Copyright (C) 2010 Brno University of Technology,
00004                       Faculty of Information Technology
00005    Author(s): Martin Musil <xmusil34 AT fit.vutbr.cz>
00006 
00007    LICENSE TERMS
00008 
00009    Redistribution and use in source and binary forms, with or without
00010    modification, are permitted provided that the following conditions
00011    are met:
00012    1. Redistributions of source code must retain the above copyright
00013       notice, this list of conditions and the following disclaimer.
00014    2. Redistributions in binary form must reproduce the above copyright
00015       notice, this list of conditions and the following disclaimer in
00016       the documentation and/or other materials provided with the
00017       distribution.
00018    3. All advertising materials mentioning features or use of this software
00019       or firmware must display the following acknowledgement:
00020 
00021         This product includes software developed by the University of
00022         Technology, Faculty of Information Technology, Brno and its
00023         contributors.
00024 
00025    4. Neither the name of the Company nor the names of its contributors
00026       may be used to endorse or promote products derived from this
00027       software without specific prior written permission.
00028 
00029    This software or firmware is provided ``as is'', and any express or implied
00030    warranties, including, but not limited to, the implied warranties of
00031    merchantability and fitness for a particular purpose are disclaimed.
00032    In no event shall the company or contributors be liable for any
00033    direct, indirect, incidental, special, exemplary, or consequential
00034    damages (including, but not limited to, procurement of substitute
00035    goods or services; loss of use, data, or profits; or business
00036    interruption) however caused and on any theory of liability, whether
00037    in contract, strict liability, or tort (including negligence or
00038    otherwise) arising in any way out of the use of this software, even
00039    if advised of the possibility of such damage.
00040 
00041    $Id$
00042 
00043 *******************************************************************************/ 
00044 
00045 #include "enc28j60_spi.h"
00046 #include "enc28j60_eth.h"
00047 #include "enc28j60_ip.h"
00048 #include "enc28j60_tcp.h"
00049 
00050 
00051 unsigned long dest_seq_num = 0;
00052 unsigned long local_seq_num = 0;
00053 unsigned long expected_ack_num = 0;
00054 
00055 struct ip_h* ip_header_ptr;
00056 
00057 extern unsigned long local_ip;
00058 extern unsigned int tcp_fsm_timer;
00059 
00060 struct tcp_socket socket;
00061 
00062 
00066 void tcp_recv(struct ip_h* ip_header){
00067 
00068         struct tcp_h tcp_header;
00069         
00070         if(rx_read(&tcp_header, TCP_HEADER_LEN) != TCP_HEADER_LEN)
00071                 return;
00072                 
00073         //port filtr
00074         if( HTONS(tcp_header.dest_port) != socket.src_port)
00075                 return; 
00076                 
00077         //IP filtr
00078         if(socket.state != FSM_LISTEN){
00079                 
00080                 if(socket.dest_port != NTOHS(tcp_header.src_port))
00081                         return;
00082                 
00083                 if(socket.dest_ip != NTOHL(ip_header->src_ip))
00084                         return;
00085         }       
00086         
00087         //pokud je hlavicka delsi nez obvyklych 20B (volitelne polozky), zahodime je
00088         if( ( ((unsigned char)tcp_header.data_offset) <<2) > TCP_HEADER_LEN){           //header_len *4
00089                 rx_skip ( ( ((unsigned char)tcp_header.data_offset) <<2) - TCP_HEADER_LEN);
00090         }
00091                         
00092         ip_header_ptr = ip_header;      
00093 
00094         //volani konecneho automatu
00095         tcp_fsm(&tcp_header);
00096         
00097 return; 
00098 }
00099 
00100 
00101 
00105 char tcp_send(){
00106         
00107         if(tcp_connected()){
00108                 tx_seek(TCP_HEADER);
00109                 tx_save(TX3);
00110                 expected_ack_num = local_seq_num + tx_data_len() - TCP_HEADER_LEN;      
00111                 
00112                 if(tcp_fsm(NULL) == -1){
00113                         return -1;
00114                 }
00115                 else{
00116                         return 0;
00117                 }
00118         }
00119 return -1;
00120 }
00121 
00122 
00126 char tcp_out(unsigned long seq, unsigned long ack, unsigned char flags){
00127 /*
00128         if(!link_up())                  //kabel odpojen,nebudeme odesilat
00129                 return -1;
00130 */
00131         struct tcp_h tcp_header;
00132 
00133         tcp_header.src_port = HTONS(socket.src_port);
00134         tcp_header.dest_port = HTONS(socket.dest_port);
00135         tcp_header.seq_num = HTONL(seq);
00136         
00137         if((flags & TCP_ACK) != 0)
00138                 tcp_header.ack_num = HTONL(ack);
00139         else
00140                 tcp_header.ack_num = 0;
00141                 
00142         tcp_header.reserved = 0;
00143         tcp_header.data_offset = TCP_HEADER_LEN >> 2;
00144         tcp_header.flags = flags;
00145         tcp_header.window_size = HTONS(WINDOW_SIZE);
00146         tcp_header.checksum = 0;
00147         tcp_header.urgent_ptr = 0;
00148                 
00149         tx_seek(TCP_HEADER);
00150         tx_write(&tcp_header, TCP_HEADER_LEN);
00151 
00152         tx_seek(TCP_HEADER);
00153         tcp_header.checksum = HTONS(tcp_checksum(socket.dest_ip, tx_data_len()));
00154                 
00155         tx_write(&tcp_header, TCP_HEADER_LEN);
00156         
00157         
00158 
00159 return ip_send(socket.dest_ip,IP_PROTO_TCP);    
00160 }
00161 
00162 
00166 unsigned int tcp_checksum(unsigned long dest_ip,unsigned int length){
00167 
00168         unsigned long sum = 0;
00169         unsigned int* ptr;
00170         
00171         ptr = (unsigned int*)&local_ip;
00172         sum += *ptr;
00173         ptr++;
00174         sum += *ptr;
00175         
00176         ptr = (unsigned int*)&dest_ip;
00177         sum += *ptr;
00178         ptr++;
00179         sum += *ptr;
00180         
00181         sum += IP_PROTO_TCP;
00182         sum += length;  
00183         
00184         sum += (unsigned int) ~tx_checksum();
00185         
00186         while(sum >>16)
00187                 sum = (sum & 0xFFFF) + (sum >> 16);
00188 
00189 return (unsigned int) ~sum;
00190 }
00191 
00195 char tcp_send_header(unsigned char flags){
00196         
00197         if( tx_init(TCP_PROTO_HEADER_ONLY) < 0)
00198                 return -1;
00199         tx_close();
00200         
00201 return tcp_out(local_seq_num,dest_seq_num, flags);
00202 }
00203 
00207 void tcp_fsm_reset(){
00208         
00209         tx_unlock(TX3);
00210         
00211         if(socket.type == TCP_SERVER)
00212                 socket.state = FSM_LISTEN;      
00213         else    
00214                 socket.state = FSM_IDLE;
00215 }
00216 
00221 unsigned char create_tcp_socket(unsigned int src_port, void* handler){
00222                 
00223         if(src_port != 0){
00224                 socket.src_port = src_port;
00225                 socket.app_handler = handler;
00226                 socket.state = FSM_IDLE;
00227                 return src_port;
00228         }
00229         else 
00230                 return 0;       
00231 }
00232 
00238 char delete_tcp_socket(){
00239 
00240         if(tcp_is_idle()){
00241                 socket.src_port = 0;
00242                 socket.app_handler = NULL;
00243                 socket.state = FSM_IDLE;
00244                 return 0;
00245         }       
00246         else 
00247                 return -1;
00248 }
00249 
00250 
00254 void change_tcp_handler(void* new_handler){
00255         
00256         socket.app_handler = new_handler;
00257         
00258 return; 
00259 }
00260 
00264 char tcp_connect(unsigned long ip, unsigned int port){
00265         
00266         if(socket.state == FSM_IDLE){
00267         socket.dest_ip = ip;
00268         socket.dest_port = port;
00269         socket.state = FSM_NOT_CONNECTED;
00270         socket.type = TCP_CLIENT;
00271         tcp_fsm(NULL);
00272         return 0;
00273         }
00274         else return -1;
00275 }
00276 
00280 char tcp_bind(){
00281         
00282         if((socket.state == FSM_IDLE) | ( socket.state == FSM_LISTEN)){
00283                 socket.state = FSM_LISTEN;
00284                 socket.type = TCP_SERVER;
00285                 return 1;
00286         }
00287         
00288 return 0;
00289 }
00290 
00294 char tcp_unbind(){
00295         if(( socket.state == FSM_LISTEN)){
00296                 socket.dest_port = 0;
00297                 socket.state = FSM_IDLE;
00298                 socket.type = TCP_SERVER;
00299                 return 1;
00300         }
00301 return 0;
00302 }
00303 
00307 inline void tcp_disconnect(){
00308         if(socket.state == FSM_ESTABILISHED){
00309                 tcp_fsm_timer = FIN_WAIT1_TIMEOUT;
00310                 socket.state = FSM_HALF_OPEN;
00311                 expected_ack_num++;                             //+1 za FIN
00312                 tcp_fsm(NULL);
00313         }
00314 }
00315 
00319 char tcp_connected(){
00320         
00321         if(socket.state == FSM_ESTABILISHED)
00322                 return 1;
00323                 
00324 else return 0;
00325 }
00326 
00330 char tcp_is_idle(){
00331         
00332         if((socket.state == FSM_IDLE) | ( socket.state == FSM_LISTEN)){
00333                 return 1;
00334         }
00335         
00336 return 0;
00337 
00338 }
00343 inline void tcp_timer(){
00344 
00345 tcp_fsm(NULL);  
00346 }