[PATCH] smpp optional params

Alexander Malysh <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization Centrium GmbH
Message-ID <[email protected]>
Hi,

attached you can find patch with new version of optional params handling in 
smpp pdu. With this version Dict* is killed and all opt. params are treated 
the same as mandatory and could be easier accessed. Now pack/unpack for int 
values works too.
Note: not available in pdu opt. params are initialized with '-1' for int, NULL 
for nulterminated/octet strings.

Comments/votes are highly welcome!

P.S. Patch wich adds handling of 'message_payload' and dlr handling with opt. 
params is available and will follow (please be patient;)...

-- 
Best regards / Mit besten Grüßen aus Düsseldorf

Dipl.-Ing.
Alexander Malysh
___________________________________________

Centrium GmbH
Vogelsanger Weg 80
40470 Düsseldorf

Fon: +49 (0211) 74 84 51 80
Fax: +49 (0211) 277 49 109

email: [email protected]
web: www.centrium.de
msn: [email protected]
icq: 98063111
___________________________________________

Please avoid sending me Word, Excel or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
smpp-optional-params.patch (text/x-diff, 27.1 KB)
Index: gw/smsc/smpp_pdu.def
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smpp_pdu.def,v
retrieving revision 1.7
diff -a -u -p -r1.7 smpp_pdu.def
--- gw/smsc/smpp_pdu.def	22 Jan 2004 14:08:24 -0000	1.7
+++ gw/smsc/smpp_pdu.def	23 Mar 2004 13:55:22 -0000
@@ -58,29 +58,15 @@
  * smpp_pdu.def - definitions of SMPP PDU structure
  *
  * Lars Wirzenius
+ * Daniel Lukic <[email protected]>:
+ *     Initial optional parameters implementation.
+ * Alexander Malysh <[email protected]>:
+ *     Extended optional parameters implementation.
  */
 
-/*
- * Remarks by Daniel Lukic <[email protected]>:
- * 
- * 1. submit_multi does not handle unsuccess_sme(s). A "MULTIPLE" macro would be
- * needed. No time for that now. Maybe switch to some kind of reg-ex handling?
- */
 
 #include "smpp_pdu_opt.def"
 
-/*
- * XXX Implementation note:
- * 
- * The PDUs bind_transmitter_resp, bind_receiver_resp, and submit_sm_resp
- * contain a body part that is not optional, but on the other hand is only
- * included if the command_status field is zero. The way this is handled at
- * the moment is that the body is not included in the PDU description in
- * this file, so it is always ignored. This is OK because it is not being
- * used anyway. In the future the body will be needed, and so this will
- * be implemented in a better way then.
- */
-
 
 #ifndef PDU
 #error Macro PDU not defined.
@@ -102,8 +88,16 @@
 #error Macro OPTIONAL_BEGIN not defined.
 #endif
 
-#ifndef TLV
-#error Macro TLV not defined.
+#ifndef TLV_INTEGER
+#error Macro TLV_INTEGER not defined.
+#endif
+
+#ifndef TLV_NULTERMINATED
+#error Macro TLV_NULTERMINATED not defined.
+#endif
+
+#ifndef TLV_OCTETS
+#error Macro TLV_OCTETS not defined.
 #endif
 
 #ifndef OPTIONAL_END
@@ -120,9 +114,9 @@
 #error Macro HEADER was already defined.
 #endif
 #define HEADER	\
