Skip to content

Using baresip as a library

Sebastian Reimers edited this page Apr 6, 2023 · 12 revisions

Baresip consists of a small core and multiple modules.

The baresip core can be compiled as libbaresip.a and used as a library from custom applications. The application must include the header file with the public API called baresip.h

Custom application

The following custom application can be used as example code for how to use libbaresip:

#include <stdint.h>
#include <stdlib.h>
#include <re.h>
#include <baresip.h>


static void signal_handler(int sig)
{
	static bool term = false;

	if (term) {
		mod_close();
		exit(0);
	}

	term = true;

	info("terminated by signal %d\n", sig);

	ua_stop_all(false);
}


static void ua_exit_handler(void *arg)
{
	(void)arg;
	debug("ua exited -- stopping main runloop\n");

	/* The main run-loop can be stopped now */
	re_cancel();
}


static void ua_event_handler(struct ua *ua, enum ua_event ev,
			     struct call *call, const char *prm, void *arg)
{
	re_printf("ua event: %s\n", uag_event_str(ev));
}


int main(int argc, char *argv[])
{
	int err;

	err = libre_init();
	if (err)
		goto out;

	err = conf_configure();
	if (err) {
		warning("main: configure failed: %m\n", err);
		goto out;
	}

	/*
	 * Initialise the top-level baresip struct, must be
	 * done AFTER configuration is complete.
	 */
	err = baresip_init(conf_config());
	if (err) {
		warning("main: baresip init failed (%m)\n", err);
		goto out;
	}

	/* Initialise User Agents */
	err = ua_init("baresip v" BARESIP_VERSION " (" ARCH "/" OS ")",
		      true, true, true);
	if (err)
		goto out;

	uag_set_exit_handler(ua_exit_handler, NULL);

	uag_event_register(ua_event_handler, NULL);

	/* Load modules */
	err = conf_modules();
	if (err)
		goto out;

	/* Main loop */
	err = re_main(signal_handler);

 out:
	if (err)
		ua_stop_all(true);

	ua_close();
        module_app_unload();
	conf_close();

	baresip_close();

	/* NOTE: modules must be unloaded after all application
	 *       activity has stopped.
	 */
	debug("main: unloading modules..\n");
	mod_close();

        re_thread_async_close();

	/* Check for open timers */
	tmr_debug();

	libre_close();

	/* Check for memory leaks */
	mem_debug();

	return err;
}

The custom application can be compiled with the following command:

$ gcc -I/usr/local/include/re -I/usr/local/include/baresip -lbaresip -lrem -lre custom.c 

And finally you can run the application with:

$ ./a.out

Making an outgoing call

To make an outgoing call you can use the ua_connect function:

    ua_connect(uag_current(), NULL, NULL, "sip:music@iptel.org", NULL, VIDMODE_OFF);

Multi-threading

If your application is using multiple threads, you must make sure that any calls to socket functions or timer functions are done properly. Baresip and libre does not have any mutex locking, so this must be done explicitly in the application.

This can be achieved in one out of two ways:

  1. Use re_thread_enter/exit around function calls

  2. Use a message queue (struct mqueue) to make sure that calls to baresip/libre are done from the re_main thread

Examples using RE lock

/*
 * The callback handler is called from the RE thread.
 */
static void ua_event_handler(struct ua *ua, enum ua_event ev,
			  struct call *call, const char *prm, void *arg)
{
	re_thread_leave();
	call_ui_function();
	re_thread_enter();
}


/*
 * This function can be called from the application's thread
 */
int application_ua_connect(void)
{
	int err;

	re_thread_enter();
	err = ua_connect()
	re_thread_leave();

	return err;
}

Example using message queue

enum {
	ID_CONNECT,
	ID_HANGUP,
	/* .. etc .. */
};


/*
 * This function is called from the RE thread. You must call mqueue_alloc
 * from the RE thread with this function handler as the argument.
 */
static void mqueue_handler(int id, void *data, void *arg)
{
	switch (id) {

	case ID_CONNECT:
		ua_connect();
		break;

	case ID_HANGUP:
		ua_hangup();
		break;
	}
}

/*
 * These functions can be called from any thread.
 */
void application_ua_connect(void)
{
	mqueue_push(mqueue, ID_CONNECT, NULL);
}


void application_ua_hangup(void)
{
	mqueue_push(mqueue, ID_HANGUP, NULL);
}

TODO: add more examples

Clone this wiki locally