Click here to Skip to main content
15,117,719 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I would like to use udp protocol for my bootloader ethernet update.
basically, the bootloader needs BOOTP and TFTP based on UDP protocol.

so, I need to open two sockets. one is sBOOTP, other one is sTFTP.
I have the program written in c++ which is do the similar task. I need to write my program in .NET C#. Therefore I need to pretty much understand the code provided in C++(I am new in windows application programming).

C++
unsigned long
StartBOOTPUpdate(unsigned char *pucMACAddr, unsigned long ulLocalAddr,
                 unsigned long ulRemoteAddr, char *pcFilename,
                 tfnCallback pfnCallback)
{
    unsigned long ulFileLen, ulBlockNum, ulLen, ulCount;
    unsigned char pcPacketData[700];
	char *pcFileData;
    SOCKET sBOOTP, sTFTP, sTFTPData, sUpdateSocket;
    struct sockaddr_in sAddr;
    tBOOTPPacket *pPacket;
    fd_set sDescriptors;
    TIMEVAL sTime;
    int iAddrLen;
    FILE *pFile;
    BOOL bBOOTPPacketSeen = FALSE;

    //
    // Open the file to be used as the update image.
    //
    dosomthing(); // function call to open file and buffer the content

    //
    // Create a socket for the BOOTP server.
    //
    sBOOTP = CreateSocket(ulLocalAddr, htons(BOOTP_SERVER_PORT), 1, TRUE);
    if(sBOOTP == INVALID_SOCKET)
    {
        EPRINTF(("Cannot allocate socket\n"));
        free(pcFileData);
        return(ERROR_BOOTPD);
    }

    //
    // Create a socket for the TFTP server.
    //
    sTFTP = CreateSocket(ulLocalAddr, htons(TFTP_PORT), 0, TRUE);
    if(sTFTP == INVALID_SOCKET)
    {
        EPRINTF(("Cannot allocate socket\n"));
        free(pcFileData);
        closesocket(sBOOTP);
        return(ERROR_TFTPD);
    }

    //
    // Create the socket we use to send remote firmware update magic packets.
    sUpdateSocket = CreateSocket(ulLocalAddr, htons(MPACKET_PORT), 1, FALSE);
    if(sUpdateSocket == INVALID_SOCKET)
    {
        EPRINTF(("Cannot allocate socket\n"));
        free(pcFileData);
        closesocket(sTFTP);
        closesocket(sBOOTP);
        return(ERROR_MPACKET);
    }

    //
    // Start off with no TFTP data socket.
    //
    sTFTPData = INVALID_SOCKET;

    //
    // Clear the flag that indicates that the BOOTP server should be aborted.
    //
    g_bAbortBOOTP = 0;
  
    //
    // Send an initial remote firmware magic packet.
    //
    SendFirmwareUpdateMagicPacket(sUpdateSocket, pucMACAddr);

    //
    // Loop until the BOOTP server is aborted.  Additionally, once the update
    // has completed, the server will exit on its own.
    //
    while(!g_bAbortBOOTP)
    {
        //
        // Set the file descriptor set to the currently opened sockets.
        //
        FD_ZERO(&sDescriptors);
        FD_SET(sBOOTP, &sDescriptors);
        FD_SET(sTFTP, &sDescriptors);
        iAddrLen = (sTFTP > sBOOTP) ? sTFTP : sBOOTP;
        if(sTFTPData != INVALID_SOCKET)
        {
            FD_SET(sTFTPData, &sDescriptors);
            iAddrLen = (sTFTPData > iAddrLen) ? sTFTPData : iAddrLen;
        }

        //
        // Set a timeout of 500ms.
        //
        sTime.tv_sec = 0;
        sTime.tv_usec = 500000;

        //
        // Display additional status about what type of packet we are
        // waiting on.
        //
        VPRINTF(("Waiting for packet ...\n"));

        //
        // Wait until there is a packet to be read on one of the open sockets.
        //
        if(select(iAddrLen + 1, &sDescriptors, 0, 0, &sTime) != 0)
        {
            //
            // See if there is a packet waiting to be read from the BOOTP port.
            //
            if(FD_ISSET(sBOOTP, &sDescriptors))
            {
                dosthing();
            }

            //
            // See if there is a packet waiting to be read from the TFTP port.
            //
            if(FD_ISSET(sTFTP, &sDescriptors))
            {
                dosthing();
            }

            //
            // See if there is a packet waiting to be read from the TFTP data
            // port.
            //
            if((sTFTPData != INVALID_SOCKET) &&
               FD_ISSET(sTFTPData, &sDescriptors))
            {
                dosthing();
            }
        }
        else
        {
           dosthing(); 
        }
    }
    //
    // Close the sockets.
    //
    VPRINTF(("Closing network connections\n"));
    closesocket(sTFTPData);
    closesocket(sTFTP);
    closesocket(sBOOTP);
    closesocket(sUpdateSocket);

    //
    // Return success.
    //
    return(ERROR_NONE);
}


