Managing a list

Yesterday I was reading about how to implement the MatrixSSL lib in Monkey, well it's pretty easy because we have been thinking and coding lots of idea that came up in the last two months, one of this things it a better API for plug-ins, which it's the easy way to implement a new layer for networking within Monkey. Well it was that while a big doubt it came to my mind, "how can I manage the poll of Sslt types per connection?" the answer was easy, use a thread key that should be created in "coreprctx" which it's one of the part of our API for plug-ins, this should contain a list, well as a curious mind I was wondering if we should implement this with macros in C or something like that when freyes came with an idea that he has hear about a lib that does exactly that but edsiper answer that it was in the linux kernel, well, both are right uthash it's one project and the other it's a tiny header file in the kernel, of course, tiny it's better and this blog post it's about this curious implementation.

Everything start by defining something that we can call our list, something that for our example it will use the Monkey prefix:

struct mk_list {
  struct mk_list *prev, *next;
};

Yes as you can see it's tiny and you only can go forward or backward but never store something there, the magic it comes when you only store the pointer of your current position and how to go forward or backward, funny right? well it's more easy with code I think.

First we need to define at least to functions, one to initialize the first node and other to add nodes, here it's the code:

static inline void mk_list_init( struct mk_list *list ) {
  list->next = list;
  list->prev = list;
}

static inline void __mk_list_add( struct mk_list *new, struct mk_list *prev, struct mk_list *next ) {
  next->prev = new;
  new->next = next;
  new->prev = prev;
  prev->next = new;
}

static inline void mk_list_add( struct mk_list *new, struct mk_list *head ) {
  __mk_list_add( new, head->prev, head );
}

With these two function we can work with our list, I just build a tiny example with a struct that will store an incremental value in a bucle.

struct ssl_connection {
  int connection;
  struct mk_list cons;
};

void main( void ) {
  int i;
  struct mk_list *lista = (struct mk_list *) malloc(sizeof(struct mk_list *));
  struct mk_list *curr;

  struct ssl_connection *con = NULL;
  mk_list_init( lista );

  for( i = 0; i < 20; i++ ) {
    con = (struct ssl_connection *) malloc(sizeof(struct ssl_connection *));
    con->connection = (i * 10);
    mk_list_add( &con->cons, lista );
  }

  mk_list_foreach( curr, lista ) {
    con = mk_list_entry( curr, struct ssl_connection, cons );
    printf( "Connection: %d\n", con->connection );
  }
}

Well I initialize the mklist and sslconnection struct for 20 rounds I multiply the value of i for 10 and store in a sslconnection struct, but here it comes the magic, our function mklist only accept mklist struct, you can check that I just store in the "lista" the pointer of cons inside of our sslconnection, and then jump again to the begin of the for and allocate new memory for our next sslconnection. What the hell, how you suppose to get the data? well there's two define's that I haven't mention yet

#define mk_list_foreach(curr, head) for( curr = (head)->next; curr != (head); curr = curr->next )

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({                      \
      const typeof( ((type *)0)->member ) *__mptr = (ptr);      \
      (type *)( (char *)__mptr - offsetof(type,member) );})

#define mk_list_entry( ptr, type, member ) container_of( ptr, type, member )

Well three actually the mklistforeach it's a define that edsiper wanted and freyes and I didn't have any argument against :P.

The containerof it's the big magic it's explained by Greg K-H (http://www.kroah.com/log/linux/containerof.html) in a simplify way this what it does it's look for our sslconnection struct in the space of memory pointer in our current position in the list using the mklist member of sslconnection list as a reference. this will cause that by pointer arithmetic we can access the complet struct of that type with that member inside, sweet right?

Well what's the heavy point complicating with this? well there's a lot of problems with the memory when you manage a double linked list, especially because you must always create the "add" function for your specific type of struct, well with this you just create a member of that struct with the type mklist and you can manage as a double-linked list =).

Well that's isn't the only super! you can always look that the linux kernel code asking for new ideas on how to manage this kind of list, this it's a tiny example of how to use it =)

Note for me: Can I use line numbers with the BEGINSRC macro inside of org-mode?

Date: 2010-08-24 18:07:38 CLT

HTML generated by org-mode 6.30trans in emacs 23

Simple and easy captcha for Django

Last night around 4 am I was asking about how to implement a captcha within Django, I started to search in the web and found two projects, both do a great job but were too complicated to implement since you must install them and join to your project as another app, which wasn't what I was looking for.

