ETSI Message Waiting Indication (MWI) support.

Add the ability to report waiting messages to ISDN endpoints (phones).

Relevant specification: EN 300 650 and EN 300 745

Review:	https://reviewboard.asterisk.org/r/600/


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1767 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2010-05-28 21:50:14 +00:00
parent 0b28bf0aab
commit 8c5eeeae79
9 changed files with 1278 additions and 8 deletions

View File

@ -57,6 +57,7 @@ STATIC_OBJS= \
rose_etsi_cc.o \
rose_etsi_diversion.o \
rose_etsi_ect.o \
rose_etsi_mwi.o \
rose_other.o \
rose_q931.o \
rose_qsig_aoc.o \
@ -82,6 +83,7 @@ DYNAMIC_OBJS= \
rose_etsi_cc.lo \
rose_etsi_diversion.lo \
rose_etsi_ect.lo \
rose_etsi_mwi.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_aoc.lo \

View File

@ -1523,6 +1523,25 @@ int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan
/* Send an MWI deactivate request to a remote location */
int pri_mwi_deactivate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
/*!
* \brief Send a MWI indication on the specified D channel.
*
* \param ctrl D channel controller.
* \param mailbox Controlling party number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status);
/* Set service message support flag */
int pri_set_service_message_support(struct pri *pri, int supportflag);

View File

