aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authoroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-20 07:44:42 +0000
committeroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-20 07:44:42 +0000
commitfece727db33a3c3a901bf6dd5d31024fffc179a3 (patch)
treed6cb545b10738cc0a62e3ddd414e3856517d581b /channels
parent36450fa365f8694be6e491596731f2457f8d00a4 (diff)
Let's understand SIP:
- REFER can create dialog, Asterisk does not support it yet - NOTIFY can create dialog in Asterisk's implementation (voicemail) even though we don't support the server side of it. In this case, the standard is a side issue ;-) - Added extened functionality for unsupported methods (PING, PUBLISH) so we don't create PVT's for those either. Russellb needs to judge what to do with this in 1.2, but I think the current implementation n 1.2 is a bug since we're sending bad replies to NOTIFY and REFER outside of dialogs git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@45741 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_sip.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 599c4fc5f..a67395b14 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -307,6 +307,7 @@ enum sipmethod {
SIP_INFO,
SIP_CANCEL,
SIP_PUBLISH, /* Not supported at all */
+ SIP_PING, /* Not supported at all, no standard but still implemented out there */
};
/*! \brief Authentication types - proxy or www authentication
@@ -342,6 +343,9 @@ enum sipregistrystate {
REG_STATE_FAILED, /*!< Registration failed after several tries */
};
+#define CAN_NOT_CREATE_DIALOG 0
+#define CAN_CREATE_DIALOG 1
+#define CAN_CREATE_DIALOG_UNSUPPORTED_METHOD 2
/*! XXX Note that sip_methods[i].id == i must hold or the code breaks */
static const struct cfsip_methods {
@@ -350,22 +354,23 @@ static const struct cfsip_methods {
char * const text;
int can_create;
} sip_methods[] = {
- { SIP_UNKNOWN, RTP, "-UNKNOWN-", 0 },
- { SIP_RESPONSE, NO_RTP, "SIP/2.0", 0 },
- { SIP_REGISTER, NO_RTP, "REGISTER", 1 },
- { SIP_OPTIONS, NO_RTP, "OPTIONS", 1 },
- { SIP_NOTIFY, NO_RTP, "NOTIFY", 0 },
- { SIP_INVITE, RTP, "INVITE", 1 },
- { SIP_ACK, NO_RTP, "ACK", 0 },
- { SIP_PRACK, NO_RTP, "PRACK", 0 },
- { SIP_BYE, NO_RTP, "BYE", 0 },
- { SIP_REFER, NO_RTP, "REFER", 0 },
- { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE", 1 },
- { SIP_MESSAGE, NO_RTP, "MESSAGE", 1 },
- { SIP_UPDATE, NO_RTP, "UPDATE", 0 },
- { SIP_INFO, NO_RTP, "INFO", 0 },
- { SIP_CANCEL, NO_RTP, "CANCEL", 0 },
- { SIP_PUBLISH, NO_RTP, "PUBLISH", 1 }
+ { SIP_UNKNOWN, RTP, "-UNKNOWN-", CAN_CREATE_DIALOG },
+ { SIP_RESPONSE, NO_RTP, "SIP/2.0", CAN_NOT_CREATE_DIALOG },
+ { SIP_REGISTER, NO_RTP, "REGISTER", CAN_CREATE_DIALOG },
+ { SIP_OPTIONS, NO_RTP, "OPTIONS", CAN_CREATE_DIALOG },
+ { SIP_NOTIFY, NO_RTP, "NOTIFY", CAN_CREATE_DIALOG },
+ { SIP_INVITE, RTP, "INVITE", CAN_CREATE_DIALOG },
+ { SIP_ACK, NO_RTP, "ACK", CAN_NOT_CREATE_DIALOG },
+ { SIP_PRACK, NO_RTP, "PRACK", CAN_NOT_CREATE_DIALOG },
+ { SIP_BYE, NO_RTP, "BYE", CAN_NOT_CREATE_DIALOG },
+ { SIP_REFER, NO_RTP, "REFER", CAN_CREATE_DIALOG },
+ { SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE", CAN_CREATE_DIALOG },
+ { SIP_MESSAGE, NO_RTP, "MESSAGE", CAN_CREATE_DIALOG },
+ { SIP_UPDATE, NO_RTP, "UPDATE", CAN_NOT_CREATE_DIALOG },
+ { SIP_INFO, NO_RTP, "INFO", CAN_NOT_CREATE_DIALOG },
+ { SIP_CANCEL, NO_RTP, "CANCEL", CAN_NOT_CREATE_DIALOG },
+ { SIP_PUBLISH, NO_RTP, "PUBLISH", CAN_CREATE_DIALOG_UNSUPPORTED_METHOD },
+ { SIP_PING, NO_RTP, "PING", CAN_CREATE_DIALOG_UNSUPPORTED_METHOD }
};
/*! Define SIP option tags, used in Require: and Supported: headers
@@ -4272,12 +4277,30 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
ast_mutex_unlock(&iflock);
/* See if the method is capable of creating a dialog */
- if (!sip_methods[intended_method].can_create) {
- if (intended_method != SIP_RESPONSE)
- transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
- } else if ((p = sip_alloc(callid, sin, 1, intended_method))) {
- ast_mutex_lock(&p->lock);
- }
+ if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
+ if (intended_method == SIP_REFER) {
+ /* We do support REFER, but not outside of a dialog yet */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)");
+ } else if (intended_method == SIP_NOTIFY) {
+ /* We do not support out-of-dialog NOTIFY either,
+ like voicemail notification, so cancel that early */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event");
+ } else {
+ /* Ok, time to create a new SIP dialog object, a pvt */
+ if ((p = sip_alloc(callid, sin, 1, intended_method)))
+ /* Ok, we've created a dialog, let's go and process it */
+ ast_mutex_lock(&p->lock);
+ }
+ return p;
+ } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) {
+ /* A method we do not support, let's take it on the volley */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "501 Method Not Implemented");
+ } else if (intended_method != SIP_RESPONSE) {
+ /* This is a request outside of a dialog that we don't know about */
+ transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist");
+ }
+ /* We do not respond to responses for dialogs that we don't know about, we just drop
+ the session quickly */
return p;
}