I was looking for a function to display a captcha just calling a function, this is because I want it to use in other place of the project without any hard work. Well, after look into some graphic library I found python-gd which comes with a very practical example (which I used to create the random list of fonts), now with the library just need it to finish the idea.

1 What do I need?

Here is the list of the things I want it for my captcha:

  • Random background color
  • Random font color
  • Random angles
  • Random fonts

With all this I just create some code, obviously it was this morning not at 5am :P, here is the code:

def captcha( request ):
    fonts = [
        '/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Bold.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationMono-BoldItalic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Italic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationMono-Regular.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Bold.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSans-BoldItalic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Italic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Regular.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Bold.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-BoldItalic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Italic.ttf',
        '/usr/share/fonts/truetype/ttf-liberation/LiberationSerif-Regular.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono-Bold.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf',
        ]

    fontpath = '.'
    fontlist = dict()
    i = 0
    for f in fonts:
        if os.path.exists(f):
            fontpath = fontpath + ':' + os.path.dirname(f)
            fontlist[i] = f
            i = i + 1

    os.environ["GDFONTPATH"] = fontpath

    im = gd.image((150, 80))

    captcha_str = str( random.randint( 0, 900000))

    bg_color = im.colorAllocate(( random.randint( 200, 250 ), random.randint( 200, 250 ), random.randint( 200, 250 ) ))
    im.filledRectangle((0,0),(199,99), bg_color)

    i = 15
    for c in captcha_str:
        font_color = im.colorAllocate( (random.randint( 0, 100 ), random.randint(0,100),random.randint(0,100)) )
        font = fontlist[ random.randint( 0, len(fontlist) - 1)]
        im.string_ttf( font, 30.0, random.uniform(-0.5,0.5), (i,50), c, font_color)
        i = i + 20

    request.session['captcha_str'] = captcha_str

    str_img = cStringIO.StringIO()
    im.writePng( str_img )
    str_img.seek(0)

    response = HttpResponse()
    response['Content-Type'] = 'image/png'
    response.write( str_img.read() )
    return response

To use this code you will need to install these packages:

# apt-get install ttf-dejavu-core ttf-liberation

And the session middleware enable in your settings.py. With all this you just need to add a line into your urls.py like this:

url('^captcha.png', views.captcha),

And then call it from your template:

<img src="htt://host/captcha.png" alt="Captcha"/>

That's all, all the rest that you may need to use it just read the code =).

All this code was for a function I was going to implement in the new framework for Savannah but the idea was rejected.

Update: Some captcha images as example

captcha 1

captcha 2

captcha 3

Date: 2010-08-24 18:07:39 CLT

HTML generated by org-mode 6.30trans in emacs 23

Xapian with init script

I wrote an init script for xapian-tcpsrv that runs on CentOS ( don't ask why CentOS ) well after a few test I can say that it works just fine even with HeartBeat.

In case that you don't know xapian is a search engine that you can use with many languages, if you need a search engine just check out this great project.

#!/bin/bash
#
# chkconfig: - 91 35
# description: Starts and stops xapian-tcpsrv.
# processname: xapian-tcpsrv
# pidfile: /var/run/xapian-tcpsrv.pid

# Source function library.
. /etc/init.d/functions

PORT="12345"
DATABASE_PATH="<xapian db path>"
USER="<user to run xapian-tcpsrv>"

CONFIG="/etc/sysconfig/xapian"

[ -r "$CONFIG" ] && source "$CONFIG"

xapiantcpsrv=/usr/bin/xapian-tcpsrv
xapianargs="--port $PORT --quiet $DATABASE_PATH"
pidfile=${PIDFILE-/var/run/xapian-tcpsrv.pid}
lockfile=${LOCKFILE-/var/lock/subsys/xapian-tcpsrv}
RETVAL=0

start() {
        echo -n $"Starting xapian-tcpsrv: "
        xapian-check $DATABASE_PATH > /dev/null 2>&1
        [ "$?" -eq 0 ] && daemon --user=$USER "$xapiantcpsrv $xapianargs </dev/null >/dev/null 2>&1 &" || failure $"xapiantcpsrv start"
        RETVAL=$?
        [ $RETVAL = 0 ] && touch ${lockfile}
}

stop() {
        echo -n $"Stopping xapain:"
        killproc -d 10 $xapiantcpsrv
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status $xapiantcpsrv
        RETVAL=$?
        ;;
  restart)
        stop
        start
        ;;
  condrestart)
        if [ -f ${pidfile} ] ; then
                stop
                start
        fi
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|status}"
        exit 1