@ -1738,6 +1738,146 @@ int mwi_message_send(struct pri *ctrl, q931_call *call, struct pri_sr *req, int
return pri_call_apdu_queue(call, Q931_SETUP, buffer, end - buffer, NULL);
}
/*!
* \internal
* \brief Encode a MWI indication.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode the facility ie contents.
* \param end End of facility ie contents encoding data buffer.
* \param mailbox Controlling party number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *enc_etsi_mwi_indicate_message(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct pri_party_id *mailbox, int basic_service,
int num_messages, const struct pri_party_id *caller_id, const char *timestamp,
int message_reference, int message_status)
{
struct rose_msg_invoke msg;
struct q931_party_number number;
pos = facility_encode_header(ctrl, pos, end, NULL);
if (!pos) {
return NULL;
}
memset(&msg, 0, sizeof(msg));
msg.operation = ROSE_ETSI_MWIIndicate;
msg.invoke_id = get_invokeid(ctrl);
if (mailbox && mailbox->number.valid) {
pri_copy_party_number_to_q931(&number, &mailbox->number);
q931_copy_number_to_rose(ctrl, &msg.args.etsi.MWIIndicate.controlling_user_number,
&number);
}
if (-1 < basic_service) {
msg.args.etsi.MWIIndicate.basic_service_present = 1;
msg.args.etsi.MWIIndicate.basic_service = basic_service;
}
if (-1 < num_messages) {
msg.args.etsi.MWIIndicate.number_of_messages_present = 1;
msg.args.etsi.MWIIndicate.number_of_messages = num_messages;
}
if (caller_id && caller_id->number.valid) {
pri_copy_party_number_to_q931(&number, &caller_id->number);
q931_copy_number_to_rose(ctrl,
&msg.args.etsi.MWIIndicate.controlling_user_provided_number, &number);
}
if (timestamp && timestamp[0]) {
msg.args.etsi.MWIIndicate.time_present = 1;
libpri_copy_string((char *) msg.args.etsi.MWIIndicate.time.str, timestamp,
sizeof(msg.args.etsi.MWIIndicate.time.str));
}
if (-1 < message_reference) {
msg.args.etsi.MWIIndicate.message_id_present = 1;
msg.args.etsi.MWIIndicate.message_id.reference_number = message_reference;
msg.args.etsi.MWIIndicate.message_id.status = message_status;
}
pos = rose_encode_invoke(ctrl, pos, end, &msg);
return pos;
}
/*!
* \internal
* \brief Encode and queue a MWI indication.
*
* \param ctrl D channel controller.
* \param call Call leg to queue message.
* \param mailbox Controlling party number (NULL if not present).
* \param basic_service Basic service enum (-1 if not present).
* \param num_messages NumberOfMessages (-1 if not present).
* \param caller_id Controlling party privided number (NULL if not present).
* \param timestamp Generalized Time format (NULL if not present).
* \param message_reference Message reference number (-1 if not present).
* \param message_status Message status: added(0), removed(1).
*
* \retval 0 on success.
* \retval -1 on error.
*/
static int rose_mwi_indicate_encode(struct pri *ctrl, struct q931_call *call,
const struct pri_party_id *mailbox, int basic_service, int num_messages,
const struct pri_party_id *caller_id, const char *timestamp, int message_reference,
int message_status)
{
unsigned char buffer[255];
unsigned char *end;
end = enc_etsi_mwi_indicate_message(ctrl, buffer, buffer + sizeof(buffer), mailbox,
basic_service, num_messages, caller_id, timestamp, message_reference,
message_status);
if (!end) {
return -1;
}
return pri_call_apdu_queue(call, Q931_FACILITY, buffer, end - buffer, NULL);
}
int pri_mwi_indicate(struct pri *ctrl, const struct pri_party_id *mailbox,
int basic_service, int num_messages, const struct pri_party_id *caller_id,
const char *timestamp, int message_reference, int message_status)
{
struct q931_call *call;
if (!ctrl) {
return -1;
}
switch (ctrl->switchtype) {
case PRI_SWITCH_EUROISDN_E1:
case PRI_SWITCH_EUROISDN_T1:
if (!BRI_NT_PTMP(ctrl)) {
return -1;
}
call = PRI_MASTER(ctrl)->dummy_call;
if (!call) {
return -1;
}
break;
default:
return -1;
}
if (rose_mwi_indicate_encode(ctrl, call, mailbox, basic_service, num_messages,
caller_id, timestamp, message_reference, message_status)
|| q931_facility(ctrl, call)) {
pri_message(ctrl,
"Could not schedule facility message for MWI indicate message.\n");
return -1;
}
return 0;
}
/* End MWI */
/* EECT functions */
@ -4558,6 +4698,14 @@ void rose_handle_invoke(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
break;
}
break;
#if 0 /* Not handled yet */
case ROSE_ETSI_MWIActivate:
break;
case ROSE_ETSI_MWIDeactivate:
break;
case ROSE_ETSI_MWIIndicate:
break;
#endif /* Not handled yet */
case ROSE_QSIG_CallingName:
/* CallingName is put in remote_id.name */
rose_copy_name_to_q931(ctrl, &call->remote_id.name,

68
rose.c
View File

@ -240,6 +240,14 @@ static const struct asn1_oid rose_etsi_ccnr_t = {
/* *INDENT-ON* */
};
/*! \brief ETSI Message Waiting Indication OID prefix. */
static const struct asn1_oid rose_etsi_mwi = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 745 operations-and-errors(1)} */
4, { 4, 0, 745, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI specific invoke/result encode/decode message table */
static const struct rose_convert_msg rose_etsi_msgs[] = {
/* *INDENT-OFF* */
@ -541,6 +549,26 @@ static const struct rose_convert_msg rose_etsi_msgs[] = {
NULL, NULL,
NULL, NULL
},
/*
* globalValue's (OIDs) from MWI-Operations-and-Errors
* {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
*/
{
ROSE_ETSI_MWIActivate, &rose_etsi_mwi, 1,
rose_enc_etsi_MWIActivate_ARG, NULL,
rose_dec_etsi_MWIActivate_ARG, NULL
},
{
ROSE_ETSI_MWIDeactivate, &rose_etsi_mwi, 2,
rose_enc_etsi_MWIDeactivate_ARG, NULL,
rose_dec_etsi_MWIDeactivate_ARG, NULL
},
{
ROSE_ETSI_MWIIndicate, &rose_etsi_mwi, 3,
rose_enc_etsi_MWIIndicate_ARG, NULL,
rose_dec_etsi_MWIIndicate_ARG, NULL
},
/* *INDENT-ON* */
};
@ -697,6 +725,35 @@ static const struct rose_convert_error rose_etsi_errors[] = {
ROSE_ERROR_CCBS_T_ShortTermDenial, &rose_etsi_ccbs_t, 21,
NULL, NULL
},
/*
* globalValue's (OIDs) from MWI-Operations-and-Errors
* {ccitt identified-organization etsi(0) 745 operations-and-errors(1)}
*/
{
ROSE_ERROR_MWI_InvalidReceivingUserNr, &rose_etsi_mwi, 10,
NULL, NULL
},
{
ROSE_ERROR_MWI_ReceivingUserNotSubscribed, &rose_etsi_mwi, 11,
NULL, NULL
},
{
ROSE_ERROR_MWI_ControllingUserNotRegistered,&rose_etsi_mwi, 12,
NULL, NULL
},
{
ROSE_ERROR_MWI_IndicationNotDelivered, &rose_etsi_mwi, 13,
NULL, NULL
},
{
ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,&rose_etsi_mwi, 14,
NULL, NULL
},
{
ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,&rose_etsi_mwi, 15,
NULL, NULL
},
/* *INDENT-ON* */
};
@ -1403,6 +1460,10 @@ const char *rose_operation2str(enum rose_operation operation)
{ ROSE_ETSI_MCIDRequest, "ROSE_ETSI_MCIDRequest" },
{ ROSE_ETSI_MWIActivate, "ROSE_ETSI_MWIActivate" },
{ ROSE_ETSI_MWIDeactivate, "ROSE_ETSI_MWIDeactivate" },
{ ROSE_ETSI_MWIIndicate, "ROSE_ETSI_MWIIndicate" },
{ ROSE_QSIG_CallingName, "ROSE_QSIG_CallingName" },
{ ROSE_QSIG_CalledName, "ROSE_QSIG_CalledName" },
{ ROSE_QSIG_ConnectedName, "ROSE_QSIG_ConnectedName" },
@ -1517,6 +1578,13 @@ const char *rose_error2str(enum rose_error_code code)
{ ROSE_ERROR_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
{ ROSE_ERROR_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
{ ROSE_ERROR_MWI_InvalidReceivingUserNr, "MWI: Invalid Receiving User Number" },
{ ROSE_ERROR_MWI_ReceivingUserNotSubscribed, "MWI: Receiving User Not Subscribed" },
{ ROSE_ERROR_MWI_ControllingUserNotRegistered,"MWI: Controlling User Not Registered" },
{ ROSE_ERROR_MWI_IndicationNotDelivered, "MWI: Indication Not Delivered" },
{ ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,"MWI: Max Num Of Controlling Users Reached" },
{ ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,"MWI: Max Num Of Active Instances Reached" },
/* Q.SIG specific errors */
{ ROSE_ERROR_QSIG_Unspecified, "Unspecified" },

247
rose.h
View File

@ -137,6 +137,11 @@ enum rose_operation {
/* ETSI MCID-Operations */
ROSE_ETSI_MCIDRequest, /*!< Invoke/Result */
/* ETSI MWI-Operations-and-Errors */
ROSE_ETSI_MWIActivate, /*!< Invoke/Result */
ROSE_ETSI_MWIDeactivate, /*!< Invoke/Result */
ROSE_ETSI_MWIIndicate, /*!< Invoke only */
/* Q.SIG Name-Operations */
ROSE_QSIG_CallingName, /*!< Invoke only */
ROSE_QSIG_CalledName, /*!< Invoke only */
@ -257,6 +262,14 @@ enum rose_error_code {
ROSE_ERROR_CCBS_T_LongTermDenial,
ROSE_ERROR_CCBS_T_ShortTermDenial,
/* ETSI MWI-Operations-and-Errors */
ROSE_ERROR_MWI_InvalidReceivingUserNr,
ROSE_ERROR_MWI_ReceivingUserNotSubscribed,
ROSE_ERROR_MWI_ControllingUserNotRegistered,
ROSE_ERROR_MWI_IndicationNotDelivered,
ROSE_ERROR_MWI_MaxNumOfControllingUsersReached,
ROSE_ERROR_MWI_MaxNumOfActiveInstancesReached,
/* Q.SIG from various specifications */
ROSE_ERROR_QSIG_Unspecified,
@ -390,6 +403,31 @@ enum {
/* ------------------------------------------------------------------- */
/*
* Comment obtained from ECMA-242 ASN.1 source.
* a VisibleString containing:
* - the (local) date in 8 digits (YYYYMMDD),
* - followed by (local) time of day in 4 or 6 digits (HHMM[SS]),
* - optionally followed by the letter "Z" or
* by a local time differential in 5 digits ("+"HHMM or "-"HHMM);
* this date and time representation follows ISO 8601
* Examples:
* 1) 19970621194530, meaning 21 June 1997, 19:45:30;
* 2) 19970621194530Z, meaning the same as 1);
* 3) 19970621194530-0500, meaning the same as 1),
* 5 hours retarded in relation to UTC time
*
* GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
*/
struct roseGeneralizedTime {
/*! GeneralizedTime (SIZE (12..19)) */
unsigned char str[19 + 1];
};
/* ------------------------------------------------------------------- */
/*
* PartyNumber ::= CHOICE {
* -- the numbering plan is the default numbering plan of
@ -2082,6 +2120,206 @@ struct roseEtsiCCBS_T_Request_RES {
/* ------------------------------------------------------------------- */
/*
* MessageID ::= SEQUENCE {
* messageRef MessageRef,
* status MessageStatus
* }
*/
struct roseEtsiMessageID {
/*! \brief Message reference number. (INTEGER (0..65535)) */
u_int16_t reference_number;
/*!
* \brief Message status
* \details
* added_message(0),
* removed_message(1)
*/
u_int8_t status;
};
/*
* ARGUMENT SEQUENCE {
* receivingUserNr PartyNumber,
* basicService BasicService,
* controllingUserNr [1] EXPLICIT PartyNumber OPTIONAL,
* numberOfMessages [2] EXPLICIT MessageCounter OPTIONAL,
* controllingUserProvidedNr [3] EXPLICIT PartyNumber OPTIONAL,
* time [4] EXPLICIT GeneralizedTime OPTIONAL,
* messageId [5] EXPLICIT MessageID OPTIONAL,
* mode [6] EXPLICIT InvocationMode OPTIONAL
* }
*/
struct roseEtsiMWIActivate_ARG {
/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
u_int16_t number_of_messages;
/*! \brief Message ID (Status of this message) (Optional)*/
struct roseEtsiMessageID message_id;
/*! \brief Receiving user number (Who the message is for.) */
struct rosePartyNumber receiving_user_number;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
struct rosePartyNumber controlling_user_provided_number;
/*! \brief When message left. (optional) */
struct roseGeneralizedTime time;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*!
* \brief Invocation mode (When it should be delivered.) (Optional)
* \details
* deferred(0),
* immediate(1),
* combined(2)
*/
u_int8_t mode;
/*! \brief TRUE if NumberOfMessages present */
u_int8_t number_of_messages_present;
/*! \brief TRUE if time present */
u_int8_t time_present;
/*! \brief TRUE if MessageId present */
u_int8_t message_id_present;
/*! \brief TRUE if invocation mode present */
u_int8_t mode_present;
};
/*
* ARGUMENT SEQUENCE {
* receivingUserNr PartyNumber,
* basicService BasicService,
* controllingUserNr PartyNumber OPTIONAL,
* mode InvocationMode OPTIONAL
* }
*/
struct roseEtsiMWIDeactivate_ARG {
/*! \brief Receiving user number (Who the message is for.) */
struct rosePartyNumber receiving_user_number;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*!
* \brief Invocation mode (When it should be delivered.) (Optional)
* \details
* deferred(0),
* immediate(1),
* combined(2)
*/
u_int8_t mode;
/*! \brief TRUE if invocation mode present */
u_int8_t mode_present;
};
/*
* ARGUMENT SEQUENCE {
* controllingUserNr [1] EXPLICIT PartyNumber OPTIONAL,
* basicService [2] EXPLICIT BasicService OPTIONAL,
* numberOfMessages [3] EXPLICIT MessageCounter OPTIONAL,
* controllingUserProvidedNr [4] EXPLICIT PartyNumber OPTIONAL,
* time [5] EXPLICIT GeneralizedTime OPTIONAL,
* messageId [6] EXPLICIT MessageID OPTIONAL
* }
*/
struct roseEtsiMWIIndicate_ARG {
/*! \brief Number of messages in mailbox. (INTEGER (0..65535)) (Optional) */
u_int16_t number_of_messages;
/*! \brief Message ID (Status of this message) (Optional)*/
struct roseEtsiMessageID message_id;
/*! \brief Controlling user number (Mailbox number) (Optional) */
struct rosePartyNumber controlling_user_number;
/*! \brief Controlling user provided number (Caller-ID of party leaving message) (Optional) */
struct rosePartyNumber controlling_user_provided_number;
/*! \brief When message left. (optional) */
struct roseGeneralizedTime time;
/*!
* \brief Type of call leaving message.
* \details
* allServices(0),
* speech(1),
* unrestrictedDigitalInformation(2),
* audio3k1Hz(3),
* unrestrictedDigitalInformationWithTonesAndAnnouncements(4),
* multirate(5),
* telephony3k1Hz(32),
* teletex(33),
* telefaxGroup4Class1(34),
* videotexSyntaxBased(35),
* videotelephony(36),
* telefaxGroup2-3(37),
* telephony7kHz(38),
* euroFileTransfer(39),
* fileTransferAndAccessManagement(40),
* videoconference(41),
* audioGraphicConference(42)
*/
u_int8_t basic_service;
/*! \brief TRUE if basic_service present */
u_int8_t basic_service_present;
/*! \brief TRUE if NumberOfMessages present */
u_int8_t number_of_messages_present;
/*! \brief TRUE if time present */
u_int8_t time_present;
/*! \brief TRUE if MessageId present */
u_int8_t message_id_present;
};
/* ------------------------------------------------------------------- */
/*
* Name ::= CHOICE {
* -- iso8859-1 is implied in namePresentationAllowedSimple.
@ -3450,7 +3688,7 @@ struct roseQsigMWIActivateArg {
struct rosePartyNumber originating_number;
/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
unsigned char timestamp[19 + 1];
struct roseGeneralizedTime timestamp;
/*!
* \details
@ -3675,7 +3913,7 @@ struct roseQsigMWIInterrogateResElt {
struct rosePartyNumber originating_number;
/*! \brief GeneralizedTime (SIZE (12..19)) (optional) */
unsigned char timestamp[19 + 1];
struct roseGeneralizedTime timestamp;
/*!
* \details
@ -3862,6 +4100,11 @@ union rose_msg_invoke_etsi_args {
/* ETSI CCNR-T */
struct roseEtsiCCBS_T_Request_ARG CCNR_T_Request;
/* ETSI Message Waiting Indication (MWI) */
struct roseEtsiMWIActivate_ARG MWIActivate;
struct roseEtsiMWIDeactivate_ARG MWIDeactivate;
struct roseEtsiMWIIndicate_ARG MWIIndicate;
};
/*! \brief Facility ie result etsi messages with arguments. */

686
rose_etsi_mwi.c Normal file
View File

@ -0,0 +1,686 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2010 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief ROSE Message Waiting Indication (MWI) operations
*
* Message Waiting Indication (MWI) supplementary service EN 300 745-1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the MessageID type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param msg_id
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_etsi_message_id(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseEtsiMessageID *msg_id)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, msg_id->reference_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED, msg_id->status));
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIActivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIActivate_ARG *mwi_activate;
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_activate = &args->etsi.MWIActivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->receiving_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_activate->basic_service));
if (mwi_activate->controlling_user_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->controlling_user_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->number_of_messages_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
mwi_activate->number_of_messages));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->controlling_user_provided_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_activate->controlling_user_provided_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->time_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_activate->time.str, sizeof(mwi_activate->time.str) - 1));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->message_id_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
&mwi_activate->message_id));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_activate->mode_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_activate->mode));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIDeactivate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_deactivate = &args->etsi.MWIDeactivate;
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_deactivate->receiving_user_number));
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_deactivate->basic_service));
if (mwi_deactivate->controlling_user_number.length) {
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_deactivate->controlling_user_number));
}
if (mwi_deactivate->mode_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_deactivate->mode));
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the MWIIndicate invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
const struct roseEtsiMWIIndicate_ARG *mwi_indicate;
unsigned char *seq_len;
unsigned char *explicit_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
mwi_indicate = &args->etsi.MWIIndicate;
if (mwi_indicate->controlling_user_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_indicate->controlling_user_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->basic_service_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
mwi_indicate->basic_service));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->number_of_messages_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
mwi_indicate->number_of_messages));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->controlling_user_provided_number.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end,
&mwi_indicate->controlling_user_provided_number));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->time_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5);
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_indicate->time.str, sizeof(mwi_indicate->time.str) - 1));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
if (mwi_indicate->message_id_present) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 6);
ASN1_CALL(pos, rose_enc_etsi_message_id(ctrl, pos, end,
&mwi_indicate->message_id));
ASN1_CONSTRUCTED_END(explicit_len, pos, end);
}
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \internal
* \brief Decode the MessageID argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param msg_id Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_etsi_message_id(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseEtsiMessageID *msg_id)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s MessageID %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "messageRef", tag, pos, seq_end, &value));
msg_id->reference_number = value;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "status", tag, pos, seq_end, &value));
msg_id->status = value;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIActivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseEtsiMWIActivate_ARG *mwi_activate;
mwi_activate = &args->etsi.MWIActivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIActivate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
&mwi_activate->receiving_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_activate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_activate->controlling_user_number.length = 0;
mwi_activate->number_of_messages_present = 0;
mwi_activate->controlling_user_provided_number.length = 0;
mwi_activate->time_present = 0;
mwi_activate->message_id_present = 0;
mwi_activate->mode_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
explicit_end, &mwi_activate->controlling_user_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
&value));
mwi_activate->number_of_messages = value;
mwi_activate->number_of_messages_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
pos, explicit_end, &mwi_activate->controlling_user_provided_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
sizeof(mwi_activate->time.str), mwi_activate->time.str, &str_len));
mwi_activate->time_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
explicit_end, &mwi_activate->message_id));
mwi_activate->message_id_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, explicit_end, &value));
mwi_activate->mode = value;
mwi_activate->mode_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIDeactivate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
struct roseEtsiMWIDeactivate_ARG *mwi_deactivate;
mwi_deactivate = &args->etsi.MWIDeactivate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIDeactivate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "receivingUserNr", tag, pos, seq_end,
&mwi_deactivate->receiving_user_number));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, seq_end, &value));
mwi_deactivate->basic_service = value;
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_deactivate->controlling_user_number.length = 0;
mwi_deactivate->mode_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
default:
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
seq_end, &mwi_deactivate->controlling_user_number));
break;
case ASN1_TYPE_ENUMERATED:
ASN1_CALL(pos, asn1_dec_int(ctrl, "mode", tag, pos, seq_end, &value));
mwi_deactivate->mode = value;
mwi_deactivate->mode_present = 1;
break;
}
}
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the MWIIndicate invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args)
{
int32_t value;
size_t str_len;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
struct roseEtsiMWIIndicate_ARG *mwi_indicate;
mwi_indicate = &args->etsi.MWIIndicate;
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " MWIIndicate %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
mwi_indicate->controlling_user_number.length = 0;
mwi_indicate->basic_service_present = 0;
mwi_indicate->number_of_messages_present = 0;
mwi_indicate->controlling_user_provided_number.length = 0;
mwi_indicate->time_present = 0;
mwi_indicate->message_id_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserNr", tag, pos,
explicit_end, &mwi_indicate->controlling_user_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
ASN1_CALL(pos, asn1_dec_int(ctrl, "basicService", tag, pos, explicit_end,
&value));
mwi_indicate->basic_service = value;
mwi_indicate->basic_service_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
ASN1_CALL(pos, asn1_dec_int(ctrl, "numberOfMessages", tag, pos, explicit_end,
&value));
mwi_indicate->number_of_messages = value;
mwi_indicate->number_of_messages_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "controllingUserProvidedNr", tag,
pos, explicit_end, &mwi_indicate->controlling_user_provided_number));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_TYPE_GENERALIZED_TIME);
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "time", tag, pos, explicit_end,
sizeof(mwi_indicate->time.str), mwi_indicate->time.str, &str_len));
mwi_indicate->time_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 6:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_etsi_message_id(ctrl, "messageId", tag, pos,
explicit_end, &mwi_indicate->message_id));
mwi_indicate->message_id_present = 1;
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/* ------------------------------------------------------------------- */
/* end rose_etsi_mwi.c */

