TFTP.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:6k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * Copyright (c) 1990, 1999 Erick Engelke
  3.  */
  4. #include <rtos.h>
  5. #include <net.h>
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <time.h>
  11. #include <syslog.h>
  12. #include <tftp.h>
  13. #include <sysstat.h>
  14. #define TFTP_LOCAL_PORT 10069
  15. #define TFTP_PACKET_LEN 512 + 8
  16. /*
  17.  * get_tftp_response
  18.  *      - if TIMEOUT return -1
  19.  *      - sends multiple retries as needed in case data lost
  20.  */
  21. static int get_tftp_response( udp_Socket *out, udp_Socket *in, char *buffer, int *buflen )
  22. {
  23. #define TFTP_TIMEOUT 5 /* seconds */
  24. #define TFTP_SLEEP 20  /* milliseconds */
  25. #define TFTP_RETRIES 5
  26.     int timeout;
  27.     DWORD  timecount;
  28.     int retrycount = TFTP_RETRIES;
  29.     int templen;
  30.     if ( out == NULL )
  31.         out = in;           /* handle post-setup sockets */
  32.     timeout = TFTP_TIMEOUT * TFTP_SLEEP;
  33.     timecount = set_timeout( 1 );
  34.     sock_fastwrite( out, buffer, *buflen );
  35.     while  ((templen = sock_dataready( in )) == 0 ) {
  36.         tcp_tick( NULL );
  37. //        rt_sleep( TFTP_SLEEP );
  38. //        timeout -= TFTP_SLEEP;
  39. //        if ( timeout < 0 ) {
  40.         rt_sleep( 0 );      // give up a bit of a slice
  41.         if ( chk_timeout( timecount )) {
  42. //            timeout = TFTP_TIMEOUT * TFTP_SLEEP;
  43.             timeout = set_timeout( 1 );
  44.             if ( retrycount -- < 1 )
  45.                 return( -1 );
  46.             sock_fastwrite( out, buffer, *buflen );
  47.         }
  48.     }
  49.     sock_fastread( in, buffer, templen );
  50.     *buflen = templen;
  51.     return( 0 );
  52. }
  53. // getblock - returns received length
  54. static int getblock( char *filename, int blocknum, void *buffer )
  55. {
  56.     FILE *f;
  57.     int result = 0;
  58.     dos_enter();
  59.     f = fopen( filename, "rb");
  60.     if ( f != NULL ) {
  61.         if ( 0 == fseek( f, (blocknum - 1) * 512L, SEEK_SET ))
  62.             result = fread( buffer, 1, 512, f );
  63.         fclose( f );
  64.     }
  65.     dos_exit();
  66.     return( result );
  67. }
  68. // putblock - returns 0 on success
  69. static int putblock( char *filename, int blocknum, void *buffer, int length )
  70. {
  71.     FILE *f;
  72.     int result = 0;
  73.     dos_enter();
  74.     f = fopen( filename, "a+b");
  75.     if ( f != NULL ) {
  76.         if ( 0 == fseek( f, (blocknum - 1) * 512L, SEEK_SET ))
  77.             fwrite( buffer, 1, length, f );
  78.         else result = 3;    // disk full or alloc exceeded
  79.         fclose( f );
  80.     } else result = 3;
  81.     dos_exit();
  82.     return( result ? 3 : 0 );
  83. }
  84. int tftp( DWORD host, int op, char * file )
  85. {
  86.     udp_Socket *s, *s2;
  87.     char *buf;
  88.     int datalen;
  89.     RRQ_Packet*t;
  90.     DATA_Packet *d;
  91.     ERROR_Packet *e;
  92.     char *p;
  93.     int result;
  94.     int ongoing = 1;        /* means we are still doing stuff */
  95.     int block;
  96.     DWORD filesize;
  97.     long bytesleft;
  98.     struct stat statbuf;
  99.     int i;
  100.     s = kcalloc( sizeof( udp_Socket ), 1 );
  101.     if ( s == NULL ) return( -1 );
  102.     s2 = kcalloc( sizeof( udp_Socket ), 1 );
  103.     if ( s2 == NULL ) {
  104.         kfree(s);
  105.         return( -1 );
  106.     }
  107.     buf = kcalloc( TFTP_PACKET_LEN , 1 );
  108.     if ( buf == NULL ) {
  109.         kfree( s );
  110.         kfree( s2 );
  111.         return( -1 );
  112.     }
  113.     d = t = e = buf;
  114.     if ( op == TFTP_GET )
  115.         unlink( file );
  116.     else {
  117.         dos_enter();
  118.         i = stat( file , &statbuf );
  119.         dos_exit();
  120.         if ( i != 0 ) return -1 ;   /* file not found */
  121.         filesize = statbuf.st_size;
  122.         block = 0;
  123.     }
  124.     if (!udp_open( s, TFTP_LOCAL_PORT, host, TFTP_PORT, NULL )) {
  125.         kfree( s );
  126.         kfree( s2 );
  127.         kfree( buf );
  128.         return( -1 );
  129.     }
  130.     udp_open( s2, TFTP_LOCAL_PORT, 0, 0, NULL );
  131.     // build the file request packet
  132.     memset( buf, 0, TFTP_PACKET_LEN );
  133.     t->op2 = ( op == TFTP_PUT ) ? TFTP_WRQ : TFTP_RRQ;
  134.     strcpy( t->filename, file );
  135.     p = strchr( t->filename, 0 );
  136.     strcpy( ++p, "octet");
  137.     p = strchr( p, 0 );
  138.     datalen = p - t + 1;
  139. // sock_write( s, buf, datalen );
  140.     result = 0;
  141.     while ( 1 ) {
  142.         if ( get_tftp_response( s, s2, buf, &datalen) == -1 ) {
  143.             result = -1;
  144.             break;
  145.         }
  146.         /* we don't need original socket any more */
  147.         if ( s != NULL ) {
  148.             sock_close( s );
  149.             kfree( s );
  150.             s = NULL;
  151.         }
  152.         if ( !ongoing ) break;      /* after we have acked last packet, we quit */
  153.         if ( d->op2 == TFTP_ERROR ) {
  154.             result = -1;
  155.             break;
  156.         } else if (d->op2 == TFTP_DATA ) {
  157.             /* TFTP_GET */
  158.             datalen = datalen - sizeof( ACK_Packet );
  159.             d->op2 = TFTP_ACK;
  160.             block = intel16( d->block) ;
  161.             putblock( file, block, d->data, datalen );
  162.             /* 512 bytes means there is more to read */
  163.             if ( datalen != 512 ) {
  164.                 sock_write( s2, buf, sizeof( ACK_Packet ));
  165.                 break;
  166.             }
  167.             datalen = sizeof( ACK_Packet );
  168.         } else if ( d->op2 == TFTP_ACK ) {
  169.             /* TFTP_PUT */
  170.             if ( intel16( d->block) == block )
  171.                 block++;                /* advance, else repeat */
  172.             bytesleft = filesize - (( block - 1) * 512L);
  173.             if ( bytesleft <= 0 )   /* hit end of file */
  174.                 break;
  175.             d->op2 = TFTP_DATA;
  176.             d->block = intel16( block );
  177.             /* try to read block from disk */
  178.             i = getblock( file, block, d->data );
  179.             if ( i == 0 ) {
  180.                 result = -1;
  181.                 break;
  182.             }
  183.             datalen = sizeof( ACK_Packet ) + i;
  184.         } else {
  185.             /* error */
  186.             result = -1;
  187.             ongoing = 0;
  188.             e->op2 = TFTP_ERROR;
  189.             e->err1 = e->err2 = 0;
  190.             *e->errmsg = 0;
  191.             datalen = sizeof( ERROR_Packet );
  192.         }
  193.     } 
  194.     if ( s != NULL ) {
  195.         sock_close( s );
  196.         kfree( s );
  197.     }
  198.     sock_close( s2 );
  199.     kfree( buf );
  200.     kfree( s2 );
  201.     return( result );
  202. }