- short-dial: use "302 Moved" to point to target
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
0.5.12
|
||||
======
|
||||
1-Jan-2006: - short-dial: use "302 Moved" to point to target
|
||||
28-Dec-2005: - Call logging: display FROM & TO for calls.
|
||||
26-Dec-2005: - Added a short-dial feature ("pi_shortdial_*" config options)
|
||||
18-Dec-2005: - Grandstream "unregister at startup" works now
|
||||
|
||||
@@ -244,13 +244,19 @@ debug_port = 0
|
||||
#
|
||||
# Quick Dial (Short Dial)
|
||||
# ability to define quick dial numbers that can be accessed by
|
||||
# dialing "*nn" from a local phone. 'nn' corresponds to the entry number
|
||||
# dialing "*00" from a local phone. '00' corresponds to the entry number
|
||||
# (pi_shortdial_entry) below. The '*' character can be chosen freely
|
||||
# (pi_shortdial_akey).
|
||||
# Note: To call a real number like "*1234" you would have to dial "**1234"
|
||||
# Note: If this module is enabled, there does NOT exist a way to dial
|
||||
# a "real" number like *01, siproxd will try to replace it by it's
|
||||
# quick dial entry.
|
||||
#
|
||||
pi_shortdial_enable = 1
|
||||
pi_shortdial_akey = *
|
||||
#
|
||||
# the first character is the "key", the following characters give
|
||||
# the length of the number string. E.g. "*00" allows qpeed dials
|
||||
# from *01 to *99. (the number "*100" will be passed through unprocessed)
|
||||
pi_shortdial_akey = *00
|
||||
#
|
||||
# *01 sipphone echo test
|
||||
pi_shortdial_entry = 17474743246
|
||||
|
||||
+90
-71
@@ -40,95 +40,114 @@ static char const ident[]="$Id$";
|
||||
/* configuration storage */
|
||||
extern struct siproxd_config configuration;
|
||||
|
||||
|
||||
|
||||
/* local prototypes */
|
||||
static int plugin_shortdial_process(sip_ticket_t *ticket);
|
||||
static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no);
|
||||
|
||||
|
||||
/* returns STS_SIP_SENT if processing is to be terminated,
|
||||
* otherwise STS_SUCCESS (go on with processing) */
|
||||
/* code (entry point) */
|
||||
int plugin_shortdial(sip_ticket_t *ticket) {
|
||||
int sts=STS_SUCCESS;
|
||||
osip_uri_t *req_url;
|
||||
int shortcut_no=0;
|
||||
|
||||
if (!ticket || !ticket->sipmsg) return STS_FAILURE;
|
||||
|
||||
DEBUGC(DBCLASS_PLUGIN,"plugin entered");
|
||||
|
||||
/* only deal with outoing calls (outgoing INVITE requests) */
|
||||
sip_find_direction(ticket, NULL);
|
||||
if ((ticket->direction == DIR_OUTGOING) ||
|
||||
(MSG_IS_INVITE(ticket->sipmsg))) {
|
||||
/* To header with username must exist, max of 2 characters */
|
||||
if (ticket && ticket->sipmsg && ticket->sipmsg &&
|
||||
ticket->sipmsg->to && ticket->sipmsg->to->url &&
|
||||
ticket->sipmsg->to->url->username &&
|
||||
(strlen(ticket->sipmsg->to->url->username) >= 2) &&
|
||||
configuration.pi_shortdial_akey) {
|
||||
char digit1=ticket->sipmsg->to->url->username[0];
|
||||
/* check for "activation key" - 1st character in number dialled */
|
||||
if (digit1 == configuration.pi_shortdial_akey[0]) {
|
||||
DEBUGC(DBCLASS_PLUGIN,"processing");
|
||||
plugin_shortdial_process(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_PLUGIN,"plugin left");
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* private code */
|
||||
static int plugin_shortdial_process(sip_ticket_t *ticket) {
|
||||
osip_uri_t *to_url=ticket->sipmsg->to->url;
|
||||
osip_uri_t *req_url;
|
||||
char *to_user=to_url->username;
|
||||
char *new_to_user=NULL;
|
||||
int shortcut_no=0;
|
||||
int i, len;
|
||||
|
||||
DEBUGC(DBCLASS_PLUGIN,"process: username=[%s]", to_user);
|
||||
|
||||
req_url=osip_message_get_uri(ticket->sipmsg);
|
||||
|
||||
/* escaped akey? (if it appears twice: e.g. "**1234" -> "*1234") */
|
||||
if (to_user[1] == configuration.pi_shortdial_akey[0]) {
|
||||
/* shift left the whole string for 1 position (incl \0 termination)*/
|
||||
for (i=0; i<strlen(to_user); i++) {
|
||||
to_user[i]=to_user[i+1];
|
||||
}
|
||||
/* only outgoing direction is handled */
|
||||
sip_find_direction(ticket, NULL);
|
||||
if (ticket->direction != DIR_OUTGOING)
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/* extract number */
|
||||
shortcut_no = atoi(&(to_user[1]));
|
||||
/* only INVITE and ACK are handled */
|
||||
if (!MSG_IS_INVITE(ticket->sipmsg) && !MSG_IS_ACK(ticket->sipmsg))
|
||||
return STS_SUCCESS;
|
||||
|
||||
/* REQ URI with username must exist, length as defined in config,
|
||||
* shortdial must be enabled and short dial key must match */
|
||||
if (!req_url || !req_url->username ||
|
||||
!configuration.pi_shortdial_akey ||
|
||||
(strlen(req_url->username) != strlen(configuration.pi_shortdial_akey)) ||
|
||||
(req_url->username[0] != configuration.pi_shortdial_akey[0]))
|
||||
return STS_SUCCESS; /* ignore */
|
||||
|
||||
shortcut_no = atoi(&(req_url->username[1]));
|
||||
if (shortcut_no <= 0) return STS_SUCCESS; /* not a number */
|
||||
|
||||
/* requested number is not defined */
|
||||
/* requested number is not defined (out of range) */
|
||||
if (shortcut_no > configuration.pi_shortdial_entry.used) {
|
||||
INFO ("shortdial: requested shortcut %i > available shortcuts",
|
||||
DEBUGC(DBCLASS_PLUGIN, "shortdial: shortcut %i > available shortcuts",
|
||||
shortcut_no, configuration.pi_shortdial_entry.used);
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/* actual replacement INVITE and To header */
|
||||
new_to_user=configuration.pi_shortdial_entry.string[shortcut_no-1];
|
||||
if (new_to_user) {
|
||||
DEBUGC(DBCLASS_PLUGIN,"process: rewriting [%s]->[%s]",
|
||||
to_user, new_to_user);
|
||||
len=strlen(new_to_user)+1; /* include trailing "\0" */
|
||||
|
||||
/* Request URI */
|
||||
if (req_url && req_url->username) {
|
||||
osip_free(req_url->username);
|
||||
req_url->username=osip_malloc(len);
|
||||
strncpy(req_url->username, new_to_user, len);
|
||||
}
|
||||
|
||||
/* To header */
|
||||
to_user=NULL;
|
||||
osip_free(to_url->username);
|
||||
to_url->username=osip_malloc(len);
|
||||
strncpy(to_url->username, new_to_user, len);
|
||||
/* requested number is not defined (empty) */
|
||||
if (!configuration.pi_shortdial_entry.string[shortcut_no-1]) {
|
||||
DEBUGC(DBCLASS_PLUGIN, "shortdial: shortcut %i empty", shortcut_no);
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return STS_SUCCESS;
|
||||
/*
|
||||
* called number does match the short dial specification
|
||||
*/
|
||||
|
||||
/* outgoing INVITE request */
|
||||
if (MSG_IS_INVITE(ticket->sipmsg)) {
|
||||
DEBUGC(DBCLASS_PLUGIN,"processing INVITE");
|
||||
sts=plugin_shortdial_redirect(ticket, shortcut_no);
|
||||
}
|
||||
/* outgoing ACK request: is result of a local 3xx answer (moved...) */
|
||||
else if (MSG_IS_ACK(ticket->sipmsg)) {
|
||||
/* make sure we only catch ACKs caused by myself (**02 -> *02 legitime) */
|
||||
DEBUGC(DBCLASS_PLUGIN,"processing ACK");
|
||||
sts=STS_SIP_SENT; /* eat up the ACK that was directed to myself */
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/* private code */
|
||||
static int plugin_shortdial_redirect(sip_ticket_t *ticket, int shortcut_no) {
|
||||
osip_uri_t *to_url=ticket->sipmsg->to->url;
|
||||
char *to_user=to_url->username;
|
||||
char *new_to_user=NULL;
|
||||
int i, len;
|
||||
osip_contact_t *contact = NULL;
|
||||
|
||||
new_to_user=configuration.pi_shortdial_entry.string[shortcut_no-1];
|
||||
if (!new_to_user) return STS_SUCCESS;
|
||||
|
||||
DEBUGC(DBCLASS_PLUGIN,"redirect: redirecting [%s]->[%s]",
|
||||
to_user, new_to_user);
|
||||
len=strlen(new_to_user)+1; /* include trailing "\0" */
|
||||
|
||||
/* use a "302 Moved temporarily" response back to the client */
|
||||
/* new target is within the Contact Header */
|
||||
|
||||
/* remove all Contact headers in message */
|
||||
for (i=0; (contact != NULL) || (i == 0); i++) {
|
||||
osip_message_get_contact(ticket->sipmsg, 0, &contact);
|
||||
if (contact) {
|
||||
osip_list_remove(ticket->sipmsg->contacts,0);
|
||||
osip_contact_free(contact);
|
||||
}
|
||||
} /* for i */
|
||||
|
||||
/* insert one new Contact header containing the new target address */
|
||||
osip_contact_init(&contact);
|
||||
osip_uri_clone(to_url, &contact->url);
|
||||
osip_free(contact->url->username);
|
||||
contact->url->username=osip_malloc(len);
|
||||
strcpy(contact->url->username, new_to_user);
|
||||
|
||||
osip_list_add(ticket->sipmsg->contacts,contact,0);
|
||||
|
||||
/* sent redirect message back to local client */
|
||||
sip_gen_response(ticket, 302 /*Moved temporarily*/);
|
||||
|
||||
return STS_SIP_SENT;
|
||||
}
|
||||
|
||||
+17
-11
@@ -110,6 +110,7 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
/*
|
||||
* logging of passing calls
|
||||
*/
|
||||
/*&&&& this should be moved to its own loggin plugin */
|
||||
if (configuration.log_calls) {
|
||||
osip_uri_t *from_url = NULL;
|
||||
osip_uri_t *to_url = NULL;
|
||||
@@ -117,12 +118,13 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
char *to_host = NULL;
|
||||
char *from_username =NULL;
|
||||
char *from_host = NULL;
|
||||
char *call_type = NULL;
|
||||
|
||||
/* From: 1st preference is contact header, then use From field */
|
||||
if (!osip_list_eol(request->contacts, 0)) {
|
||||
from_url = ((osip_contact_t*)(request->contacts->node->element))->url;
|
||||
} else {
|
||||
/* From: 1st preference is From header, then try contact header */
|
||||
if (request->from->url) {
|
||||
from_url = request->from->url;
|
||||
} else {
|
||||
from_url = (osip_uri_t *)osip_list_get(request->contacts, 0);
|
||||
}
|
||||
|
||||
to_url = request->to->url;
|
||||
@@ -139,20 +141,24 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
|
||||
/* INVITE */
|
||||
if (MSG_IS_INVITE(request)) {
|
||||
INFO("%s Call: %s@%s -> %s@%s",
|
||||
(type==REQTYP_INCOMING) ? "Incoming":"Outgoing",
|
||||
from_username ? from_username: "*NULL*",
|
||||
from_host ? from_host : "*NULL*",
|
||||
to_username ? to_username : "*NULL*",
|
||||
to_host ? to_host : "*NULL*");
|
||||
if (type==REQTYP_INCOMING) call_type="Incoming";
|
||||
else call_type="Outgoing";
|
||||
/* BYE / CANCEL */
|
||||
} else if (MSG_IS_ACK(request)) {
|
||||
call_type="ACK";
|
||||
} else if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||
INFO("Ending Call: %s@%s -> %s@%s",
|
||||
call_type="Ending";
|
||||
}
|
||||
|
||||
if (call_type) {
|
||||
INFO("%s Call: %s@%s -> %s@%s",
|
||||
call_type,
|
||||
from_username ? from_username: "*NULL*",
|
||||
from_host ? from_host : "*NULL*",
|
||||
to_username ? to_username : "*NULL*",
|
||||
to_host ? to_host : "*NULL*");
|
||||
}
|
||||
|
||||
} /* log_calls */
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ int register_client(sip_ticket_t *ticket, int force_lcl_masq) {
|
||||
/* answer the request myself. Most likely this is an UNREGISTER
|
||||
* request when the client just booted */
|
||||
sts = register_response(ticket, STS_SUCCESS);
|
||||
return STS_RESP_SENT;
|
||||
return STS_SIP_SENT;
|
||||
}
|
||||
|
||||
return STS_SUCCESS;
|
||||
|
||||
+17
-1
@@ -97,7 +97,23 @@ int security_check_raw(char *sip_buffer, int size) {
|
||||
DEBUGC(DBCLASS_SIP,"security_check_raw: found only one space");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/* libosip2 can be put into an endless loop by trying to parse:
|
||||
---BUFFER DUMP follows---
|
||||
49 4e 56 49 54 45 20 20 53 49 50 2f 32 2e 30 0d INVITE SIP/2.0.
|
||||
0a 56 69 61 3a 20 53 49 50 2f 32 2e 30 2f 55 44 .Via: SIP/2.0/UD
|
||||
Note, this is an INVITE with no valid SIP URI (INVITE SIP/2.0)
|
||||
*/
|
||||
/* clumsy... */
|
||||
if (size >20) {
|
||||
if (strncmp(sip_buffer, "INVITE SIP/2.0", 15)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "ACK SIP/2.0", 12)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "BYE SIP/2.0", 12)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "CANCEL SIP/2.0", 15)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "REGISTER SIP/2.0",17)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "OPTIONS SIP/2.0", 16)==0) return STS_FAILURE;
|
||||
else if (strncmp(sip_buffer, "INFO SIP/2.0", 13)==0) return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* TODO: still way to go here ... */
|
||||
return STS_SUCCESS;
|
||||
|
||||
@@ -84,6 +84,14 @@ osip_message_t *msg_make_template_reply (sip_ticket_t *ticket, int code) {
|
||||
osip_to_clone (request->to, &response->to);
|
||||
osip_from_clone (request->from, &response->from);
|
||||
|
||||
/* if 3xx, also include 1st contact header */
|
||||
if ((code>=300) && (code<400)) {
|
||||
osip_contact_t *req_contact = NULL;
|
||||
osip_contact_t *res_contact = NULL;
|
||||
osip_message_get_contact(request, 0, &req_contact);
|
||||
osip_contact_clone (req_contact, &res_contact);
|
||||
osip_list_add(response->contacts,res_contact,0);
|
||||
}
|
||||
|
||||
/* via headers */
|
||||
pos = 0;
|
||||
|
||||
+4
-1
@@ -426,7 +426,10 @@ int main (int argc, char *argv[])
|
||||
* additional preprocessing
|
||||
*********************************/
|
||||
/* Dial shortcuts */
|
||||
if (configuration.pi_shortdial) plugin_shortdial(&ticket);
|
||||
if (configuration.pi_shortdial) {
|
||||
sts = plugin_shortdial(&ticket);
|
||||
if (sts == STS_SIP_SENT) goto end_loop;
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
|
||||
+1
-1
@@ -262,7 +262,7 @@ int sip_message_set_body(osip_message_t * sip, const char *buf, int len);
|
||||
#define STS_FAILURE 1 /* FAILURE */
|
||||
#define STS_FALSE 1 /* FALSE */
|
||||
#define STS_NEED_AUTH 1001 /* need authentication */
|
||||
#define STS_RESP_SENT 2001 /* response is already sent */
|
||||
#define STS_SIP_SENT 2001 /* SIP packet is already sent */
|
||||
|
||||
/* symbolic direction of data */
|
||||
#define DIR_INCOMING 1
|
||||
|
||||
Reference in New Issue
Block a user