-	INTEGER(command_id, 4) \
-	INTEGER(command_status, 4) \
-	INTEGER(sequence_number, 4)
+    INTEGER(command_id, 4) \
+    INTEGER(command_status, 4) \
+    INTEGER(sequence_number, 4)
 
 PDU(bind_transmitter,
     0x00000002,
@@ -140,8 +134,8 @@ PDU(bind_transmitter_resp,
     0x80000002,
     HEADER
     NULTERMINATED(system_id, 16)
-    OPTIONAL_BEGIN(1)
-    TLV(SMPP_SC_interface_version, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(sc_interface_version, 1)
     OPTIONAL_END
 )
 
@@ -161,8 +155,8 @@ PDU(bind_receiver_resp,
     0x80000001,
     HEADER
     NULTERMINATED(system_id, 16)
-    OPTIONAL_BEGIN(1)
-    TLV(SMPP_SC_interface_version, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(sc_interface_version, 1)
     OPTIONAL_END
 )
 
@@ -182,8 +176,8 @@ PDU(bind_transceiver_resp,
     0x80000009,
     HEADER
     NULTERMINATED(system_id, 16)
-    OPTIONAL_BEGIN(1)
-    TLV(SMPP_SC_interface_version, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(sc_interface_version, 1)
     OPTIONAL_END
 )
 
@@ -230,35 +224,35 @@ PDU(submit_sm,
     INTEGER(sm_default_msg_id, 1)
     INTEGER(sm_length, 1)
     OCTETS(short_message, sm_length)
-    OPTIONAL_BEGIN(28)
-    TLV(SMPP_user_message_reference, 2, 2)
-    TLV(SMPP_source_port, 2, 2)
-    TLV(SMPP_source_addr_subunit, 1, 1)
-    TLV(SMPP_destination_port, 2, 2)
-    TLV(SMPP_dest_addr_subunit, 1, 1)
-    TLV(SMPP_sar_msg_ref_num, 2, 2)
-    TLV(SMPP_sar_total_segments, 1, 1)
-    TLV(SMPP_sar_segment_seqnum, 1, 1)
-    TLV(SMPP_more_messages_to_send, 1, 1)
-    TLV(SMPP_payload_type, 1, 1)
-    TLV(SMPP_message_payload, 0, 65536)
-    TLV(SMPP_privacy_indicator, 1, 1)
-    TLV(SMPP_callback_num, 4, 19)
-    TLV(SMPP_callback_num_pres_ind, 1, 1)
-    TLV(SMPP_callback_num_atag, 0, 65)
-    TLV(SMPP_source_subaddress, 2, 23)
-    TLV(SMPP_dest_subaddress, 2, 23)
-    TLV(SMPP_user_response_code, 1, 1)
-    TLV(SMPP_display_time, 1, 1)
-    TLV(SMPP_sms_signal, 2, 2)
-    TLV(SMPP_ms_validity, 1, 1)
-    TLV(SMPP_ms_msg_wait_facilities, 1, 1)
-    TLV(SMPP_number_of_messages, 1, 1)
-    TLV(SMPP_alert_on_message_delivery, 0, 0)
-    TLV(SMPP_language_indicator, 1, 1)
-    TLV(SMPP_its_reply_type, 1, 1)
-    TLV(SMPP_its_session_info, 2, 2)
-    TLV(SMPP_ussd_service_op, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(user_message_reference, 2)
+    TLV_INTEGER(source_port, 2)
+    TLV_INTEGER(source_addr_subunit, 1)
+    TLV_INTEGER(destination_port, 2)
+    TLV_INTEGER(dest_addr_subunit, 1)
+    TLV_INTEGER(sar_msg_ref_num, 2)
+    TLV_INTEGER(sar_total_segments, 1)
+    TLV_INTEGER(sar_segment_seqnum, 1)
+    TLV_INTEGER(more_messages_to_send, 1)
+    TLV_INTEGER(payload_type, 1)
+    TLV_OCTETS(message_payload, 0, 65536)
+    TLV_INTEGER(privacy_indicator, 1)
+    TLV_OCTETS(callback_num, 4, 19)
+    TLV_INTEGER(callback_num_pres_ind, 1)
+    TLV_OCTETS(callback_num_atag, 0, 65)
+    TLV_OCTETS(source_subaddress, 2, 23)
+    TLV_OCTETS(dest_subaddress, 2, 23)
+    TLV_INTEGER(user_response_code, 1)
+    TLV_INTEGER(display_time, 1)
+    TLV_INTEGER(sms_signal, 2)
+    TLV_INTEGER(ms_validity, 1)
+    TLV_INTEGER(ms_msg_wait_facilities, 1)
+    TLV_INTEGER(number_of_messages, 1)
+    TLV_INTEGER(alert_on_message_delivery, 0)
+    TLV_INTEGER(language_indicator, 1)
+    TLV_INTEGER(its_reply_type, 1)
+    TLV_OCTETS(its_session_info, 2, 2)
+    TLV_OCTETS(ussd_service_op, 1, 1)
     OPTIONAL_END
 )
 
@@ -288,29 +282,29 @@ PDU(submit_multi,
     INTEGER(sm_default_msg_id, 1)
     INTEGER(sm_length, 1)
     OCTETS(short_message, sm_length)
-    OPTIONAL_BEGIN(22)
-    TLV(SMPP_user_message_reference, 2, 2)
-    TLV(SMPP_source_port, 2, 2)
-    TLV(SMPP_source_addr_subunit, 1, 1)
-    TLV(SMPP_destination_port, 2, 2)
-    TLV(SMPP_dest_addr_subunit, 1, 1)
-    TLV(SMPP_sar_msg_ref_num, 2, 2)
-    TLV(SMPP_sar_total_segments, 1, 1)
-    TLV(SMPP_sar_segment_seqnum, 1, 1)
-    TLV(SMPP_payload_type, 1, 1)
-    TLV(SMPP_message_payload, 0, 65536)
-    TLV(SMPP_privacy_indicator, 1, 1)
-    TLV(SMPP_callback_num, 4, 19)
-    TLV(SMPP_callback_num_pres_ind, 1, 1)
-    TLV(SMPP_callback_num_atag, 0, 65)
-    TLV(SMPP_source_subaddress, 2, 23)
-    TLV(SMPP_dest_subaddress, 2, 23)
-    TLV(SMPP_display_time, 1, 1)
-    TLV(SMPP_sms_signal, 2, 2)
-    TLV(SMPP_ms_validity, 1, 1)
-    TLV(SMPP_ms_msg_wait_facilities, 1, 1)
-    TLV(SMPP_alert_on_message_delivery, 0, 0)
-    TLV(SMPP_language_indicator, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(user_message_reference, 2)
+    TLV_INTEGER(source_port, 2)
+    TLV_INTEGER(source_addr_subunit, 1)
+    TLV_INTEGER(destination_port, 2)
+    TLV_INTEGER(dest_addr_subunit, 1)
+    TLV_INTEGER(sar_msg_ref_num, 2)
+    TLV_INTEGER(sar_total_segments, 1)
+    TLV_INTEGER(sar_segment_seqnum, 1)
+    TLV_INTEGER(payload_type, 1)
+    TLV_OCTETS(message_payload, 0, 65536)
+    TLV_INTEGER(privacy_indicator, 1)
+    TLV_OCTETS(callback_num, 4, 19)
+    TLV_INTEGER(callback_num_pres_ind, 1)
+    TLV_OCTETS(callback_num_atag, 0, 65)
+    TLV_OCTETS(source_subaddress, 2, 23)
+    TLV_OCTETS(dest_subaddress, 2, 23)
+    TLV_INTEGER(display_time, 1)
+    TLV_INTEGER(sms_signal, 2)
+    TLV_INTEGER(ms_validity, 1)
+    TLV_INTEGER(ms_msg_wait_facilities, 1)
+    TLV_INTEGER(alert_on_message_delivery, 0)
+    TLV_INTEGER(language_indicator, 1)
     OPTIONAL_END
 )
 
@@ -342,25 +336,25 @@ PDU(deliver_sm,
     INTEGER(sm_default_msg_id, 1)
     INTEGER(sm_length, 1)
     OCTETS(short_message, sm_length)
-    OPTIONAL_BEGIN(18)
-    TLV(SMPP_user_message_reference, 2, 2)
-    TLV(SMPP_source_port, 2, 2)
-    TLV(SMPP_destination_port, 2, 2)
-    TLV(SMPP_sar_msg_ref_num, 2, 2)
-    TLV(SMPP_sar_total_segments, 1, 1)
-    TLV(SMPP_sar_segment_seqnum, 1, 1)
-    TLV(SMPP_user_response_code, 1, 1)
-    TLV(SMPP_privacy_indicator, 1, 1)
-    TLV(SMPP_payload_type, 1, 1)
-    TLV(SMPP_message_payload, 0, 65536)
-    TLV(SMPP_callback_num, 4, 19)
-    TLV(SMPP_source_subaddress, 2, 23)
-    TLV(SMPP_dest_subaddress, 2, 23)
-    TLV(SMPP_language_indicator, 1, 1)
-    TLV(SMPP_its_session_info, 2, 2)
-    TLV(SMPP_network_error_code, 3, 3)
-    TLV(SMPP_message_state, 1, 1)
-    TLV(SMPP_receipted_message_id, 1, 65)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(user_message_reference, 2)
+    TLV_INTEGER(source_port, 2)
+    TLV_INTEGER(destination_port, 2)
+    TLV_INTEGER(sar_msg_ref_num, 2)
+    TLV_INTEGER(sar_total_segments, 1)
+    TLV_INTEGER(sar_segment_seqnum, 1)
+    TLV_INTEGER(user_response_code, 1)
+    TLV_INTEGER(privacy_indicator, 1)
+    TLV_INTEGER(payload_type, 1)
+    TLV_OCTETS(message_payload, 0, 65536)
+    TLV_OCTETS(callback_num, 4, 19)
+    TLV_OCTETS(source_subaddress, 2, 23)
+    TLV_OCTETS(dest_subaddress, 2, 23)
+    TLV_INTEGER(language_indicator, 1)
+    TLV_OCTETS(its_session_info, 2, 2)
+    TLV_OCTETS(network_error_code, 3, 3)
+    TLV_INTEGER(message_state, 1)
+    TLV_NULTERMINATED(receipted_message_id, 65)
     OPTIONAL_END
 )
 
@@ -383,45 +377,45 @@ PDU(data_sm,
     INTEGER(esm_class, 1)
     INTEGER(registered_delivery, 1)
     INTEGER(data_coding, 1)
-    OPTIONAL_BEGIN(38)
-    TLV(SMPP_source_port, 2, 2)
-    TLV(SMPP_source_addr_subunit, 1, 1)
-    TLV(SMPP_source_network_type, 1, 1)
-    TLV(SMPP_source_bearer_type, 1, 1)
-    TLV(SMPP_source_telematics_id, 1, 1)
-    TLV(SMPP_destination_port, 2, 2)
-    TLV(SMPP_dest_addr_subunit, 1, 1)
-    TLV(SMPP_dest_network_type, 1, 1)
-    TLV(SMPP_dest_bearer_type, 1, 1)
-    TLV(SMPP_dest_telematics_id, 2, 2)
-    TLV(SMPP_sar_msg_ref_num, 2, 2)
-    TLV(SMPP_sar_total_segments, 1, 1)
-    TLV(SMPP_sar_segment_seqnum, 1, 1)
-    TLV(SMPP_more_messages_to_send, 1, 1)
-    TLV(SMPP_qos_time_to_live, 4, 4)
-    TLV(SMPP_payload_type, 1, 1)
-    TLV(SMPP_message_payload, 0, 65536)
-    TLV(SMPP_set_dpf, 1, 1)
-    TLV(SMPP_receipted_message_id, 1, 65)
-    TLV(SMPP_message_state, 1, 1)
-    TLV(SMPP_network_error_code, 3, 3)
-    TLV(SMPP_user_message_reference, 2, 2)
-    TLV(SMPP_privacy_indicator, 1, 1)
-    TLV(SMPP_callback_num, 4, 19)
-    TLV(SMPP_callback_num_pres_ind, 1, 1)
-    TLV(SMPP_callback_num_atag, 0, 65)
-    TLV(SMPP_source_subaddress, 2, 23)
-    TLV(SMPP_dest_subaddress, 2, 23)
-    TLV(SMPP_user_response_code, 1, 1)
-    TLV(SMPP_display_time, 1, 1)
-    TLV(SMPP_sms_signal, 2, 2)
-    TLV(SMPP_ms_validity, 1, 1)
-    TLV(SMPP_ms_msg_wait_facilities, 1, 1)
-    TLV(SMPP_number_of_messages, 1, 1)
-    TLV(SMPP_alert_on_message_delivery, 0, 0)
-    TLV(SMPP_language_indicator, 1, 1)
-    TLV(SMPP_its_reply_type, 1, 1)
-    TLV(SMPP_its_session_info, 2, 2)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(source_port, 2)
+    TLV_INTEGER(source_addr_subunit, 1)
+    TLV_INTEGER(source_network_type, 1)
+    TLV_INTEGER(source_bearer_type, 1)
+    TLV_INTEGER(source_telematics_id, 1)
+    TLV_INTEGER(destination_port, 2)
+    TLV_INTEGER(dest_addr_subunit, 1)
+    TLV_INTEGER(dest_network_type, 1)
+    TLV_INTEGER(dest_bearer_type, 1)
+    TLV_INTEGER(dest_telematics_id, 2)
+    TLV_INTEGER(sar_msg_ref_num, 2)
+    TLV_INTEGER(sar_total_segments, 1)
+    TLV_INTEGER(sar_segment_seqnum, 1)
+    TLV_INTEGER(more_messages_to_send, 1)
+    TLV_INTEGER(qos_time_to_live, 4)
+    TLV_INTEGER(payload_type, 1)
+    TLV_OCTETS(message_payload, 0, 65536)
+    TLV_INTEGER(set_dpf, 1)
+    TLV_NULTERMINATED(receipted_message_id, 65)
+    TLV_INTEGER(message_state, 1)
+    TLV_OCTETS(network_error_code, 3, 3)
+    TLV_INTEGER(user_message_reference, 2)
+    TLV_INTEGER(privacy_indicator, 1)
+    TLV_OCTETS(callback_num, 4, 19)
+    TLV_INTEGER(callback_num_pres_ind, 1)
+    TLV_OCTETS(callback_num_atag, 0, 65)
+    TLV_OCTETS(source_subaddress, 2, 23)
+    TLV_OCTETS(dest_subaddress, 2, 23)
+    TLV_INTEGER(user_response_code, 1)
+    TLV_INTEGER(display_time, 1)
+    TLV_INTEGER(sms_signal, 2)
+    TLV_INTEGER(ms_validity, 1)
+    TLV_INTEGER(ms_msg_wait_facilities, 1)
+    TLV_INTEGER(number_of_messages, 1)
+    TLV_INTEGER(alert_on_message_delivery, 0)
+    TLV_INTEGER(language_indicator, 1)
+    TLV_INTEGER(its_reply_type, 1)
+    TLV_OCTETS(its_session_info, 2, 2)
     OPTIONAL_END
 )
 
@@ -429,11 +423,11 @@ PDU(data_sm_resp,
     0x80000103,
     HEADER
     NULTERMINATED(message_id, 65)
-    OPTIONAL_BEGIN(28)
-    TLV(SMPP_delivery_failure_reason, 1, 1)
-    TLV(SMPP_network_error_code, 3, 3)
-    TLV(SMPP_additional_status_info_text, 1, 256)
-    TLV(SMPP_dpf_result, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(delivery_failure_reason, 1)
+    TLV_OCTETS(network_error_code, 3, 3)
+    TLV_NULTERMINATED(additional_status_info_text, 256)
+    TLV_INTEGER(dpf_result, 1)
     OPTIONAL_END
 )
 
@@ -513,8 +507,8 @@ PDU(alert_notification,
     INTEGER(esme_addr_ton, 1)
     INTEGER(esme_addr_npi, 1)
     NULTERMINATED(esme_addr, 65)
-    OPTIONAL_BEGIN(1)
-    TLV(SMPP_ms_availability_status, 1, 1)
+    OPTIONAL_BEGIN
+    TLV_INTEGER(ms_availability_status, 1)
     OPTIONAL_END
 )
 
@@ -524,6 +518,8 @@ PDU(alert_notification,
 #undef OCTETS
 #undef HEADER
 #undef OPTIONAL_BEGIN
-#undef TLV
+#undef TLV_INTEGER
+#undef TLV_NULTERMINATED
+#undef TLV_OCTETS
 #undef OPTIONAL_END
 
Index: gw/smsc/smpp_pdu_opt.def
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smpp_pdu_opt.def,v
retrieving revision 1.3
diff -a -u -p -r1.3 smpp_pdu_opt.def
--- gw/smsc/smpp_pdu_opt.def	22 Jan 2004 14:08:24 -0000	1.3
+++ gw/smsc/smpp_pdu_opt.def	23 Mar 2004 13:55:22 -0000
@@ -85,7 +85,7 @@
 #define	SMPP_language_indicator 		0x020D 
 #define	SMPP_sar_total_segments 		0x020E 
 #define	SMPP_sar_segment_seqnum 		0x020F 
-#define	SMPP_SC_interface_version 		0x0210 
+#define	SMPP_sc_interface_version 		0x0210 
 #define	SMPP_callback_num_pres_ind 		0x0302 
 #define	SMPP_callback_num_atag 			0x0303 
 #define	SMPP_number_of_messages 		0x0304 
Index: gw/smsc/smpp_pdu.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smpp_pdu.c,v
retrieving revision 1.18
diff -a -u -p -r1.18 smpp_pdu.c
--- gw/smsc/smpp_pdu.c	22 Jan 2004 14:08:24 -0000	1.18
+++ gw/smsc/smpp_pdu.c	23 Mar 2004 13:55:22 -0000
@@ -58,6 +58,8 @@
  * smpp_pdu.c - parse and generate SMPP PDUs
  *
  * Lars Wirzenius
+ * Alexander Malysh <[email protected]>:
+ *     Extended optional parameters implementation.
  */
 
 
@@ -122,9 +124,10 @@ SMPP_PDU *smpp_pdu_create(unsigned long 
     pdu->type = type;
 
     switch (type) {
-    #define OPTIONAL_BEGIN(num_expected) \
-    	p->optional_parameters = dict_create(num_expected, (void (*)(void *))octstr_destroy);
-    #define TLV(tag_id, min_len, max_len)
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, octets) p->name = -1;
+    #define TLV_NULTERMINATED(name, max_len) p->name = NULL;
+    #define TLV_OCTETS(name, min_len, max_len) p->name = NULL;
     #define OPTIONAL_END
     #define INTEGER(name, octets) \
    	if (strcmp(#name, "command_id") == 0) p->name = type; \
@@ -154,8 +157,10 @@ void smpp_pdu_destroy(SMPP_PDU *pdu)
     	return;
 
     switch (pdu->type) {
-    #define OPTIONAL_BEGIN(num_expected) dict_destroy(p->optional_parameters);
-    #define TLV(tag_id, min_len, max_len)
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, octets) p->name = -1;
+    #define TLV_NULTERMINATED(name, max_octets) octstr_destroy(p->name);
+    #define TLV_OCTETS(name, min_len, max_len) octstr_destroy(p->name);
     #define OPTIONAL_END
     #define INTEGER(name, octets) p->name = 0; /* Make sure "p" is used */
     #define NULTERMINATED(name, max_octets) octstr_destroy(p->name);
@@ -183,8 +188,10 @@ Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
      * Fix lengths of octet string fields.
      */
     switch (pdu->type) {
-    #define OPTIONAL_BEGIN(num_expected)
-    #define TLV(tag_id, min_len, max_len)
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, octets)
+    #define TLV_NULTERMINATED(name, max_len)
+    #define TLV_OCTETS(name, min_len, max_len)
     #define OPTIONAL_END
     #define INTEGER(name, octets) p = *(&p);
     #define NULTERMINATED(name, max_octets) p = *(&p);
@@ -198,21 +205,31 @@ Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
     }
 
     switch (pdu->type) {
-    #define OPTIONAL_BEGIN(num_expected)
-    #define TLV(tag_id, min_len, max_len)                                               \
-        {   /* Add optional parameter - if existing */                                  \
-            short tag_id_buffer = tag_id;                                               \
-            Octstr *opt_tag = octstr_create_from_data((char*) &tag_id_buffer, 2);       \
-            Octstr *opt_val = dict_get(p->optional_parameters, opt_tag);                \
-            if (opt_val != NULL) {                                                      \
-                long opt_len = octstr_len(opt_val);                                     \
-                gw_assert(min_len == -1 || (min_len <= opt_len && opt_len <= max_len)); \
-                octstr_append(os, opt_tag);                                             \
-                octstr_append_data(os, (char*) &opt_len, 2);                            \
-                octstr_append(os, opt_val);                                             \
-            }                                                                           \
-            octstr_destroy(opt_tag);                                                    \
-        } 
+    #define TL(name, octets) \
+        append_encoded_integer(os, SMPP_##name, 2); \
+        append_encoded_integer(os, octets, 2);
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, octets) \
+        if (p->name != -1) { \
+            TL(name, octets); \
+            INTEGER(name, octets) \
+        }
+    #define TLV_NULTERMINATED(name, max_len) \
+        if (p->name != NULL) { \
+            TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name))); \
+            NULTERMINATED(name, max_len) \
+        }
+    #define TLV_OCTETS(name, min_len, max_len) \
+        if (p->name != NULL) { \
+            unsigned long len = octstr_len(p->name); \
+            if (len > max_len || len < min_len) { \
+                error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
+                    #name, len, min_len, max_len);\
+            } else { \
+                TL(name, len); \
+                octstr_append(os, p->name); \
+            } \
+        }
     #define OPTIONAL_END
     #define INTEGER(name, octets) \
     	append_encoded_integer(os, p->name, octets);
@@ -230,7 +247,7 @@ Octstr *smpp_pdu_pack(SMPP_PDU *pdu)
         } \
         octstr_append_char(os, '\0');
     #define OCTETS(name, field_giving_octets) \
-    	octstr_append(os, p->name);
+        if (p->name) octstr_append(os, p->name);
     #define PDU(name, id, fields) \
     	case id: { struct name *p = &pdu->u.name; fields } break;
     #include "smpp_pdu.def"
@@ -273,37 +290,51 @@ SMPP_PDU *smpp_pdu_unpack(Octstr *data_w
     pos = 0;
 
     switch (type) {
-    #define OPTIONAL_BEGIN(num_expected)                                                \
-        {   /* Read optional parameters */                                              \
-            while (pos+4 <= len) {                                                      \
-                unsigned long opt_tag, opt_len;                                         \
-                Octstr *opt_val = NULL;                                                 \
-                Octstr *tag_str = NULL;                                                 \
-                opt_tag = decode_integer(data_without_len, pos, 2); pos += 2;           \
-                debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag);      \
-                opt_len = decode_integer(data_without_len, pos, 2); pos += 2;           \
+    #define OPTIONAL_BEGIN  \
+        {   /* Read optional parameters */  \
+            while (pos + 4 <= len) { \
+                unsigned long opt_tag, opt_len; \
+                opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \
+                debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag);   \
+                opt_len = decode_integer(data_without_len, pos, 2); pos += 2;  \
                 debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len);
-    #define TLV(tag_id, min_len, max_len)                                                                          \
-                if (tag_id == opt_tag) {                                                                           \
-                    if ((min_len != -1 && opt_len < min_len) || (max_len != -1 && opt_len > max_len) ||            \
-                        (pos+opt_len > len)) {                                                                     \
-                        error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #tag_id, opt_len);\
-                        pos += opt_len;                                                                            \
-                        continue;                                                                                  \
-                    }                                                                                              \
-                    opt_val = octstr_copy(data_without_len, pos, opt_len); pos += opt_len;                         \
-                    debug("sms.smpp", 0, "Optional parameter value (%s)", octstr_get_cstr(opt_val));               \
-                    tag_str = octstr_create_from_data((char*) &opt_tag, 2);                                        \
-                    dict_put(p->optional_parameters, tag_str, opt_val);                                            \
-                    octstr_destroy(tag_str);                                                                       \
-                    opt_val = NULL;                                                                                \
-                } else 
-    #define OPTIONAL_END                                                                           \
-    		{                                                             \
+    #define TLV_INTEGER(name, octets) \
+                if (SMPP_##name == opt_tag) { \
+                    /* check length */ \
+                    if (opt_len > octets) { \
+                        error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #name, opt_len); \
+                        pos += opt_len; \
+                        continue; \
+                    } \
+                    INTEGER(name, opt_len); \
+                } else
+    #define TLV_NULTERMINATED(name, max_len) \
+                if (SMPP_##name == opt_tag) { \
+                    /* check length */ \
+                    if (opt_len > max_len || pos+opt_len > len) { \
+                        error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #name, opt_len);  \
+                        pos += opt_len; \
+                        continue; \
+                    } \
+                    NULTERMINATED(name, opt_len); \
+                } else
+    #define TLV_OCTETS(name, min_len, max_len) \
+                if (SMPP_##name == opt_tag) { \
+                    /* check length */ \
+                    if (opt_len < min_len || opt_len > max_len || pos + opt_len > len) { \
+                        error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \
+                            #name, opt_len, min_len, max_len);  \
+                        pos += opt_len; \
+                        continue; \
+                    } \
+                    p->name = octstr_copy(data_without_len, pos, opt_len); \
+                } else
+    #define OPTIONAL_END \
+    		{ \
 		    error(0, "SMPP: Unknown optional parameter (0x%04lx) for PDU type (%s) received!", \
-		            opt_tag, pdu->type_name);                                              \
-		}                                                                                  \
-            }                                                                                      \
+		            opt_tag, pdu->type_name); \
+		} \
+            } \
         } 
     #define INTEGER(name, octets) \
     	p->name = decode_integer(data_without_len, pos, octets); \
@@ -337,24 +368,20 @@ void smpp_pdu_dump(SMPP_PDU *pdu)
     debug("sms.smpp", 0, "SMPP PDU %p dump:", (void *) pdu);
     debug("sms.smpp", 0, "  type_name: %s", pdu->type_name);
     switch (pdu->type) {
-    #define OPTIONAL_BEGIN(num_expected) \
-	if (p->optional_parameters != NULL) { \
-	    Octstr *key = NULL, *tag_val = NULL;
-            unsigned long id;
-    #define TLV(tag_id, min_len, max_len) \
-            id = tag_id; \
-            key = octstr_create_from_data((char*)&id, 2); \
-            tag_val = dict_get(p->optional_parameters, key); \
-            if (tag_val != NULL) { \
-                debug("sms.smpp",0,"  %s: ", #tag_id); \
-                debug("sms.smpp",0,"    tag: 0x%04lx", id); \
-                debug("sms.smpp",0,"    length: 0x%04lx", \
-                      octstr_len(tag_val)); \
-		        octstr_dump_short(tag_val, 2, "  value"); \
-            } \
-            octstr_destroy(key);
-    #define OPTIONAL_END \
-	}
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, max_len) \
+        if (p->name != -1)  { \
+            INTEGER(name, max_len) \
+        }
+    #define TLV_NULTERMINATED(name, max_len) \
+        if (p->name != NULL) { \
+            NULTERMINATED(name, max_len) \
+        }
+    #define TLV_OCTETS(name, min_len, max_len) \
+        if (p->name != NULL) { \
+            OCTETS(name, max_len) \
+        }        
+    #define OPTIONAL_END
     #define INTEGER(name, octets) \
     	debug("sms.smpp", 0, "  %s: %lu = 0x%08lx", #name, p->name, p->name);
     #define NULTERMINATED(name, max_octets) \
Index: gw/smsc/smpp_pdu.h
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smpp_pdu.h,v
retrieving revision 1.9
diff -a -u -p -r1.9 smpp_pdu.h
--- gw/smsc/smpp_pdu.h	22 Jan 2004 14:08:24 -0000	1.9
+++ gw/smsc/smpp_pdu.h	23 Mar 2004 13:55:22 -0000
@@ -58,6 +58,8 @@
  * smpp_pdu.h - declarations for SMPP PDUs
  *
  * Lars Wirzenius
+ * Alexander Malysh <[email protected]>:
+ *     Extended optional parameters implementation.
  */
 
 
@@ -70,8 +72,10 @@
 
 
 enum {
-    #define OPTIONAL_BEGIN(num_expected)
-    #define TLV(tag_id, min_len, max_len)
+    #define OPTIONAL_BEGIN
+    #define TLV_INTEGER(name, max_len)
+    #define TLV_NULTERMINATED(name, max_len)
+    #define TLV_OCTETS(name, min_len, max_len)
     #define OPTIONAL_END
     #define INTEGER(name, octets)
     #define NULTERMINATED(name, max_octets)
@@ -87,14 +91,16 @@ struct SMPP_PDU {
     unsigned long type;
     const char *type_name;
     union {
-	#define OPTIONAL_BEGIN(num_expected) Dict * optional_parameters;
-	#define TLV(tag_id, min_len, max_len)
-	#define OPTIONAL_END
-	#define INTEGER(name, octets) unsigned long name;
-	#define NULTERMINATED(name, max_octets) Octstr *name;
-	#define OCTETS(name, field_giving_octets) Octstr *name;
-	#define PDU(name, id, fields) struct name { fields } name;
-	#include "smpp_pdu.def"
+        #define OPTIONAL_BEGIN
+        #define TLV_INTEGER(name, octets) unsigned long name;
+        #define TLV_NULTERMINATED(name, max_len) Octstr *name;
+        #define TLV_OCTETS(name, min_len, max_len) Octstr *name;
+        #define OPTIONAL_END
+        #define INTEGER(name, octets) unsigned long name;
+        #define NULTERMINATED(name, max_octets) Octstr *name;
+        #define OCTETS(name, field_giving_octets) Octstr *name;
+        #define PDU(name, id, fields) struct name { fields } name;
+        #include "smpp_pdu.def"
     } u;
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.