mirror of https://github.com/hak5/openwrt.git
180 lines
3.4 KiB
C
180 lines
3.4 KiB
C
|
|
||
|
#include <stdbool.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <errno.h>
|
||
|
#include <poll.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <linux/input.h>
|
||
|
#include "dialdetector.h"
|
||
|
|
||
|
#include <tapi-ioctl.h>
|
||
|
|
||
|
#include <tapi-device.h>
|
||
|
#include <tapi-port.h>
|
||
|
|
||
|
#include "contact.h"
|
||
|
#include "session.h"
|
||
|
#include "sip_client.h"
|
||
|
#include "sip_agent.h"
|
||
|
#include "tapi_agent.h"
|
||
|
|
||
|
static struct tapi_device dev;
|
||
|
static struct tapi_agent *ports;
|
||
|
|
||
|
static struct sip_client sip_client;
|
||
|
|
||
|
static void release_session(struct session *session)
|
||
|
{
|
||
|
free(session);
|
||
|
}
|
||
|
|
||
|
static void dial(struct tapi_agent *caller, struct agent *callee)
|
||
|
{
|
||
|
struct session *session;
|
||
|
|
||
|
session = session_alloc(&dev, &caller->agent, callee, release_session);
|
||
|
|
||
|
if (!session)
|
||
|
return;
|
||
|
|
||
|
caller->session = session;
|
||
|
}
|
||
|
|
||
|
static void tel_dial(struct tapi_agent *caller, const char *number)
|
||
|
{
|
||
|
int callee;
|
||
|
|
||
|
callee = atoi(number) - 1;
|
||
|
|
||
|
if (callee < 0 || callee > 1)
|
||
|
return;
|
||
|
dial(caller, &ports[callee].agent);
|
||
|
}
|
||
|
|
||
|
static void sip_dial(struct tapi_agent *caller, const char *identifier)
|
||
|
{
|
||
|
struct sip_agent *callee;
|
||
|
|
||
|
callee = sip_client_alloc_agent(&sip_client, identifier);
|
||
|
if (!callee)
|
||
|
return;
|
||
|
|
||
|
dial(caller, &callee->agent);
|
||
|
}
|
||
|
|
||
|
static void dial_callback(struct tapi_port *port, size_t num_digits, const unsigned char *digits)
|
||
|
{
|
||
|
struct tapi_agent *tagent = port_to_tapi_agent(port);
|
||
|
char number[100];
|
||
|
struct contact *contact;
|
||
|
size_t i;
|
||
|
|
||
|
if (tagent->state != TAPI_AGENT_STATE_IDLE)
|
||
|
return;
|
||
|
|
||
|
for (i = 0; i < num_digits; ++i) {
|
||
|
if (digits[0] > 9)
|
||
|
break;
|
||
|
number[i] = digits[i] + '0';
|
||
|
}
|
||
|
number[i] = '\0';
|
||
|
|
||
|
printf("dial callback: %s\n", number);
|
||
|
|
||
|
contact = contact_get(number);
|
||
|
|
||
|
if (!contact)
|
||
|
return;
|
||
|
|
||
|
if (strncmp("tel:", contact->identifier, 4) == 0) {
|
||
|
tel_dial(tagent, contact->identifier + 4);
|
||
|
} else if (strncmp("sip:", contact->identifier, 4) == 0) {
|
||
|
sip_dial(tagent, contact->identifier);
|
||
|
}
|
||
|
tagent->state = TAPI_AGENT_STATE_ACTIVE;
|
||
|
}
|
||
|
|
||
|
static int incoming_sip_call(struct sip_client *client,
|
||
|
struct sip_agent *caller)
|
||
|
{
|
||
|
struct tapi_agent *callee = NULL;;
|
||
|
struct session *session;
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < 2; ++i) {
|
||
|
if (ports[i].state == TAPI_AGENT_STATE_IDLE) {
|
||
|
callee = &ports[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (callee == NULL)
|
||
|
return -1;
|
||
|
|
||
|
session = session_alloc(&dev, &caller->agent, &callee->agent,
|
||
|
release_session);
|
||
|
caller->session = session;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
struct dialdetector *dd, *dd2;
|
||
|
struct account *account;
|
||
|
struct sip_client_config config;
|
||
|
const char *interface = "eth0";
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
if (argc > 1)
|
||
|
interface = argv[1];
|
||
|
|
||
|
pj_init();
|
||
|
pjlib_util_init();
|
||
|
|
||
|
contacts_init();
|
||
|
|
||
|
account = get_account();
|
||
|
if (!account) {
|
||
|
printf("No account\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ret = tapi_device_open(0, &dev);
|
||
|
if (ret) {
|
||
|
printf("Failed to open tapi device: %d\n", ret);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ports = calloc(dev.num_ports, sizeof(*ports));
|
||
|
for (i = 0; i < dev.num_ports; ++i)
|
||
|
tapi_agent_init(&dev, i, &ports[i]);
|
||
|
|
||
|
dd = dialdetector_alloc(&ports[0].port);
|
||
|
dd->dial_callback = dial_callback;
|
||
|
dd2 = dialdetector_alloc(&ports[1].port);
|
||
|
dd2->dial_callback = dial_callback;
|
||
|
|
||
|
config.iface = interface;
|
||
|
config.host = account->realm;
|
||
|
config.port = account->sip_port;
|
||
|
config.username = account->username;
|
||
|
config.password = account->password;
|
||
|
|
||
|
config.stun_host = account->stun_host;
|
||
|
config.stun_port = account->stun_port;
|
||
|
|
||
|
sip_client_init(&sip_client, &dev, &config);
|
||
|
|
||
|
sip_client.incoming_call_cb = incoming_sip_call;
|
||
|
|
||
|
tapi_mainloop();
|
||
|
|
||
|
return 0;
|
||
|
}
|