esac

1 Testing LDAP server with python

I just started tiny code last saturday to test how many connections I was able to create run a search over it.

The main idea it's to create as many threads as you want and then in every thread create N connections. This worked for me pretty well.

The code use threads and the ldap python library which you can install using apt: <src lang="bash"> </src>

The other dependencies are commons so you will not need to install anything else. Here is the source code:

##
## ldap_stress.py
## Login : <zeus@lunareja.example.org>
## Started on  Sat Sep 12 17:07:19 2009 Jonathan Gonzalez V.
## $Id$
##
## Copyright (C) 2009 Jonathan Gonzalez V. <jonathan@blueplanet.cl>
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as
## published by the Free Software Foundation, either version 3 of the
## License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU Affero General Public License for more details.
##
## You should have received a copy of the GNU Affero General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##

import threading
import time
import ldap

uri="ldaps://<host>:<port>"
binddn="<binddn>"
password="<password>"
basedn="<basedn>"
ldap_filter="(&(objectClass=posixAccount)(|(uid=unixuser)(personID=1234)))"

class TestConnections( threading.Thread ):
    def __init__ (self, number):
        threading.Thread.__init__(self)
        self.number = number

    def run(self):
        time.sleep(5)
        for i in range(1, 2):
            try:
                l = ldap.initialize( uri, 1)
            except:
                print "Can't Connect ?"

            ldap.set_option( ldap.OPT_X_TLS_REQUIRE_CERT, 0 )
            ldap.set_option( ldap.OPT_NETWORK_TIMEOUT, 10 )

            try:
                l.bind_s( binddn, password )
            except ldap.SERVER_DOWN:
                print "Server down!"
            except:
                print "Otro Error!"

            try:
                r = l.search_s( basedn, ldap.SCOPE_SUBTREE, ldap_filter )
            except:
                print "Can't get results"

if __name__ == '__main__':
    for x in range (1, 20):
        test = TestConnections (x)
        test.start ()

Date: 2010-08-24 18:07:40 CLT

HTML generated by org-mode 6.30trans in emacs 23

Blogging again!

After trying OrgMode to blog I decided to keep using Muse, the decision was pretty simple, I want to use something easy and fast, OrgMode it's easy but it doesn't have the journal method to export/publish text so, that's the why… besides, this work perfectly to me!! :D

Date: 2010-08-24 18:07:41 CLT

HTML generated by org-mode 6.30trans in emacs 23

My old text browser

A few days ago I started to get angry with my browser at that time FireFox, everything started because using my laptop with GNU Emacs and FireFox was a real pain, so I took the decision of use a text browser inside of my GNU Emacs.

1 And what kind of problem can you have with this idea?

Well, let's start by saying that just a few page work well with a text browser, and Facebook isn't one of them. Yes, I started to love this new way to contact people and organize parties (which is obviously the best part!).

The big problem it's that you don't even know what the hell it's going on with the new web 2.0 and text browser, so I started to search on Google.

NOTHING, that's what I found on the web, nothing about web 2.0 and how we must deal with text browser. Well, if a web developer follow the rules we will no need too much, but what happen with sites like Facebook which have a new look that I cannot even open with my Emacs-w3m.

Almost every new web technology use what the people use to call AJAX, which it's just some Java-Scripts that use some XML to transfer information, well this it's against any text browser that you can pick up from the web!, because support so complex java-script isn't one of the aims of a text browser.

Definitely, if you want to browse a web page with the new web2.0 and that "high technology" you must start to think on spend a few megabytes of RAM. Maybe instead of give an step forward we are just doing the same as 10 years ago, try to tell the user that the web it's so useful that you cannot browse it with 100 USD computer you have to spend two or three times more if you want a "real" experience.

Bad, bad, well not so bad, I can browse EmacsWiki, any GIT repository with git-web and use Google to search!I can even read Slashdot.

Date: 2010-08-24 18:07:41 CLT

HTML generated by org-mode 6.30trans in emacs 23

GNU
GNU Emacs Emacs Muse Mode hacker emblem Play Ogg Ohloh profile for sxd
Valid XHTML 1.0 Transitional Valid CSS!