简体   繁体   中英

Sending TFTP packets in C++

I am relatively new to C++, so please forgive my lack of knowledge. I need help regarding TFTP packets. Below is the code I am using to generate a WRQ (write request package) and DATA packet which will be sent to a designated server.

bool createWRQ(char * filename)  {
  /*  structure is the same as RRQ  */
  clear();
  addWord(TFTP_OPCODE_WRITE);
  addString(filename);
  addByte(0);
  addString(TFTP_DEFAULT_TRANSFER_MODE);
  addByte(0);
  return true;
}

bool createData(int block, char * mData, int data_size)  {
  /*      2 bytes    2 bytes       n bytes
  ----------------------------------------
   DATA  | 03    |   Block #  |    Data    |
  ---------------------------------------- */

  clear();                     // to clean the memory location
  addWord(TFTP_OPCODE_DATA);
  addWord(block);
  addMemory(mData, data_size);
  return true;
}

I will include the declarations and required functions.

#include "stdafx.h"
#include "WebComm.h"
#include "WebCommDlg.h"
#include <stdio.h>
#include <stdlib.h>
#include "visa.h"
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winsock.h>
#include <string.h>
#include <string>
#include <fstream>
#include <cstdio>
#include <cerrno>

int      mCurPacketSize = 512;
char     mData[512]; 

#define VIBUF_LEN 255

#define TFTP_OPCODE_READ     1
#define TFTP_OPCODE_WRITE    2
#define TFTP_OPCODE_DATA     3
#define TFTP_OPCODE_ACK      4
#define TFTP_OPCODE_ERROR    5

#define cTFTPPacket_MAX_SIZE 1024
#define cTFTPPacket_DATA_SIZE 512
#define TFTP_DEFAULT_TRANSFER_MODE "octet" //"netascii", "octet", or "mail"

typedef unsigned char BYTE;
typedef unsigned short WORD;    



bool addByte(BYTE b) {
  if(mCurPacketSize >= cTFTPPacket_MAX_SIZE)
    return false;
  mData[mCurPacketSize] = (unsigned char)b;
  mCurPacketSize++;
  return true;
}


bool addWord(WORD w)  {
    w = htons(w);
  if(!addByte(*(((BYTE*)&w)+1))) 
    return false;
  return !addByte(*((BYTE*)&w));
}

bool addString(char * str)  {
  int n = strlen(str);
  for(int i=0; i<n; i++)
    if(!addByte(str[i])) 
      return false;
  return true;
}



bool addMemory(char * buffer, int len)  {
  bool oStatus = false;

  if(mCurPacketSize + len >= cTFTPPacket_MAX_SIZE)   {
    AfxMessageBox("Packet max size exceeded");
    return false;
  } else {
    memcpy(mData + mCurPacketSize), buffer, len);
    mCurPacketSize += len;
    return true;
  }
}


void clear() {
  mCurPacketSize = 0;
  memset(mData, mCurPacketSize, cTFTPPacket_MAX_SIZE);
}

I am aware these function have been declared mostly as type bool, however I need to send a WRQ packet to the server and wait for an ACK response before sending a DATA packet.

Something along the lines of:

while(/* something */)
  if(!sendto(socket, WRQ, 512, NULL, (sockaddr*)&Addr, sizeof(struct sockaddr_in)))){
     if(!recvfrom(socket, ACK, /* ... */))
         sendto(socket, DATA_Packet, 512, NULL, (sockaddr*)&Addr, sizeof(struct sockaddr_in))));

My question is: how can I modify the createWRQ() and createData() functions so that I can return them as packets to use for transmission, since bool only returns true or false as 1 or 0. I need to be able to send them using the winsock send and receive functions. Apologies for the silly question. If anyone could point me in the right direction I would greatly appreciate it.

your whole approach has a few issues...

  1. When you create your packets relying on functions like

     bool addByte(BYTE b) 

    they use global variables

     mCurPacketSize, mData 

    that's not good. You could use instead something on these lines

     int addByte(char* Pkt, int PktIdx, BYTE b) { if (PktIdx > cTFTPPacket_MAX_SIZE) { return 0; } Pkt[PktIdx] = (unsigned char)b; PktIdx++; return PktIdx; } 

then you know that Pkt is always the head of your packet and PktIdx is either the place for a new byte (or string) and "also" the size of the packet.

  1. When you create packets that have a fixed length structure (or a fixed length header followed by a variable length payload area) it is a good idea to represent the fixed length area with a "packed" (pay attention to memory alignment) C/C++ structure and then populate the structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM