Index: doc/userguide/userguide.xml
===================================================================
RCS file: /home/cvs/gateway/doc/userguide/userguide.xml,v
retrieving revision 1.350
diff -u -b -w -r1.350 userguide.xml
--- doc/userguide/userguide.xml 25 May 2009 15:19:35 -0000 1.350
+++ doc/userguide/userguide.xml 9 Jun 2009 14:01:24 -0000
@@ -4080,38 +4080,209 @@
Password for username, if needed.
+
+
+
+The "generic" system-type
+
+ For a generic HTTP-based relay, the system-type 'generic' can be used.
+ It can use the escape codes known from sms-service's get-url config
+ directives in the send-url string to indicate the HTTP API calling style of
+ the remote HTTP server, and the 3 HTTP body response parsing regular
+ expressions 'status-success-regex' for successfull acknowledge,
+ 'status-permfail-regex' for permanent failure and 'status-tempfail-regex'
+ for temporary failure. It can also accomodate the incoming parameters and response
+ codes and text. This system-type has a lot of extra parameters that gives it a lot
+ of flexibility:
+
+
+
+
+
+ Variable
+ Value
+ Description
+
status-success-regex (o)
POSIX regular expression
- Regular expression for system-type 'generic' to match against HTTP
+ Regular expression to match against HTTP
response body conent, indicating a successfull submission.
status-permfail-regex (o)
POSIX regular expression
- Regular expression for system-type 'generic' to match against HTTP
+ Regular expression to match against HTTP
response body conent, indicating a permanent failure.
status-tempfail-regex (o)
POSIX regular expression
- Regular expression for system-type 'generic' to match against HTTP
+ Regular expression to match against HTTP
response body conent, indicating a temporary failure.
+ generic-param-username (o)
+ string
+
+ Overrides the default parameter for the 'username'
+ field used on incoming requests.
+
+
+ generic-param-password (o)
+ string
+
+ Overrides the default parameter for the 'password'
+ field used on incoming requests.
+
+
+ generic-param-from (o)
+ string
+
+ Overrides the default parameter for the 'from' field
+ used on incoming requests.
+
+
+ generic-param-to (o)
+ string
+
+ Overrides the default parameter for the 'to' field
+ used on incoming requests.
+
+
+ generic-param-text (o)
+ string
+
+ Overrides the default parameter for the 'text' field
+ used on incoming requests.
+
+
+ generic-param-udh (o)
+ string
+
+ Overrides the default parameter for the 'udh' field
+ used on incoming requests.
+
+
+ generic-param-service (o)
+ string
+
+ Overrides the default parameter for the 'service' field
+ used on incoming requests.
+
+
+ generic-param-account (o)
+ string
+
+ Overrides the default parameter for the 'account' field
+ used on incoming requests.
+
+
+ generic-param-binfo (o)
+ string
+
+ Overrides the default parameter for the 'binfo' field
+ used on incoming requests.
+
+
+ generic-param-dlr-mask (o)
+ string
+
+ Overrides the default parameter for the 'dlr-mask' field
+ used on incoming requests.
+
+
+ generic-param-dlr-url (o)
+ string
+
+ Overrides the default parameter for the 'dlr-url' field
+ used on incoming requests.
+
+
+ generic-param-dlr-mid (o)
+ string
+
+ Overrides the default parameter for the 'dlr-mid' field
+ used on incoming requests.
+
+
+ generic-param-flash (o)
+ string
+
+ Overrides the default parameter for the 'flash' field
+ used on incoming requests.
+
+
+ generic-param-mclass (o)
+ string
+
+ Overrides the default parameter for the 'mclass' field
+ used on incoming requests.
+
+
+ generic-param-mwi (o)
+ string
+
+ Overrides the default parameter for the 'mwi' field
+ used on incoming requests.
+
+
+ generic-param-coding (o)
+ string
+
+ Overrides the default parameter for the 'coding' field
+ used on incoming requests.
+
+
+ generic-param-validity (o)
+ string
+
+ Overrides the default parameter for the 'validity' field
+ used on incoming requests.
+
+
+ generic-param-deferred (o)
+ string
+
+ Overrides the default parameter for the 'deferred' field
+ used on incoming requests.
+
+
+ generic-param-foreign-id (o)
+ string
+
+ Overrides the default parameter for the 'foreign-id' field
+ used on incoming requests.
+
+
+ generic-message-sent (o)
+ string
+
+ It allows you to set the text returned when a succesful request is made.
+ If not set, defaults to 'Sent.'. Note that you can use all sms service escapes
+ here, see for details.
+
+
+ generic-status-sent (o)
+ string
+
+ Overrides the HTTP status code returned when a successful
+ request is made. If not set, defaults to 202 (HTTP_ACCEPTED).
+
+
+ generic-status-error (o)
+ string
+
+ Overrides the HTTP status code returned when a request is
+ rejected for any reason. If not set, defaults to 202 (HTTP_ACCEPTED).
+
+
- For a generic HTTP-based relay, the system-type 'generic' can be used.
- It can use the escape codes known from sms-service's get-url config
- directives in the send-url string to indicate the HTTP API calling style of
- the remote HTTP server, and the 3 HTTP body response parsing regular
- expressions 'status-success-regex' for successfull acknowledge,
- 'status-permfail-regex' for permanent failure and 'status-tempfail-regex'
- for temporary failure. An example for a 'generic' group looks like this:
-
+ An example for a 'generic' group looks like this:
group = smsc
@@ -4122,14 +4293,13 @@
status-success-regex = "ok"
status-permfail-regex = "failure"
status-tempfail-regex = "retry later"
+generic-param-from = "phoneNumber"
+generic-param-to = "shortCode"
+generic-message-sent = "Message sent with ID: %I"
+generic-status-sent = 200
+generic-status-error = 404
-
- Beware that this generic HTTP system-type is for MT only. We don't
- provide a way for the MO side too. For MO traffic we simply expect the
- remote HTTP caller to use Kannel's sendsms HTTP API on the given port to
- inject MO messages.
-
-
+
@@ -6120,8 +6290,8 @@
-
- Parameters (Escape Codes)
+
+ Parameters (Escape Codes)
Index: gw/smsc/smsc_http.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_http.c,v
retrieving revision 1.61
diff -u -b -w -r1.61 smsc_http.c
--- gw/smsc/smsc_http.c 14 Jan 2009 11:11:46 -0000 1.61
+++ gw/smsc/smsc_http.c 9 Jun 2009 14:01:27 -0000
@@ -129,8 +129,37 @@
#define DEFAULT_CHARSET "UTF-8"
+/*
+ * This maps fields to values for MO parameters
+ */
+typedef struct fieldmap {
+ Octstr *username;
+ Octstr *password;
+ Octstr *from;
+ Octstr *to;
+ Octstr *text;
+ Octstr *udh;
+ Octstr *service;
+ Octstr *account;
+ Octstr *binfo;
+ Octstr *dlr_mask;
+ Octstr *dlr_url;
+ Octstr *dlr_mid;
+ Octstr *flash;
+ Octstr *mclass;
+ Octstr *mwi;
+ Octstr *coding;
+ Octstr *validity;
+ Octstr *deferred;
+ Octstr *foreign_id;
+ Octstr *message_sent;
+ long status_sent;
+ long status_error;
+} FieldMap;
+
typedef struct conndata {
HTTPCaller *http_ref;
+ FieldMap *fieldmap;
long receive_thread;
long send_cb_thread;
int shutdown;
@@ -165,6 +194,37 @@
} ConnData;
+/*
+ * Destroys the FieldMap structure
+ */
+static void fieldmap_destroy(FieldMap *fieldmap)
+{
+ if (fieldmap == NULL)
+ return;
+ octstr_destroy(fieldmap->username);
+ octstr_destroy(fieldmap->password);
+ octstr_destroy(fieldmap->from);
+ octstr_destroy(fieldmap->to);
+ octstr_destroy(fieldmap->text);
+ octstr_destroy(fieldmap->udh);
+ octstr_destroy(fieldmap->service);
+ octstr_destroy(fieldmap->account);
+ octstr_destroy(fieldmap->binfo);
+ octstr_destroy(fieldmap->dlr_mask);
+ octstr_destroy(fieldmap->dlr_url);
+ octstr_destroy(fieldmap->dlr_mid);
+ octstr_destroy(fieldmap->flash);
+ octstr_destroy(fieldmap->mclass);
+ octstr_destroy(fieldmap->mwi);
+ octstr_destroy(fieldmap->coding);
+ octstr_destroy(fieldmap->validity);
+ octstr_destroy(fieldmap->deferred);
+ octstr_destroy(fieldmap->foreign_id);
+ octstr_destroy(fieldmap->message_sent);
+ gw_free(fieldmap);
+}
+
+
static void conndata_destroy(ConnData *conndata)
{
if (conndata == NULL)
@@ -177,6 +237,7 @@
gw_regex_destroy(conndata->permfail_regex);
if (conndata->tempfail_regex)
gw_regex_destroy(conndata->tempfail_regex);
+ fieldmap_destroy(conndata->fieldmap);
octstr_destroy(conndata->allow_ip);
octstr_destroy(conndata->send_url);
octstr_destroy(conndata->dlr_url);
@@ -1454,7 +1515,7 @@
/*----------------------------------------------------------------
- * (Semi-)generic HTTP interface
+ * Generic HTTP interface
*
* This 'generic' type will handle the 'send-url' directive in the
* group the same way the 'sms-service' for smsbox does, via
@@ -1462,12 +1523,6 @@
* regex value that match against the reponse body. The HTTP reponse
* code is not obeyed.
*
- * It handles mainly MT messages, due to the fact that MO traffic
- * can't be abstracted in a universal way. Therefor we use the
- * Kannel sendsms interface layout as generic fallback. So if your
- * SMSC provider needs to send MO messages, he needs to implement
- * the Kannel sendsms HTTP interface variables.
- *
* Example config group:
*
* group = smsc
@@ -1477,12 +1532,267 @@
* status-success-regex = "ok"
* status-permfail-regex = "failure"
* status-tempfail-regex = "retry later"
+ * generic-param-from = "phoneNumber"
+ * generic-param-to = "shortCode"
+ * generic-param-text = "message"
+ * generic-message-sent = "OK"
+ * generic-status-sent = 200
+ * generic-status-error = 400
*
* Note that neither 'smsc-username' nor 'smsc-password' is required,
* since they are coded into the the 'send-url' value directly.
*
* Stipe Tolj
+ *
+ * MO processing by Alejandro Guerrieri
+ */
+
+/*
+ * Get the FieldMap struct to map MO parameters
*/
+static FieldMap *generic_get_field_map(CfgGroup *grp)
+{
+ FieldMap *fm = NULL;
+ fm = gw_malloc(sizeof(FieldMap));
+ gw_assert(fm != NULL);
+ fm->username = cfg_get(grp, octstr_imm("generic-param-username"));
+ if (fm->username == NULL)
+ fm->username = octstr_create("username");
+ fm->password = cfg_get(grp, octstr_imm("generic-param-password"));
+ if (fm->password == NULL)
+ fm->password = octstr_create("password");
+ fm->from = cfg_get(grp, octstr_imm("generic-param-from"));
+ if (fm->from == NULL)
+ fm->from = octstr_create("from");
+ fm->to = cfg_get(grp, octstr_imm("generic-param-to"));
+ if (fm->to == NULL)
+ fm->to = octstr_create("to");
+ fm->text = cfg_get(grp, octstr_imm("generic-param-text"));
+ if (fm->text == NULL)
+ fm->text = octstr_create("text");
+ fm->udh = cfg_get(grp, octstr_imm("generic-param-udh"));
+ if (fm->udh == NULL)
+ fm->udh = octstr_create("udh");
+ /* "service" preloads the "username" parameter to mimic former behaviour */
+ fm->service = cfg_get(grp, octstr_imm("generic-param-service"));
+ if (fm->service == NULL)
+ fm->service = octstr_create("username");
+ fm->account = cfg_get(grp, octstr_imm("generic-param-account"));
+ if (fm->account == NULL)
+ fm->account = octstr_create("account");
+ fm->binfo = cfg_get(grp, octstr_imm("generic-param-binfo"));
+ if (fm->binfo == NULL)
+ fm->binfo = octstr_create("binfo");
+ fm->dlr_mask = cfg_get(grp, octstr_imm("generic-param-dlr-mask"));
+ if (fm->dlr_mask == NULL)
+ fm->dlr_mask = octstr_create("dlr-mask");
+ fm->dlr_url = cfg_get(grp, octstr_imm("generic-param-dlr-url"));
+ if (fm->dlr_url == NULL)
+ fm->dlr_url = octstr_create("dlr-url");
+ fm->dlr_mid = cfg_get(grp, octstr_imm("generic-param-dlr-mid"));
+ if (fm->dlr_mid == NULL)
+ fm->dlr_mid = octstr_create("dlr-mid");
+ fm->flash = cfg_get(grp, octstr_imm("generic-param-flash"));
+ if (fm->flash == NULL)
+ fm->flash = octstr_create("flash");
+ fm->mclass = cfg_get(grp, octstr_imm("generic-param-mclass"));
+ if (fm->mclass == NULL)
+ fm->mclass = octstr_create("mclass");
+ fm->mwi = cfg_get(grp, octstr_imm("generic-param-mwi"));
+ if (fm->mwi == NULL)
+ fm->mwi = octstr_create("mwi");
+ fm->coding = cfg_get(grp, octstr_imm("generic-param-coding"));
+ if (fm->coding == NULL)
+ fm->coding = octstr_create("coding");
+ fm->validity = cfg_get(grp, octstr_imm("generic-param-validity"));
+ if (fm->validity == NULL)
+ fm->validity = octstr_create("validity");
+ fm->deferred = cfg_get(grp, octstr_imm("generic-param-deferred"));
+ if (fm->deferred == NULL)
+ fm->deferred = octstr_create("deferred");
+ fm->foreign_id = cfg_get(grp, octstr_imm("generic-param-foreign-id"));
+ if (fm->foreign_id == NULL)
+ fm->foreign_id = octstr_create("foreign-id");
+ fm->message_sent = cfg_get(grp, octstr_imm("generic-message-sent"));
+ if (fm->message_sent == NULL)
+ fm->message_sent = octstr_create("Sent");
+ /* both success and error uses HTTP_ACCEPTED to mimic former behaviour */
+ if (cfg_get_integer(&fm->status_sent, grp, octstr_imm("generic-status-sent")) == -1) {
+ fm->status_sent = HTTP_ACCEPTED;
+ }
+ if (cfg_get_integer(&fm->status_error, grp, octstr_imm("generic-status-error")) == -1) {
+ fm->status_error = HTTP_ACCEPTED;
+ }
+
+ return fm;
+}
+
+static void generic_receive_sms(SMSCConn *conn, HTTPClient *client,
+ List *headers, Octstr *body, List *cgivars)
+{
+ ConnData *conndata = conn->data;
+ FieldMap *fm = conndata->fieldmap;
+ Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo;
+ Octstr *dlrurl, *dlrmid;
+ Octstr *tmp_string, *retmsg;
+ int mclass, mwi, coding, validity, deferred, dlrmask;
+ List *reply_headers;
+ int ret, retstatus;
+
+ mclass = mwi = coding = validity =
+ deferred = dlrmask = SMS_PARAM_UNDEFINED;
+
+ /* Parse enough parameters to validate the request */
+ user = http_cgi_variable(cgivars, octstr_get_cstr(fm->username));
+ pass = http_cgi_variable(cgivars, octstr_get_cstr(fm->password));
+ from = http_cgi_variable(cgivars, octstr_get_cstr(fm->from));
+ to = http_cgi_variable(cgivars, octstr_get_cstr(fm->to));
+ text = http_cgi_variable(cgivars, octstr_get_cstr(fm->text));
+ udh = http_cgi_variable(cgivars, octstr_get_cstr(fm->udh));
+ dlrurl = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_url));
+ dlrmid = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mid));
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->dlr_mask));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
+ }
+ debug("smsc.http.kannel", 0, "HTTP[%s]: Received an HTTP request",
+ octstr_get_cstr(conn->id));
+
+ if ((conndata->username != NULL && conndata->password != NULL) &&
+ (user == NULL || pass == NULL ||
+ octstr_compare(user, conndata->username) != 0 ||
+ octstr_compare(pass, conndata->password) != 0)) {
+ error(0, "HTTP[%s]: Authorization failure",
+ octstr_get_cstr(conn->id));
+ retmsg = octstr_create("Authorization failed for sendsms");
+ retstatus = fm->status_error;
+ }
+ else if (dlrmask != 0 && dlrmid != NULL) {
+ /* we got a DLR, and we don't require additional values */
+ Msg *dlrmsg;
+
+ dlrmsg = dlr_find(conn->id,
+ dlrmid, /* message id */
+ to, /* destination */
+ dlrmask);
+
+ if (dlrmsg != NULL) {
+ dlrmsg->sms.sms_type = report_mo;
+
+ debug("smsc.http.kannel", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
+ octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
+
+ Msg *resp = msg_duplicate(dlrmsg);
+ ret = bb_smscconn_receive(conn, dlrmsg);
+ if (ret == -1) {
+ retmsg = octstr_create("Not accepted");
+ retstatus = fm->status_error;
+ } else {
+ retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
+ retstatus = fm->status_sent;
+ }
+ msg_destroy(resp);
+ } else {
+ error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
+ "in it id<%s> dst<%s>, type<%d>",
+ octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
+ octstr_get_cstr(to), dlrmask);
+ retmsg = octstr_create("Unknown DLR, not accepted");
+ retstatus = fm->status_error;
+ }
+ }
+ else if (from == NULL || to == NULL || text == NULL) {
+ error(0, "HTTP[%s]: Insufficient args",
+ octstr_get_cstr(conn->id));
+ retmsg = octstr_create("Insufficient args, rejected");
+ retstatus = fm->status_error;
+ }
+ else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
+ error(0, "HTTP[%s]: UDH field misformed, rejected",
+ octstr_get_cstr(conn->id));
+ retmsg = octstr_create("UDH field misformed, rejected");
+ retstatus = fm->status_error;
+ }
+ else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
+ error(0, "HTTP[%s]: UDH field is too long, rejected",
+ octstr_get_cstr(conn->id));
+ retmsg = octstr_create("UDH field is too long, rejected");
+ retstatus = fm->status_error;
+ }
+ else {
+ /* we got a normal MO SMS */
+ Msg *msg;
+ msg = msg_create(sms);
+
+ /* Parse the rest of the parameters */
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->flash));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.mclass);
+ }
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mclass));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.mclass);
+ }
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->mwi));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.mwi);
+ }
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->coding));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.coding);
+ }
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->validity));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.validity);
+ }
+ tmp_string = http_cgi_variable(cgivars, octstr_get_cstr(fm->deferred));
+ if (tmp_string) {
+ sscanf(octstr_get_cstr(tmp_string),"%d", &msg->sms.deferred);
+ }
+ account = http_cgi_variable(cgivars, octstr_get_cstr(fm->account));
+ binfo = http_cgi_variable(cgivars, octstr_get_cstr(fm->binfo));
+
+ debug("smsc.http.kannel", 0, "HTTP[%s]: Constructing new SMS",
+ octstr_get_cstr(conn->id));
+
+ /* convert character encoding if required */
+ if (conndata->alt_charset &&
+ charset_convert(text, octstr_get_cstr(conndata->alt_charset),
+ DEFAULT_CHARSET) != 0)
+ error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave it as it is.",
+ octstr_get_cstr(conndata->alt_charset), DEFAULT_CHARSET);
+
+ msg->sms.service = octstr_duplicate(user);
+ msg->sms.sender = octstr_duplicate(from);
+ msg->sms.receiver = octstr_duplicate(to);
+ msg->sms.msgdata = octstr_duplicate(text);
+ msg->sms.udhdata = octstr_duplicate(udh);
+ msg->sms.smsc_id = octstr_duplicate(conn->id);
+ msg->sms.time = time(NULL);
+ msg->sms.account = octstr_duplicate(account);
+ msg->sms.binfo = octstr_duplicate(binfo);
+ Msg *resp = msg_duplicate(msg);
+ ret = bb_smscconn_receive(conn, msg);
+ if (ret == -1) {
+ retmsg = octstr_create("Not accepted");
+ retstatus = fm->status_error;
+ } else {
+ retmsg = urltrans_fill_escape_codes(fm->message_sent, resp);
+ retstatus = fm->status_sent;
+ }
+ msg_destroy(resp);
+ }
+
+ reply_headers = gwlist_create();
+ http_header_add(reply_headers, "Content-Type", "text/plain");
+ debug("smsc.http.kannel", 0, "HTTP[%s]: Sending reply",
+ octstr_get_cstr(conn->id));
+ http_send_reply(client, retstatus, reply_headers, retmsg);
+
+ octstr_destroy(retmsg);
+ http_destroy_headers(reply_headers);
+}
+
static void generic_send_sms(SMSCConn *conn, Msg *sms)
{
@@ -1635,6 +1945,7 @@
cfg_get_bool(&conndata->no_sep, cfg, octstr_imm("no-sep"));
conndata->proxy = cfg_get(cfg, octstr_imm("system-id"));
conndata->alt_charset = cfg_get(cfg, octstr_imm("alt-charset"));
+ conndata->fieldmap = NULL;
if (conndata->send_url == NULL)
panic(0, "HTTP[%s]: Sending not allowed. No 'send-url' specified.",
@@ -1693,7 +2004,8 @@
octstr_get_cstr(conn->id));
goto error;
}
- conndata->receive_sms = kannel_receive_sms; /* emulate sendsms interface */
+ conndata->fieldmap = generic_get_field_map(cfg);
+ conndata->receive_sms = generic_receive_sms; /* emulate sendsms interface */
conndata->send_sms = generic_send_sms;
conndata->parse_reply = generic_parse_reply;
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.139
diff -u -b -w -r1.139 cfg.def
--- gwlib/cfg.def 6 May 2009 18:47:34 -0000 1.139
+++ gwlib/cfg.def 9 Jun 2009 14:01:27 -0000
@@ -386,6 +386,28 @@
OCTSTR(max-sms-octets)
OCTSTR(login-prompt)
OCTSTR(password-prompt)
+ OCTSTR(generic-param-username)
+ OCTSTR(generic-param-password)
+ OCTSTR(generic-param-from)
+ OCTSTR(generic-param-to)
+ OCTSTR(generic-param-text)
+ OCTSTR(generic-param-udh)
+ OCTSTR(generic-param-service)
+ OCTSTR(generic-param-account)
+ OCTSTR(generic-param-binfo)
+ OCTSTR(generic-param-dlr-mask)
+ OCTSTR(generic-param-dlr-url)
+ OCTSTR(generic-param-dlr-mid)
+ OCTSTR(generic-param-flash)
+ OCTSTR(generic-param-mclass)
+ OCTSTR(generic-param-mwi)
+ OCTSTR(generic-param-coding)
+ OCTSTR(generic-param-validity)
+ OCTSTR(generic-param-deferred)
+ OCTSTR(generic-param-foreign-id)
+ OCTSTR(generic-message-sent)
+ OCTSTR(generic-status-sent)
+ OCTSTR(generic-status-error)
)