4. Writing Haka extensions

Haka has a modular architecture and you can extend it by adding your favorite module.

We provide here a Makefile to compile your source files, link your module against haka libraries and have it installed on haka target path.

Note

You are free to use your own compilation toolchain.

In the following, we will create a sample C module mymodule that exports a single function myfunc.

First, create a directory mymodule and two sub folders src and obj. In the former, create your source and header files:

mymodule
\--obj
\--src
   \--mymodule.c
   \--mymodule.h
   \--mymodule.i
\--Makefile

The source file mymodule.c must include a module structure that sets the type of the module to MODULE_EXTENSION along with other information such as the name and the author of the module:

struct module MY_MODULE = {
    type:        MODULE_EXTENSION,
    name:        L"my module",
    description: L"my module",
    api_version: HAKA_API_VERSION,
    init:        init,
    cleanup:     cleanup
};

The module code must also defines a initialization and a cleanup function that will be called when the module loads and unloads, respectively.

static int init(struct parameters args)//
{
    messagef(HAKA_LOG_INFO, L"mymodule", L"init my module");
    return 0;
}

static void cleanup()
{
    messagef(HAKA_LOG_INFO, L"mymodule", L"cleanup my module");
}

Here is the mymodule.c which defines also the myfunc function that we want to export.

Then, we have created a single header file mymodule.h That simply defines the prototype of the function myfunc.

Finally, in Haka we use SWIG to bind C functions to Lua objects. Here is the content of our swig file mymodule.i that binds the myfunc function.

Note

for more complex binding, you can have a look at C protocol modules in Haka source tree.

The last step is to compile (make) our newly created module using the following Makefile that must be created in the main module folder.

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

# Configure variables
HAKA_PATH ?= /usr
INSTALL ?= install -o root -g bin

MODULE_NAME = mymodule

SRCS = mymodule.c mymodule.i

# Haka specifics
OBJ_DIR = obj
OUT_DIR = out
SRC_DIR = src
OBJS := ${SRCS:%.i=%_lua.c}
OBJS := ${OBJS:%.c=$(OBJ_DIR)/%.o}
SRCS := ${addprefix $(SRC_DIR)/, $(SRCS)}
OUT = $(MODULE_NAME).so
BIN = $(OUT_DIR)/$(OUT)

SWIG = swig
CFLAGS = -Wall -I$(HAKA_PATH)/include/ -I$(HAKA_PATH)/include/haka/lua -I$(SRC_DIR) -fPIC -c -g
LDFLAGS = -L$(HAKA_PATH)/lib/ -lhaka -shared -Wl,-soname,$(OUT) -Wl,--defsym=luaopen_external/$(MODULE_NAME)=luaopen_$(MODULE_NAME)
SWIGFLAGS = -I$(HAKA_PATH)/include/ -lua -module $(MODULE_NAME)

$(BIN): $(OBJS)
    $(CC) $(LDFLAGS) -o $(BIN) $(OBJS)

install: $(BIN)
    $(INSTALL) -m 555 $(BIN) -D $(HAKA_PATH)/lib/haka/modules/external/$(OUT)

clean:
    rm -f $(BIN) $(OBJS)

$(OBJ_DIR):
    mkdir $(OBJ_DIR) $(OUT_DIR)

# Haka rules
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(OBJ_DIR)
    $(CC) $(CFLAGS) -o $@ $<

$(OBJ_DIR)/%_lua.c: $(SRC_DIR)/%.i $(OBJ_DIR)
    $(SWIG) $(SWIGFLAGS) -o $@ $<

.SECONDARY:

Note

You may need to adjust the HAKA_PATH variable.

Now, we are ready to use the module in haka script files. Here is a sample file that simply calls the myfunc function:

local mymodule = require('external/mymodule')
local ipv4 = require('protocol/ipv4')

haka.rule{
    hook = ipv4.events.receive_packet,
    eval = function ()
        mymodule.myfunc()
    end
}