Domanda

Context: I'm writing a sort of non-trivial client-server UDP multicast program that I'm deploying on some wireless nodes. The means of deployment is a script I wrote that broadcast pings the network that these nodes sit on, gets a list of the nodes (based on IP addresses), deploys my package, and installs it. It has come to my attention that sometimes not all the nodes are detected at the time of deployment, and the most current package I'm developing is not installed. Ultimately, it can be the case in which the server running on one node is older than a client who wishes to communicate with the server. Because the server gets packets, and allocates memory depending on entries in this packet, if the structure changes, the server usually crashes in a segfault. As a solution, I'm thinking about implementing version numbers in the packets that get sent between client and server such that if the server/client reads a packet in which the version number isn't the same (or is garbage because of restructuring of packets), this packet gets ignored, and a log is updated, or an emergency packet is sent to the original sender.

So, I'm trying to come up with the best way of getting this "version number" at compile time that can sit in a header as a #define. I've looked up the __time__ preprocessor macro, but this is in the form of a string. Is there a way to get the epoch time during compile time so that I can bitmask it into an unsigned int (which should only roll over after 136 years, if I'm thinking about this correctly)?

Sorry if I'm being unclear.

È stato utile?

Soluzione

It depends on your build system, but if you're using gmake, you can do something like:

CXX_TIME = -DBUILDTIME=$(shell python -c "import time; print( int( time.time() ) )" )

Add this into your other compiler options, and then use the macro BUILDTIME in your code.

(This supposes that you've got Python installed in your path. If not, you can either install it, or do something similar with a tool you have installed.)

Altri suggerimenti

You can get the epoch from the __DATE__ preprocessor macro.

Below the getCompileTimeEpoch() function, which in turn depends on two other simple auxiliary functions that return the month number and another one to switch the month acronym to lower case.

It puzzles me how GCC developers have introduced a macro with a human readable date and not with an epoch, from which anything else about a date can be derived with maximum reliability.

You may very easily add the time from the __TIME__ macro, should you need it added to the epoch.

I opted for this solution, as it keeps everything inside the code and does not depend on compiler options.

char *tolowercase(char *letstr){
    int l;
    for(l=0;l<=strlen(letstr);l++){
        if(letstr[l]>=65 && letstr[l]<=92){
            letstr[l]=letstr[l]+32;
        }
    }
    return letstr;
}

int getMonFromAbbr(char *abbr){
    if (strlen(abbr) > 0)
        tolowercase(abbr);
    if ( strcmp(abbr, "jan") == 0 )
        return 0;
    if ( strcmp(abbr, "feb") == 0 )
        return 1;
    if ( strcmp(abbr, "mar") == 0 )
        return 2;
    if ( strcmp(abbr, "apr") == 0 )
        return 3;
    if ( strcmp(abbr, "may") == 0 )
        return 4;
    if ( strcmp(abbr, "jun") == 0 )
        return 5;
    if ( strcmp(abbr, "jul") == 0 )
        return 6;
    if ( strcmp(abbr, "aug") == 0 )
        return 7;
    if ( strcmp(abbr, "sep") == 0 )
        return 8;
    if ( strcmp(abbr, "oct") == 0 )
        return 9;
    if ( strcmp(abbr, "nov") == 0 )
        return 10;
    if ( strcmp(abbr, "dec") == 0 )
        return 11;
    return(-1);
}

// Convert from __DATE__ macro
uint64_t getCompileTimeEpoch(){
    char date_macro[20]="";
    strcpy(date_macro, __DATE__);
    char *token;
    int yea=0;
    int mon=0;
    int day=0;
    token=strtok(date_macro, " ");
    if (token != NULL){
        mon=getMonFromAbbr(token);
        token=strtok(NULL, " ");
        if (token != NULL){
            day=atoi(token);
            token=strtok(NULL, " ");
            if (token != NULL){
                yea=atoi(token);
                struct tm t;
                time_t epoch_t;
                t.tm_year = yea-1900;    // Year - 1900
                t.tm_mon = mon;          // Month, where 0 = jan
                t.tm_mday = day;         // Day of the month
                t.tm_hour = 0;
                t.tm_min = 0;
                t.tm_sec = 0;
                t.tm_isdst = 0;         // Is DST on? 1 = yes, 0 = no, -1 = unknown
                epoch_t = mktime(&t);               
                return epoch_t;
            }           
        }
    }
    return(-1);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top