initial demo program working with libcapi20 + capiconn

doesn't do anything but accept incoming calls and log debug output
This commit is contained in:
Harald Welte 2022-04-15 16:52:46 +02:00
parent 8bfbcf6d86
commit 1751d4b827
4 changed files with 281 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
capi-test

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
LIBS = -lasan
CFLAGS = -g -Wall
LIBS += $(shell pkg-config --libs talloc libosmocore capi20)
CFLAGS += $(shell pkg-config --cflags talloc libosmocore capi20)
all: capi-test
clean:
@rm -f *.o capi-test
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $^
capi-test: capi.o capiconn.o
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)

261
capi.c Normal file
View File

@ -0,0 +1,261 @@
#include <malloc.h>
#include <errno.h>
#include <talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/select.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/application.h>
#include <capi_debug.h>
#include "capiconn.h"
#define CM(x) (1<<(x))
#define CIPMASK_ALL 0x1FFF03FF
#define CIPMASK_VOICE (CM(1)|CM(4)|CM(5)|CM(16)|CM(26))
#define CIPMASK_DATA (CM(2)|CM(3))
enum log_subsys {
DLCAPI20,
DCAPI,
};
static void *tall_capi_ctx;
struct capi_inst {
unsigned int applid;
capiconn_context *cc_ctx;
struct osmo_fd ofd;
};
static const char *conninfo(capi_connection *p)
{
static char buf[1024];
capi_conninfo *cp = capiconn_getinfo(p);
char *callingnumber = "";
char *callednumber = "";
if (cp->callingnumber && cp->callingnumber[0] > 2)
callingnumber = (char *) cp->callingnumber+3;
if (cp->callednumber && cp->callednumber[0] > 1)
callednumber = (char *) cp->callednumber+2;
snprintf(buf, sizeof(buf),
"\"%s\" -> \"%s\" %s (pcli=0x%x/ncci=0x%x)",
callingnumber, callednumber,
cp->isincoming ? "incoming" : "outgoing",
cp->plci, cp->ncci
);
buf[sizeof(buf)-1] = 0;
return buf;
}
/***********************************************************************
* capiconn call-backs
***********************************************************************/
static void *cb_malloc(size_t size)
{
return talloc_size(tall_capi_ctx, size);
}
static void cb_free(void *buf)
{
talloc_free(buf);
}
static void cb_disconnected(capi_connection *cp, int localdisconnect, unsigned reason, unsigned reason_b3)
{
LOGP(DCAPI, LOGL_DEBUG, "%s(local=%d, reason=0x%4x, reason_b3=0x%x)\n", __func__, localdisconnect, reason, reason_b3);
}
static void cb_incoming(capi_connection *cp, unsigned contr, unsigned cipvalue, char *called, char *calling)
{
printf("incoming call: %s (0x%x) %s -> %s\n", conninfo(cp), cipvalue, calling, called);
/* we should call capiconn_{accept,ignore,reject} */
if (1) {
capiconn_accept(cp, 1, 1, 0, 0, 0, 0, 0);
} else
capiconn_ignore(cp);
}
static void cb_connected(capi_connection *cp, _cstruct NCPI)
{
printf("connected: %s\n", conninfo(cp));
}
/* user plane data received */
static void cb_datareceived(capi_connection *cp, unsigned char *data, unsigned int len)
{
LOGP(DCAPI, LOGL_DEBUG, "%s(%p, %u)\n", __func__, data, len);
}
/* sent user plane data was confirmed */
static void cb_datasent(capi_connection *cp, unsigned char *data)
{
LOGP(DCAPI, LOGL_DEBUG, "%s(%p)\n", __func__, data);
}
/* capiconn wants to issue a CAPI_PUT_MESSAGE */
static void cb_put_message(unsigned int appid, unsigned char *msg)
{
int rc;
//LOGP(DCAPI, LOGL_DEBUG, "%s(%u)\n", __func__, appid);
rc = capi20_put_message(appid, msg);
if (rc)
fprintf(stderr, "capi20_put_message: %s\n", capi_info2str(rc));
}
static void cb_debugmsg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
osmo_vlogp(DCAPI, LOGL_DEBUG, __FILE__, __LINE__, 0, fmt, ap);
va_end(ap);
LOGPC(DCAPI, LOGL_DEBUG, "\n");
}
static void cb_infomsg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
osmo_vlogp(DCAPI, LOGL_INFO, __FILE__, __LINE__, 0, fmt, ap);
va_end(ap);
LOGPC(DCAPI, LOGL_INFO, "\n");
}
static void cb_errmsg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
osmo_vlogp(DCAPI, LOGL_ERROR, __FILE__, __LINE__, 0, fmt, ap);
va_end(ap);
LOGPC(DCAPI, LOGL_ERROR, "\n");
}
capiconn_callbacks callbacks = {
.malloc = cb_malloc,
.free = cb_free,
.disconnected = cb_disconnected,
.incoming = cb_incoming,
.connected = cb_connected,
.received = cb_datareceived,
.datasent = cb_datasent,
.chargeinfo = NULL,
.capi_put_message = cb_put_message,
.debugmsg = cb_debugmsg,
.infomsg = cb_infomsg,
.errmsg = cb_errmsg,
};
/***********************************************************************
* initialization / integration
***********************************************************************/
/* debug print callback for capi20 to log via libosmocore logging framework */
static int cb_capi_dprintf(const char *file, int line, const char *func, const char *fmt, va_list va)
{
osmo_vlogp(DLCAPI20, LOGL_DEBUG, file, line, 0, fmt, va);
return 0;
}
/* osmocom select file descriptor call-back for capi20 file descriptor */
static int capifd_cb(struct osmo_fd *ofd, unsigned int what)
{
struct capi_inst *ci = ofd->data;
int rc;
if (what & OSMO_FD_READ) {
unsigned char *msg = NULL;
rc = capi20_get_message(ci->applid, &msg);
if (rc == 0) {
const char *str = capi20_cmd2str(CAPIMSG_COMMAND(msg), CAPIMSG_SUBCOMMAND(msg));
LOGP(DCAPI, LOGL_DEBUG, "Rx from CAPI: %s\n", str);
capiconn_inject(ci->applid, msg);
}
}
return 0;
}
struct capi_inst *capi_init(void *ctx)
{
int rc;
/* libcapi20 debug log print callback */
register_dbg_vprintf(cb_capi_dprintf);
struct capi_inst *ci = talloc_zero(ctx, struct capi_inst);
if (!ci)
return NULL;
rc = capi20_register(1, 8, 128, &ci->applid);
if (rc != 0) {
fprintf(stderr, "Error in capi_register: %s\n", capi_info2str(rc));
talloc_free(ci);
exit(1);
}
ci->cc_ctx = capiconn_getcontext(ci->applid, &callbacks);
if (!ci->cc_ctx) {
fprintf(stderr, "get_coontext\n");
capi20_release(ci->applid);
talloc_free(ci);
exit(1);
}
struct capi_contrinfo cinfo = {0, 0, 0};
capiconn_addcontr(ci->cc_ctx, 1, &cinfo);
rc = capiconn_listen(ci->cc_ctx, 1, CIPMASK_ALL, 0);
if (rc) {
fprintf(stderr, "Error in capiconn_listen: %s\n", capi_info2str(rc));
capi20_release(ci->applid);
talloc_free(ci);
exit(1);
}
osmo_fd_setup(&ci->ofd, capi20_fileno(ci->applid), OSMO_FD_READ, capifd_cb, ci, 0);
osmo_fd_register(&ci->ofd);
return ci;
}
static const struct log_info_cat log_info_cat[] = {
[DCAPI] = {
.name = "DCAPI",
.description = "ISDN CAPI Interface",
.enabled = 1,
.loglevel = LOGL_DEBUG,
},
[DLCAPI20] = {
.name = "DLCAPI02",
.description = "ISDN libcapi20",
.enabled = 1,
.loglevel = LOGL_DEBUG,
},
};
static const struct log_info log_info = {
.cat = log_info_cat,
.num_cat = ARRAY_SIZE(log_info_cat),
};
int main(int argc, char **argv)
{
void *ctx = talloc_named_const(NULL, 1, "capi-test");
osmo_init_logging2(ctx, &log_info);
capi_init(ctx);
while (1) {
osmo_select_main(0);
}
}

View File

@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string.h>
#include "isdntun.h"
#include "capiconn.h"
/* xxxxxxxxxxxxxxxxxx */