View File

@ -367,6 +367,24 @@ const unsigned char *rose_dec_etsi_CCNR_T_Request_RES(struct pri *ctrl, unsigned
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Message Waiting Indication (MWI) */
unsigned char *rose_enc_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIActivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_MWIIndicate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG Name-Operations */
unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigName *name);

View File

@ -126,7 +126,7 @@ unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *po
}
if (mwi_activate->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
mwi_activate->timestamp, sizeof(mwi_activate->timestamp) - 1));
mwi_activate->timestamp.str, sizeof(mwi_activate->timestamp.str) - 1));
}
if (mwi_activate->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
@ -254,7 +254,7 @@ static unsigned char *rose_enc_qsig_MWIInterrogateResElt(struct pri *ctrl,
}
if (record->timestamp_present) {
ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_TYPE_GENERALIZED_TIME,
record->timestamp, sizeof(record->timestamp) - 1));
record->timestamp.str, sizeof(record->timestamp.str) - 1));
}
if (record->priority_present) {
ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5,
@ -450,7 +450,8 @@ const unsigned char *rose_dec_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned ta
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(mwi_activate->timestamp), mwi_activate->timestamp, &str_len));
sizeof(mwi_activate->timestamp.str), mwi_activate->timestamp.str,
&str_len));
mwi_activate->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
@ -710,7 +711,7 @@ static const unsigned char *rose_dec_qsig_MWIInterrogateResElt(struct pri *ctrl,
break;
case ASN1_TYPE_GENERALIZED_TIME:
ASN1_CALL(pos, asn1_dec_string_max(ctrl, "timestamp", tag, pos, end,
sizeof(record->timestamp), record->timestamp, &str_len));
sizeof(record->timestamp.str), record->timestamp.str, &str_len));
record->timestamp_present = 1;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 5:

