00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include <string.h>
00065 #include "smasi_pdu.h"
00066
00067
00068 static Octstr *decode_type(Octstr *os)
00069 {
00070 long p1, p2;
00071 Octstr *temp;
00072
00073 if ((p2 = octstr_search_char(os, ':', 0)) == -1)
00074 return NULL;
00075
00076 if ((p1 = octstr_search_char(os, '!', 0)) != -1 && p1 < p2) {
00077 p1++;
00078 } else {
00079 p1 = 0;
00080 }
00081
00082 temp = octstr_copy(os, p1, p2 - p1);
00083
00084 return temp;
00085 }
00086
00087
00088 static Octstr *copy_until_coma(Octstr *os, long *pos)
00089 {
00090 long nul;
00091 Octstr *data;
00092
00093 nul = octstr_search_char(os, ',', *pos);
00094 if (nul == -1) {
00095 warning(0, "SMASI: Parameter without value or value not properly terminated: %s", octstr_get_cstr(os));
00096 return NULL;
00097 }
00098 data = octstr_copy(os, *pos, nul - *pos);
00099 *pos = nul + 1;
00100 return data;
00101 }
00102
00103
00104 static Octstr *copy_until_assign(Octstr *os, long *pos)
00105 {
00106 long nul;
00107 Octstr *data;
00108
00109 nul = octstr_search_char(os, '=', *pos);
00110 if (nul == -1 && (octstr_len(os) - *pos) > 1) {
00111 warning(0, "SMASI: Garbage at end of parameter list: %s", octstr_get_cstr(os));
00112 *pos = octstr_len(os);
00113 return NULL;
00114 }
00115 data = octstr_copy(os, *pos, nul - *pos);
00116 *pos = nul + 1;
00117 return data;
00118 }
00119
00120
00121 static void skip_until_after_colon(Octstr *os, long *pos)
00122 {
00123 long colon = octstr_search_char(os, ':', *pos);
00124
00125 if (colon == -1) warning(0, "SMASI: No colon after SMASI PDU name: %s", octstr_get_cstr(os));
00126
00127 *pos = colon + 1;
00128
00129 }
00130
00131
00132 SMASI_PDU *smasi_pdu_create(unsigned long type)
00133 {
00134 SMASI_PDU *pdu;
00135
00136 pdu = gw_malloc(sizeof(*pdu));
00137 pdu->type = type;
00138
00139 switch (type) {
00140 #define NONTERMINATED(name) p->name = NULL;
00141 #define COMATERMINATED(name) p->name = NULL;
00142 #define PDU(name, id, fields) \
00143 case id: { \
00144 struct name *p = &pdu->u.name; \
00145 pdu->type_name = #name; \
00146 pdu->needs_hyphen = (id < SMASI_HYPHEN_ID ? 1 : 0); \
00147 fields \
00148 } break;
00149 #include "smasi_pdu.def"
00150 default:
00151 warning(0, "Unknown SMASI_PDU type, internal error.");
00152 gw_free(pdu);
00153 return NULL;
00154 }
00155
00156 return pdu;
00157 }
00158
00159
00160 void smasi_pdu_destroy(SMASI_PDU *pdu)
00161 {
00162 if (pdu == NULL)
00163 return;
00164
00165 switch (pdu->type) {
00166 #define NONTERMINATED(name) octstr_destroy(p->name);
00167 #define COMATERMINATED(name) octstr_destroy(p->name);
00168 #define PDU(name, id, fields) \
00169 case id: { struct name *p = &pdu->u.name; fields } break;
00170 #include "smasi_pdu.def"
00171 default:
00172 error(0, "Unknown SMASI_PDU type, internal error while destroying.");
00173 }
00174 gw_free(pdu);
00175 }
00176
00177
00178 Octstr *smasi_pdu_pack(SMASI_PDU *pdu)
00179 {
00180 Octstr *os;
00181 Octstr *temp;
00182
00183 os = octstr_create("");
00184
00185
00186
00187
00188 switch (pdu->type) {
00189 #define NONTERMINATED(name) p = *(&p);
00190 #define COMATERMINATED(name) p = *(&p);
00191 #define PDU(name, id, fields) \
00192 case id: { struct name *p = &pdu->u.name; fields } break;
00193 #include "smasi_pdu.def"
00194 default:
00195 error(0, "Unknown SMASI_PDU type, internal error while packing.");
00196 }
00197
00198 switch (pdu->type) {
00199 #define NONTERMINATED(name) p = *(&p);
00200 #define COMATERMINATED(name) \
00201 if (p->name != NULL) { octstr_append_cstr(os, #name); \
00202 octstr_append_char(os, '='); \
00203 octstr_append(os, p->name); \
00204 octstr_append_char(os, ','); }
00205 #define PDU(name, id, fields) \
00206 case id: { struct name *p = &pdu->u.name; fields } break;
00207 #include "smasi_pdu.def"
00208 default:
00209 error(0, "Unknown SMASI_PDU type, internal error while packing.");
00210 }
00211
00212 octstr_append_char(os, '\n');
00213 temp = pdu->needs_hyphen ? octstr_create("!") : octstr_create("");
00214 octstr_append_cstr(temp, pdu->type_name);
00215 octstr_append_char(temp, ':');
00216 octstr_insert(os, temp, 0);
00217 octstr_destroy(temp);
00218
00219 return os;
00220 }
00221
00222
00223 SMASI_PDU *smasi_pdu_unpack(Octstr *data_without_len)
00224 {
00225 SMASI_PDU *pdu;
00226 char *type_name;
00227 Octstr *temp;
00228 long pos;
00229 unsigned long type = 0;
00230
00231
00232 temp = decode_type(data_without_len);
00233 type_name = (temp ? octstr_get_cstr(temp) : "");
00234
00235 if (strcmp(type_name, "dummy") == 0) type = 0;
00236 #define NONTERMINATED(name) p = *(&p);
00237 #define COMATERMINATED(name) p = *(&p);
00238 #define PDU(name, id, fields) \
00239 else if (strcmp(type_name, #name) == 0) type = id;
00240 #include "smasi_pdu.def"
00241 else warning(0, "unknown SMASI PDU type");
00242
00243 pdu = smasi_pdu_create(type);
00244 if (pdu == NULL) return NULL;
00245
00246 pos = 0;
00247 skip_until_after_colon(data_without_len, &pos);
00248
00249 switch (type) {
00250 #define NONTERMINATED(name) p = *(&p);
00251 #define COMATERMINATED(name) \
00252 if (octstr_str_compare(field_name, #name) == 0 && field_value != NULL) \
00253 p->name = octstr_duplicate(field_value);
00254 #define PDU(name, id, fields) \
00255 case id: { \
00256 Octstr * field_name = NULL; \
00257 Octstr * field_value = NULL; \
00258 struct name *p = &pdu->u.name; \
00259 while (pos < octstr_len(data_without_len)) { \
00260 field_name = copy_until_assign(data_without_len, &pos); \
00261 if (field_name == NULL) break; \
00262 field_value = copy_until_coma(data_without_len, &pos); \
00263 if (field_value == NULL) continue; \
00264 fields \
00265 octstr_destroy(field_name); \
00266 octstr_destroy(field_value); \
00267 } \
00268 } break;
00269 #include "smasi_pdu.def"
00270 default:
00271 warning(0, "Unknown SMASI_PDU type, internal error while unpacking.");
00272 }
00273
00274 octstr_destroy(temp);
00275
00276 return pdu;
00277 }
00278
00279
00280 void smasi_pdu_dump(SMASI_PDU *pdu)
00281 {
00282 debug("sms.smasi", 0, "SMASI PDU %p dump:", (void *) pdu);
00283 debug("sms.smasi", 0, " type_name: %s", pdu->type_name);
00284 switch (pdu->type) {
00285 #define NONTERMINATED(name) p = *(&p);
00286 #define COMATERMINATED(name) \
00287 octstr_dump_short(p->name, 2, #name);
00288 #define PDU(name, id, fields) \
00289 case id: { struct name *p = &pdu->u.name; fields } break;
00290 #include "smasi_pdu.def"
00291 default:
00292 warning(0, "Unknown SMASI_PDU type, internal error.");
00293 break;
00294 }
00295 debug("sms.smasi", 0, "SMASI PDU dump ends.");
00296 }
00297
00298
00299 Octstr *smasi_pdu_read(Connection *conn)
00300 {
00301 Octstr *line;
00302
00303 line = conn_read_line(conn);
00304 return line;
00305 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.