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
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;
 };
 

Reply via email to