Please ignore all the dosthing() function. by look at the code my question is the following part of code:

C++
//
        // Set the file descriptor set to the currently opened sockets.
        //
        FD_ZERO(&sDescriptors);
        FD_SET(sBOOTP, &sDescriptors);
        FD_SET(sTFTP, &sDescriptors);
        iAddrLen = (sTFTP > sBOOTP) ? sTFTP : sBOOTP;
        if(sTFTPData != INVALID_SOCKET)
        {
            FD_SET(sTFTPData, &sDescriptors);
            iAddrLen = (sTFTPData > iAddrLen) ? sTFTPData : iAddrLen;
        }

how can code compare sTFTP > sBOOTP, if true assign sTFTP to iAddrLen, false, assign sBOOTP to iAddrLen. I know sTFTP and sBOOP is defined as SOCKET. can it compare this way? I dont understand what is SOCKET. is SOCKET a struct? I could not get reference from winsock2.

can someone give some hint?

Thanks in advance
Posted
Comments
Garth J Lancaster 7-Feb-14 17:47pm
   
are not sFFTP and sBOOTP just 'structs' - so the comparison is comparing [maybe] the length of those structs as dependent on their content

[edit] it appears SOCKET in win32 is just a Handle, which is .. an integer used to refer to a kernel data structure [/edit]
Garth J Lancaster 7-Feb-14 17:53pm
   
you should be able to verify whats going on if you add some breakpoints and step through your c++ version, btw, inspecting the types and values of each 'variable'

1 solution

iAddrLen is not a length. It is a badly named variable.
It is a Socket descriptor, but they use it as an indirect counter of number of sockets.

A SOCKET is just an integer.

Select can be used to look if one can read or write to sockets.
This implementation of select has 5 parameters
Number of sockets in the arrays (in total)
An array of sockets available for reads
An array of sockets available for writes
An array of sockets which should be checked for errors.
And a timeout


What they are actually doing is finding the SOCKET with the highest number.
I think the socket numbers may be consecutive.
So it is indirectly a counter, where the first socket starts with 0.
Hence the +1.
The INVALIDSOCKET is probably -1 if I remember correctly.

In this case, for three sockets. The parameter should be 3.
But nothing bad will happen if it is bigger.

According to the MSDN API, the first parameter is ignored.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx[^]


FDSET just assigns the array.
A call to select sets the appropriate flags in the array.

What you should concentrate on is the FD_SET FD_ISSET

Select is a way to multitask over an array of sockets.
You can keep the number of working threads to a minimum with select.
If you call Select with timout equal to NULL, it means that it will be a non blocking call.
Very practical indeed.

In .Net you should probably not use this sort of mechanism.
You can probably register some kind of event to get a callback,
or use an asynchronous model with BeginReceive and EndReceive,
or use the new Async model which is available in Net 4.5
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900