Posts about spf

Official RaSPF page

Ok, time to go a little more public with this.

Here's a page for it (click on "read more") and I will ask the openspf guys to put it on the implementations list (let's see how that goes).

RaSPF on its way to release

I have been able to work some more on RaSPF and the results are encouraging.

Thanks to valgrind and test suites, I am pretty confident it doesn't leak memory, or at least, that it doesn't leak except on very rare cases.

I think I found a neat way to simplify memory management, though, and that's what I wanted to mention.

This is probably trivial for everyone reading, but I am a limited C programmer, so whenever something works unexpectedly right, I am happy ;-)

One problem with C memory management is that if you have many exit points for your functions, releasing everything you allocate is rather annoying, since you may have to do it in several different locations.

I compounded this problem because I am using exceptions (yeah, C doesn't have them. I used this).

Now not only do I have my returns but also my throws and whatever uncaught throw something I called has!

Hell, right?

Nope: what exceptions complicated, exceptions fixed. Look at this function:

bstring spf_query_get_explanation(spf_query *q, bstring spec)
{
    bstring txt=0;
    struct bstrList *l=0;
    bstring expanded=0;
    bstring result=0;
    struct tagbstring s=bsStatic("");

    try
    {
        // Expand an explanation
        if (spec && spec->slen)
        {
            expanded=spf_query_expand(q,spec,1);
            l=spf_query_dns_txt(q,expanded);

            if (l)
            {
                txt=bjoin(l,&s);
            }
            else
            {
                txt=bfromcstr("");
            }
            result=spf_query_expand(q,txt,0);
            throw(EXC_OK,0);
        }
        else
        {
            result=bfromcstr("explanation: Required option is missing");
            throw(EXC_OK,0);
        }
    }
    except
    {
        if(expanded) bdestroy(expanded);
        if(txt) bdestroy(txt);
        if(l) bstrListDestroy(l);
        on (EXC_OK)
        {
            return result;
        }
        if(result) bdestroy(result);
        throw(EXCEPTION.type,EXCEPTION.param1);
    }
}

It doesn't matter if spf_query_expand or spf_query_dns_txt throw an exception, this will not leak.

Nice, I think :-)

SPF test suite on RASPF

Here are the results as of right now:

  • Give the expected results: 82 tests
  • Give the wrong result: 48 tests
  • Give a correct but not preferred result (mostly because of SPF records and IPv6): 6 tests
  • Fail (crash): 9 tests

So, depending on how you look at it, RASPF passes between 61% and 56% of the tests.

Not bad so far :-)

Update: As of 20:52 ART, it's 105/0/35/5 and 72-76%. The bad news is that that was all the low hanging fruit, and now it gets much harder.

My SPF lib improving

It now can do a bunch of things like expanding macros and (in some cases) validating mechanisms.

I am making very heavy use of unit testing, because it's a pretty complex piece and each function needs to do exactly the right thing or everything else fails (it's pretty hard to figure out where it will fail ;-)

You can check the 947 LOC thing at http://code.google.com/p/raspf (the Code tab).

If you do check it, jeep in mind the following:

  • It uses a few libs, and they are included in the source code for simplicity.
  • I do sometimes commit code that doesn't compile
  • I do sometimes commit code that fails tests
  • You need cmake
  • I am not giving a damn about memory management right now, so don't bother worrying about leaks: everything leaks in this code. I want to make it functional first, then I can plug it one function at a time (simply by running the unit testing code with a memory checker).

Enjoy (although it's not precisely enjoyable code right now ;-)