0
            uint32_t ip=time_count.rbegin()->first;
            clientAddress=ip_to_struct.find(ip)->second;
            for(auto i=time_count.begin();i!=time_count.end();i++){
                i->second+=timeOut_int-time_count.rbegin()->second;
            }
            time_count.erase(ip);
            time_count.insert(std::pair<uint32_t,int> (ip,0));
            }
            char buff[MAX_WRQ_SIZE];
            /*int recievedOPcode = */if(recvfrom(udp_fd, buff,MAX_WRQ_SIZE, 0,
            (struct sockaddr *) &clientAddress, &sockLen)<0){
            perror("TTFTP_ERROR4");
            exit(1);
            }
            if (strlen(buff)>0){
                for(int i =0;i<MAX_WRQ_SIZE;i++){
                cout<<"the buff cont is "<<buff[i]<<endl;
                }
            }
            else{
                cout<<"the buff is empty or worse"<<endl;
            }
            cout<<"buff is "<<buff;
            char opCodeChar[2];
            memcpy(opCodeChar,buff,2);
            if(atoi(opCodeChar)==WRQ_OPCODE){
                recieve_WRQ(buff,udp_fd,clientAddress);
            }
            else if(atoi(opCodeChar)==DATA_OPCODE){
                recieve_DATA(buff,udp_fd,clientAddress);
            }
            else{
                ERROR send_err_msg =
                {htons(ERROR_OPCODE), htons(4), "Illegal TFTP operation"};
                if(sendto(udp_fd, &send_err_msg, MAX_PACKET, 0,
                (struct sockaddr *) &clientAddress,
                sizeof(clientAddress)) <0){
                    cout<<"client address<0"<<endl;
                    perror("TTFTP_ERROR6");
                }
            }

        }

So basically I get "the buff is empty or worse" even though the return value of recvfrom is positive.

edit: basically what interests me is why the buffer appears empty. I have edited the code to include the line where I try to read from the buffer. when I print I get nothing (empty). What can I do?

Micha Blum
  • 15
  • 5
  • How do you know that `recvfrom()` returns a *positive* result, as opposed to 0? – John Bollinger Jan 28 '22 at 14:07
  • From the commented out int variable – Micha Blum Jan 28 '22 at 14:16
  • You get no information from a comment, and there is no sign in the code presented of how your program would distinguish 0 from >0 in a case where you record `recvfrom`'s return value in a variable. We don't answer debugging questions about code we can't see. – John Bollinger Jan 28 '22 at 14:20
  • Of course I get no info from a comment, I am just telling you that I commented it out, before commenting it out I printed it's value and saw it is 20 – Micha Blum Jan 28 '22 at 14:25

1 Answers1

3
        if (strlen(buff)>0){

strlen does not give the size of the buffer. It gives the number of bytes until the first \0 byte. Especially with binary data \0 bytes are pretty common in the middle of data. And there might even no \0 at all in the transmitted data - for example if only the characters of a string are transmitted (i.e. strlen bytes) but not a final \0. In this check might return a length larger than the actual data or might crash because unmapped memory is accessed.

To get the size of the transmitted data check the return code of recvfrom instead.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • True, but if the OP is expecting a message that starts with at least one non-zero byte, then `strlen(buff)>0` evaluating to 0 still indicates that they did not successfully receive what they expected. – John Bollinger Jan 28 '22 at 14:09
  • @JohnBollinger: *"if the OP is expecting a message that starts with at least one non-zero byte"* - true, but it is unknown if the OP is expecting this. It is totally unknown what the OP is actually expecting, except "something". – Steffen Ullrich Jan 28 '22 at 14:10
  • You are correct: I have given a hypothetical. I think the condition is pretty likely to hold, especially given that the OP chose the `strlen` test in the first place, but I can't say for sure. – John Bollinger Jan 28 '22 at 14:13
  • As you can see from the commented out int variable, I did check the return value, it is 20. I try passing a WRQ request... – Micha Blum Jan 28 '22 at 14:15
  • @MichaBlum, if the `recvfrom()` call returns 20 then that's how many bytes were received and stored in the buffer. Whether they are the bytes you *expected* to receive is a different question. Note also that `recvfrom()` does not add a null terminator, so you cannot rely on there being one to terminate the data as a string unless the sender included one in the message. – John Bollinger Jan 28 '22 at 14:26
  • Ultimately, "*To get the size of the transmitted data check the return code of `recvfrom` instead*" is the answer to the question posed. – John Bollinger Jan 28 '22 at 14:29
  • Okay so I have edited my question to be more on point – Micha Blum Jan 28 '22 at 18:49
  • @MichaBlum: there is no need to change the answer after your edit: you are assuming that what you received is a number of characters followed by \0. Only in this case you could treat it as a string and use strlen on it. This assumption is likely wrong. I must say "likely" though since nothing is known about the actual data transmitted, all we know is the code you use to receive. But given that recvfrom returns 20 (based on your comment) and strlen returns 0 you must have received 20 bytes which start with \0. – Steffen Ullrich Jan 28 '22 at 19:06
  • As a general rule, you can't trust the sender to NUL-terminate the data he sends. (i.e. even if you can trust *your own* sending program to do so, you can trust that some other program won't accidentally or intentionally send a non-NUL-terminated UDP packet to your program's port). (You *can* guarantee it on the receiving side, though, by calling `recvfrom()` with `bufSize-1` as the size argument, and doing a `buf[numBytesRead]='\0';` after any successful `recvfrom()` call) – Jeremy Friesner Jan 28 '22 at 19:16