View File

@ -1396,6 +1396,91 @@ static const struct rose_message rose_etsi_msgs[] = {
.component.invoke.operation = ROSE_ETSI_MCIDRequest,
.component.invoke.invoke_id = 54,
},
/* MWI */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIActivate,
.component.invoke.invoke_id = 55,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.plan = 8,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.length = 4,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.str = "6229",
.component.invoke.args.etsi.MWIActivate.basic_service = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIActivate,
.component.invoke.invoke_id = 56,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.plan = 8,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.length = 4,
.component.invoke.args.etsi.MWIActivate.receiving_user_number.str = "6229",
.component.invoke.args.etsi.MWIActivate.basic_service = 3,
.component.invoke.args.etsi.MWIActivate.controlling_user_number.plan = 8,
.component.invoke.args.etsi.MWIActivate.controlling_user_number.length = 4,
.component.invoke.args.etsi.MWIActivate.controlling_user_number.str = "6229",
.component.invoke.args.etsi.MWIActivate.number_of_messages_present = 1,
.component.invoke.args.etsi.MWIActivate.number_of_messages = 7,
.component.invoke.args.etsi.MWIActivate.controlling_user_provided_number.plan = 8,
.component.invoke.args.etsi.MWIActivate.controlling_user_provided_number.length = 4,
.component.invoke.args.etsi.MWIActivate.controlling_user_provided_number.str = "6229",
.component.invoke.args.etsi.MWIActivate.time_present = 1,
.component.invoke.args.etsi.MWIActivate.time.str = "19970621194530",
.component.invoke.args.etsi.MWIActivate.message_id_present = 1,
.component.invoke.args.etsi.MWIActivate.message_id.reference_number = 98,
.component.invoke.args.etsi.MWIActivate.message_id.status = 1,
.component.invoke.args.etsi.MWIActivate.mode_present = 1,
.component.invoke.args.etsi.MWIActivate.mode = 2,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIDeactivate,
.component.invoke.invoke_id = 57,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.plan = 8,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.length = 4,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.str = "6229",
.component.invoke.args.etsi.MWIDeactivate.basic_service = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIDeactivate,
.component.invoke.invoke_id = 58,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.plan = 8,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.length = 4,
.component.invoke.args.etsi.MWIDeactivate.receiving_user_number.str = "6229",
.component.invoke.args.etsi.MWIDeactivate.basic_service = 3,
.component.invoke.args.etsi.MWIDeactivate.controlling_user_number.plan = 8,
.component.invoke.args.etsi.MWIDeactivate.controlling_user_number.length = 4,
.component.invoke.args.etsi.MWIDeactivate.controlling_user_number.str = "6229",
.component.invoke.args.etsi.MWIDeactivate.mode_present = 1,
.component.invoke.args.etsi.MWIDeactivate.mode = 2,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIIndicate,
.component.invoke.invoke_id = 59,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_MWIIndicate,
.component.invoke.invoke_id = 60,
.component.invoke.args.etsi.MWIIndicate.controlling_user_number.plan = 8,
.component.invoke.args.etsi.MWIIndicate.controlling_user_number.length = 4,
.component.invoke.args.etsi.MWIIndicate.controlling_user_number.str = "6229",
.component.invoke.args.etsi.MWIIndicate.basic_service_present = 1,
.component.invoke.args.etsi.MWIIndicate.basic_service = 3,
.component.invoke.args.etsi.MWIIndicate.number_of_messages_present = 1,
.component.invoke.args.etsi.MWIIndicate.number_of_messages = 7,
.component.invoke.args.etsi.MWIIndicate.controlling_user_provided_number.plan = 8,
.component.invoke.args.etsi.MWIIndicate.controlling_user_provided_number.length = 4,
.component.invoke.args.etsi.MWIIndicate.controlling_user_provided_number.str = "6229",
.component.invoke.args.etsi.MWIIndicate.time_present = 1,
.component.invoke.args.etsi.MWIIndicate.time.str = "19970621194530",
.component.invoke.args.etsi.MWIIndicate.message_id_present = 1,
.component.invoke.args.etsi.MWIIndicate.message_id.reference_number = 98,
.component.invoke.args.etsi.MWIIndicate.message_id.status = 1,
},
/* *INDENT-ON* */
};
@ -2610,7 +2695,7 @@ static const struct rose_message rose_qsig_msgs[] = {
.component.invoke.args.qsig.MWIActivate.originating_number.length = 4,
.component.invoke.args.qsig.MWIActivate.originating_number.str = "9838",
.component.invoke.args.qsig.MWIActivate.timestamp_present = 1,
.component.invoke.args.qsig.MWIActivate.timestamp = "19970621194530",
.component.invoke.args.qsig.MWIActivate.timestamp.str = "19970621194530",
.component.invoke.args.qsig.MWIActivate.priority_present = 1,
.component.invoke.args.qsig.MWIActivate.priority = 7,
},
@ -2690,7 +2775,7 @@ static const struct rose_message rose_qsig_msgs[] = {
.component.result.args.qsig.MWIInterrogate.list[0].originating_number.length = 4,
.component.result.args.qsig.MWIInterrogate.list[0].originating_number.str = "9838",
.component.result.args.qsig.MWIInterrogate.list[0].timestamp_present = 1,
.component.result.args.qsig.MWIInterrogate.list[0].timestamp = "19970621194530",
.component.result.args.qsig.MWIInterrogate.list[0].timestamp.str = "19970621194530",
.component.result.args.qsig.MWIInterrogate.list[0].priority_present = 1,
.component.result.args.qsig.MWIInterrogate.list[0].priority = 7,
.component.result.args.qsig.MWIInterrogate.list[1].basic_service = 1,