Thread: tftpclient enhancement/modification.

  1. #1
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147

    tftpclient enhancement/modification.

    Hello all,

    My requirement is to have an API's for tftp implementation.
    Here my tftp " get call" should write the reqested file from host into the buffer which i sent to that specific API ( in my case that buffer name is testimg) call rather than storing in one of local file.

    I searched in the net for any such implementations but not with much success.

    If any body can point me / give the links that would be really help full.

    My another approach is taking one tftp client opensource and changing that according to my requriement.

    Here i chose one tftpclient opensource and changed some code in that , this works fine for less than 100k .

    If the file size is more that 1MB or so it does not give me the expected results.

    i guess one of my memory re allocation logic might be creating the problem.

    If any other approach ( rather than strncpy in my code )would be good i would welcome it .

    thanks in advance.

    Code:
    /*
     * Receive a file.
     */
    void
    recvfile(int fd, char *name, char *mode)
    {
            register struct tftphdr *ap;
            struct tftphdr *dp;
            volatile int size = 0;
            volatile u_int16_t block = 1;
            int n; 
            volatile unsigned long amount = 0;
            struct sockaddr_in from;
            socklen_t fromlen;
            volatile int firsttrip = 1;
            FILE *file;
            volatile int convert;            /* true if converting crlf -> lf */
            size_t len=0, nBufSize=0;
            char *testimg = NULL;
    
    
            startclock();
            dp = w_init();
            ap = (struct tftphdr *)ackbuf;
            file = fdopen(fd, "w");
            convert = !strcmp(mode, "netascii");
    
                    nBufSize = 8917016;
    
                    nBufSize = ((nBufSize / WSTLIB_FTP_ALLOC_UPG_SIZE) + 1)  * WSTLIB_FTP_ALLOC_UPG_SIZE;
                    testimg = (char *)malloc(nBufSize);
    
                     if ( !testimg )
                     { 
                                            printf("FtpLib: no memory\n");
                                            return ;
                     }
    
    
    
            mysignal(SIGALRM, timer);
            do {
                    if (firsttrip) {
                            size = makerequest(RRQ, name, ap, mode);
                            firsttrip = 0;
                    } else {
                            ap->th_opcode = htons((u_short)ACK);
                            ap->th_block = htons((u_short)(block));
                            size = 4;
                            block++;
                    }
                    timeout = 0;
                    (void) sigsetjmp(timeoutbuf, 1);
    send_ack:
                    if (trace)
                            tpacket("sent", ap, size);
                    if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&s_inn,
                        sizeof (s_inn)) != size) {
                            alarm(0);
                            perror("tftp: sendto");
                            goto abort;
                    }
                    write_behind(file, convert);
                    for ( ; ; ) {
                            alarm(rexmtval);
                            do  {
                                    fromlen = sizeof (from);
                                    n = recvfrom(f, dp, PKTSIZE, 0,
                                        (struct sockaddr *)&from, &fromlen);
                            } while (n <= 0);
                            alarm(0);
                            if (n < 0) {
                                    perror("tftp: recvfrom");
                                    goto abort;
                            }
                            s_inn.sin_port = from.sin_port;   /* added */
                            if (trace)
                                    tpacket("received", dp, n);
                            /* should verify client address */
                            dp->th_opcode = ntohs(dp->th_opcode);
                            dp->th_block = ntohs(dp->th_block);
                            if (dp->th_opcode == ERROR) {
                                    printf("Error code %d: %s\n", dp->th_code,
                                            dp->th_msg);
                                    goto abort;
                            }
                            if (dp->th_opcode == DATA) {
                                    volatile int j = 0;
    
                                    if (dp->th_block == block) {
                                            break;          /* have next packet */
                                    }
                                    /* On an error, try to synchronize
                                     * both sides.
                                     */
                                    j = synchnet(f);
                                    if (j && trace) {
                                            printf("discarded %d packets\n", j);
                                    }
                                    if (dp->th_block == (block-1)) {
                                            goto send_ack;  /* resend ack */
                                    }
                            }
                    }
    /*            size = write(fd, dp->th_data, n - 4); */
    /*              printf(" data %s \n",dp->th_data);*/
    /*              size = writeit(file, &dp, n - 4, convert);*/
    
    /* changed code for my requirement */
                    if((n-4) > 0)
                    {
                                      len = len + n;
    
                                      if(n == nBufSize)
                                      {
                                                                nBufSize = WSTLIB_FTP_ALLOC_UPG_SIZE / 2;
    
                                                             testimg =(int *)realloc(testimg, len + nBufSize);
    
                                                             if (testimg == NULL)
                                                             {
                                                                                    printf("FtpLib: no memory\n");
                                                                                    return;
                                                             }
                                      }
                                      else
                                                            nBufSize -= n;
                                                            strncat(testimg,dp->th_data,n-4);
                                                            printf("total img %s",testimg);
    
                    }
    /* changed code for my requirement */
    
                    if (size < 0) {
                            nak(errno + 100);
                            break;
                    }
                    amount += size;
            } while (size == SEGSIZE);
    abort:                                          /* ok to ack, since user */
            ap->th_opcode = htons((u_short)ACK);    /* has seen err msg */
            ap->th_block = htons((u_short)block);
            (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&s_inn, sizeof(s_inn));
            write_behind(file, convert);            /* flush last buffer */
            fclose(file);
            stopclock();
            if (amount > 0)
                    printstats("Received", amount);
    }

  2. #2
    {Jaxom,Imriel,Liam}'s Dad Kennedy's Avatar
    Join Date
    Aug 2006
    Location
    Alabama
    Posts
    1,065
    busybox and uboot both have tftp functions. You could rip out one of those.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Purchase a copy of Stevens' classic "UNIX Network Programming". The book has a detailed implementation of a tftp client/server alongwith the source code. It's an excellent read and a must for network programmers.

  4. #4
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    Thanks Kennedy and itCbitC for your suggestions., i got some kind of implementations my self.

    My approach is iam allocating a huge chunk of memeory in starting and writing into it instead of file.
    Any way my plan is to do dynamic allocation as and when i get from the server.

    so any ideas on that .

    thanks and regards

Popular pages Recent additions subscribe to a feed