summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith <keith@rhizomatica.org>2018-08-31 15:23:48 +0200
committerKeith <keith@rhizomatica.org>2018-08-31 16:22:17 +0200
commit503d8fdb64140061d7e64c64d0478de6acb2a7b7 (patch)
tree8d699a2207807846d6519a944589e17941d2f2f1
parent6fc496eba370c8f557efd5d03066aae4c6935f39 (diff)
Add SIP <-> MNCC Cause Map
Implements a cause_map, mapping the SIP status codes to GSM48_CC_CAUSE_* that are defined in libosmocore. The map at the same time implements the Q.850 cause texts that are subsequently used in the SIP Reason: header. Implements two functions cause2status() and status2cause() to read the map and return the the mapped status. The mapping mostly follows the implemention in the LCR program, so that any implementation relying on that mapping should continue to work as expected with osmo-sip-connector. Change-Id: Id82be8603a30a6aec28fc0258236c1746973db58
-rw-r--r--src/sip.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/sip.c b/src/sip.c
index 84d1f6e..07d2286 100644
--- a/src/sip.c
+++ b/src/sip.c
@@ -148,6 +148,75 @@ static void new_call(struct sip_agent *agent, nua_handle_t *nh,
talloc_strdup(leg, to));
}
+/* Sofia SIP definitions come with error code numbers and strings, this
+ * map allows us to reuse the existing definitions.
+ * The map is in priority order. The first matching entry found
+ * will be used.
+ */
+
+static struct cause_map {
+ int sip_status;
+ const char *sip_phrase;
+ int gsm48_cause;
+ const char *q850_reason;
+} cause_map[] = {
+ { SIP_200_OK, GSM48_CC_CAUSE_NORM_CALL_CLEAR, "Normal Call Clearing" },
+ { SIP_403_FORBIDDEN, GSM48_CC_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { SIP_401_UNAUTHORIZED, GSM48_CC_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { SIP_402_PAYMENT_REQUIRED, GSM48_CC_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { SIP_407_PROXY_AUTH_REQUIRED, GSM48_CC_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { SIP_603_DECLINE, GSM48_CC_CAUSE_CALL_REJECTED, "Call Rejected" },
+ { SIP_406_NOT_ACCEPTABLE, GSM48_CC_CAUSE_CHAN_UNACCEPT, "Channel Unacceptable" },
+ { SIP_404_NOT_FOUND, GSM48_CC_CAUSE_UNASSIGNED_NR, "Unallocated Number" },
+ { SIP_485_AMBIGUOUS, GSM48_CC_CAUSE_NO_ROUTE, "No Route to Destination" },
+ { SIP_604_DOES_NOT_EXIST_ANYWHERE, GSM48_CC_CAUSE_NO_ROUTE, "No Route to Destination" },
+ { SIP_504_GATEWAY_TIME_OUT, GSM48_CC_CAUSE_RECOVERY_TIMER, "Recovery on Timer Expiry" },
+ { SIP_408_REQUEST_TIMEOUT, GSM48_CC_CAUSE_RECOVERY_TIMER, "Recovery on Timer Expiry" },
+ { SIP_410_GONE, GSM48_CC_CAUSE_NUMBER_CHANGED, "Number Changed" },
+ { SIP_416_UNSUPPORTED_URI, GSM48_CC_CAUSE_INVAL_TRANS_ID, "Invalid Call Reference Value" },
+ { SIP_420_BAD_EXTENSION, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_414_REQUEST_URI_TOO_LONG, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_413_REQUEST_TOO_LARGE, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_421_EXTENSION_REQUIRED, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_423_INTERVAL_TOO_BRIEF, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_505_VERSION_NOT_SUPPORTED, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_513_MESSAGE_TOO_LARGE, GSM48_CC_CAUSE_INTERWORKING, "Interworking, Unspecified" },
+ { SIP_480_TEMPORARILY_UNAVAILABLE, GSM48_CC_CAUSE_USER_NOTRESPOND, "No User Responding" },
+ { SIP_503_SERVICE_UNAVAILABLE, GSM48_CC_CAUSE_RESOURCE_UNAVAIL,"Resource Unavailable, Unspecified" },
+ { SIP_503_SERVICE_UNAVAILABLE, GSM48_CC_CAUSE_TEMP_FAILURE, "Temporary Failure" },
+ { SIP_503_SERVICE_UNAVAILABLE, GSM48_CC_CAUSE_SWITCH_CONG, "Switching Equipment Congestion" },
+ { SIP_400_BAD_REQUEST, GSM48_CC_CAUSE_TEMP_FAILURE, "Temporary Failure" },
+ { SIP_481_NO_CALL, GSM48_CC_CAUSE_TEMP_FAILURE, "Temporary Failure" },
+ { SIP_500_INTERNAL_SERVER_ERROR, GSM48_CC_CAUSE_TEMP_FAILURE, "Temporary Failure" },
+ { SIP_486_BUSY_HERE, GSM48_CC_CAUSE_USER_BUSY, "User Busy" },
+ { SIP_600_BUSY_EVERYWHERE, GSM48_CC_CAUSE_USER_BUSY, "User Busy" },
+ { SIP_484_ADDRESS_INCOMPLETE, GSM48_CC_CAUSE_INV_NR_FORMAT, "Invalid Number Format (addr incomplete)" },
+ { SIP_488_NOT_ACCEPTABLE, GSM48_CC_CAUSE_INCOMPAT_DEST, "Incompatible Destination" },
+ { SIP_606_NOT_ACCEPTABLE, GSM48_CC_CAUSE_INCOMPAT_DEST, "Incompatible Destination" },
+ { SIP_502_BAD_GATEWAY, GSM48_CC_CAUSE_DEST_OOO, "Destination Out of Order" },
+ { SIP_503_SERVICE_UNAVAILABLE, GSM48_CC_CAUSE_NETWORK_OOO, "Network Out of Order" },
+ { SIP_405_METHOD_NOT_ALLOWED, GSM48_CC_CAUSE_SERV_OPT_UNAVAIL,"Service or Option Not Implemented" },
+ { SIP_501_NOT_IMPLEMENTED, GSM48_CC_CAUSE_SERV_OPT_UNIMPL, "Service or Option Not Implemented" },
+ { SIP_415_UNSUPPORTED_MEDIA, GSM48_CC_CAUSE_SERV_OPT_UNIMPL, "Service or Option Not Implemented" },
+ { SIP_406_NOT_ACCEPTABLE, GSM48_CC_CAUSE_SERV_OPT_UNIMPL, "Service or Option Not Implemented" },
+ { SIP_482_LOOP_DETECTED, GSM48_CC_CAUSE_PRE_EMPTION, "Exchange Routing Error" },
+ { SIP_483_TOO_MANY_HOPS, GSM48_CC_CAUSE_PRE_EMPTION, "Exchange Routing Error" },
+ { SIP_503_SERVICE_UNAVAILABLE, GSM48_CC_CAUSE_BEARER_CA_UNAVAIL,"Bearer Capability Not Available" },
+ { SIP_480_TEMPORARILY_UNAVAILABLE, GSM48_CC_CAUSE_NORMAL_UNSPEC, "Normal, Unspecified" }
+};
+
+static int status2cause(int status)
+{
+ uint8_t i;
+
+ for (i = 0; i < ARRAY_SIZE(cause_map) - 1; i++) {
+ if (cause_map[i].sip_status == status) {
+ return cause_map[i].gsm48_cause;
+ }
+ }
+ return GSM48_CC_CAUSE_NORMAL_UNSPEC;
+}
+
void nua_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
{
LOGP(DSIP, LOGL_DEBUG, "SIP event(%u) status(%d) phrase(%s) %p\n",
@@ -217,6 +286,25 @@ void nua_callback(nua_event_t event, int status, char const *phrase, nua_t *nua,
}
}
+static void cause2status(int cause, int *sip_status, const char **sip_phrase, const char **reason_text)
+{
+ uint8_t i;
+
+ for (i = 0; i < ARRAY_SIZE(cause_map) - 1; i++) {
+ if (cause_map[i].gsm48_cause == cause) {
+ *sip_status = cause_map[i].sip_status;
+ *sip_phrase = cause_map[i].sip_phrase;
+ *reason_text = cause_map[i].q850_reason;
+ LOGP(DSIP, LOGL_DEBUG, "%s(): Mapping cause(%d) to status(%d)\n",
+ __func__, cause, *sip_status);
+ return;
+ }
+ }
+ LOGP(DSIP, LOGL_ERROR, "%s(): Cause(%d) not found in map.\n", __func__, cause);
+ *sip_status = cause_map[i].sip_status;
+ *sip_phrase = cause_map[i].sip_phrase;
+ *reason_text = cause_map[i].q850_reason;
+}
static void sip_release_call(struct call_leg *_leg)
{