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
00065 #include "gwlib/gwlib.h"
00066 #include "wsp_pdu.h"
00067
00068 WSP_PDU *wsp_pdu_create(int type) {
00069 WSP_PDU *pdu;
00070
00071 pdu = gw_malloc(sizeof(*pdu));
00072 pdu->type = type;
00073
00074 switch (pdu->type) {
00075 #define PDU(name, docstring, fields, is_valid) \
00076 case name: {\
00077 struct name *p; p = &pdu->u.name; \
00078 fields \
00079 } break;
00080 #define UINT(field, docstring, bits) p->field = 0;
00081 #define UINTVAR(field, docstring) p->field = 0;
00082 #define OCTSTR(field, docstring, lengthfield) p->field = NULL;
00083 #define REST(field, docstring) p->field = NULL;
00084 #define TYPE(bits, value)
00085 #define RESERVED(bits)
00086 #include "wsp_pdu.def"
00087 #undef RESERVED
00088 #undef TYPE
00089 #undef REST
00090 #undef OCTSTR
00091 #undef UINTVAR
00092 #undef UINT
00093 #undef PDU
00094 default:
00095 panic(0, "Internal error: Unknown PDU type %d", pdu->type);
00096 break;
00097 }
00098
00099 return pdu;
00100 }
00101
00102 void wsp_pdu_destroy(WSP_PDU *pdu) {
00103 if (pdu == NULL)
00104 return;
00105
00106 switch (pdu->type) {
00107 #define PDU(name, docstring, fields, is_valid) \
00108 case name: {\
00109 struct name *p; p = &pdu->u.name; \
00110 fields \
00111 } break;
00112 #define UINT(field, docstring, bits)
00113 #define UINTVAR(field, docstring)
00114 #define OCTSTR(field, docstring, lengthfield) octstr_destroy(p->field);
00115 #define REST(field, docstring) octstr_destroy(p->field);
00116 #define TYPE(bits, value)
00117 #define RESERVED(bits)
00118 #include "wsp_pdu.def"
00119 #undef RESERVED
00120 #undef TYPE
00121 #undef REST
00122 #undef OCTSTR
00123 #undef UINTVAR
00124 #undef UINT
00125 #undef PDU
00126 default:
00127 panic(0, "Cannot destroy unknown WSP PDU type %d", pdu->type);
00128 break;
00129 }
00130
00131 gw_free(pdu);
00132 }
00133
00134
00135
00136 static int wsp_pdu_type(Octstr *data) {
00137 long bitpos;
00138 long lastpos = -1;
00139 long lastnumbits = -1;
00140 long lastval = -1;
00141 int thistype;
00142
00143
00144
00145
00146
00147
00148
00149 #define PDU(name, docstring, fields, is_valid) \
00150 bitpos = 0; \
00151 thistype = name; \
00152 fields
00153 #define UINT(field, docstring, bits) bitpos += (bits);
00154 #define UINTVAR(field, docstring)
00155 #define OCTSTR(field, docstring, lengthfield)
00156 #define REST(field, docstring)
00157 #define TYPE(bits, value) \
00158 if ((bits) != lastnumbits || bitpos != lastpos) { \
00159 lastval = octstr_get_bits(data, bitpos, (bits)); \
00160 } \
00161 if (lastval == (value)) \
00162 return thistype; \
00163 lastnumbits = (bits); \
00164 lastpos = bitpos;
00165 #define RESERVED(bits) bitpos += (bits);
00166 #include "wsp_pdu.def"
00167 #undef RESERVED
00168 #undef TYPE
00169 #undef REST
00170 #undef OCTSTR
00171 #undef UINTVAR
00172 #undef UINT
00173 #undef PDU
00174
00175 return -1;
00176 }
00177
00178 WSP_PDU *wsp_pdu_unpack(Octstr *data) {
00179 WSP_PDU *pdu = NULL;
00180 long bitpos = 0;
00181
00182 gw_assert(data != NULL);
00183
00184 pdu = gw_malloc(sizeof(*pdu));
00185
00186 pdu->type = wsp_pdu_type(data);
00187
00188 switch (pdu->type) {
00189 #define PDU(name, docstring, fields, is_valid) \
00190 case name: { \
00191 struct name *p = &pdu->u.name; \
00192 fields \
00193 gw_assert(bitpos % 8 == 0); \
00194 if (bitpos / 8 != octstr_len(data)) { \
00195 warning(0, "Bad length for " #name " PDU, " \
00196 "expected %ld", bitpos / 8); \
00197 } \
00198 if (!(is_valid)) { \
00199 warning(0, #name " PDU failed %s", #is_valid); \
00200 } \
00201 } break;
00202 #define UINT(field, docstring, bits) \
00203 p->field = octstr_get_bits(data, bitpos, (bits)); \
00204 bitpos += (bits);
00205 #define UINTVAR(field, docstring) \
00206 gw_assert(bitpos % 8 == 0); \
00207 p->field = octstr_get_bits(data, bitpos + 1, 7); \
00208 while (octstr_get_bits(data, bitpos, 1)) { \
00209 bitpos += 8; \
00210 p->field <<= 7; \
00211 p->field |= octstr_get_bits(data, bitpos + 1, 7); \
00212 } \
00213 bitpos += 8;
00214 #define OCTSTR(field, docstring, lengthfield) \
00215 gw_assert(bitpos % 8 == 0); \
00216 p->field = octstr_copy(data, bitpos / 8, p->lengthfield); \
00217 bitpos += 8 * p->lengthfield;
00218 #define REST(field, docstring) \
00219 gw_assert(bitpos % 8 == 0); \
00220 if (bitpos / 8 <= octstr_len(data)) { \
00221 p->field = octstr_copy(data, bitpos / 8, \
00222 octstr_len(data) - bitpos / 8); \
00223 bitpos = octstr_len(data) * 8; \
00224 } else { \
00225 p->field = octstr_create(""); \
00226 }
00227 #define TYPE(bits, value) bitpos += (bits);
00228 #define RESERVED(bits) bitpos += (bits);
00229 #include "wsp_pdu.def"
00230 #undef RESERVED
00231 #undef TYPE
00232 #undef REST
00233 #undef OCTSTR
00234 #undef UINTVAR
00235 #undef UINT
00236 #undef PDU
00237 default:
00238 warning(0, "WSP PDU with unknown type %d", pdu->type);
00239 gw_free(pdu);
00240 return NULL;
00241 }
00242
00243 return pdu;
00244 }
00245
00246 static void fixup_length_fields(WSP_PDU *pdu) {
00247 switch (pdu->type) {
00248 #define PDU(name, docstring, fields, is_valid) \
00249 case name: { \
00250 struct name *p; p = &pdu->u.name; \
00251 fields \
00252 } break;
00253 #define UINT(field, docstring, bits)
00254 #define UINTVAR(field, docstring)
00255 #define OCTSTR(field, docstring, lengthfield) \
00256 p->lengthfield = octstr_len(p->field);
00257 #define REST(field, docstring)
00258 #define TYPE(bits, value)
00259 #define RESERVED(bits)
00260 #include "wsp_pdu.def"
00261 #undef RESERVED
00262 #undef TYPE
00263 #undef REST
00264 #undef OCTSTR
00265 #undef UINTVAR
00266 #undef UINT
00267 #undef PDU
00268 }
00269 }
00270
00271 Octstr *wsp_pdu_pack(WSP_PDU *pdu) {
00272 Octstr *data;
00273 long bitpos;
00274
00275
00276 data = octstr_create("");
00277
00278 fixup_length_fields(pdu);
00279
00280 bitpos = 0;
00281 switch (pdu->type) {
00282 #define PDU(name, docstring, fields, is_valid) \
00283 case name: { \
00284 struct name *p = &pdu->u.name; \
00285 fields \
00286 gw_assert(bitpos % 8 == 0); \
00287 } break;
00288 #define UINT(field, docstring, bits) \
00289 octstr_set_bits(data, bitpos, (bits), p->field); \
00290 bitpos += (bits);
00291 #define UINTVAR(field, docstring) \
00292 gw_assert(bitpos % 8 == 0); \
00293 octstr_append_uintvar(data, p->field); \
00294 bitpos = 8 * octstr_len(data);
00295 #define OCTSTR(field, docstring, lengthfield) \
00296 gw_assert(bitpos % 8 == 0); \
00297 if (p->field != NULL) \
00298 octstr_append(data, p->field); \
00299 bitpos += 8 * octstr_len(p->field);
00300 #define REST(field, docstring) \
00301 gw_assert(bitpos % 8 == 0); \
00302 if (p->field != NULL) \
00303 octstr_append(data, p->field); \
00304 bitpos += 8 * octstr_len(p->field);
00305 #define TYPE(bits, value) \
00306 octstr_set_bits(data, bitpos, (bits), (value)); \
00307 bitpos += (bits);
00308 #define RESERVED(bits) bitpos += (bits);
00309 #include "wsp_pdu.def"
00310 #undef RESERVED
00311 #undef TYPE
00312 #undef REST
00313 #undef OCTSTR
00314 #undef UINTVAR
00315 #undef UINT
00316 #undef PDU
00317 default:
00318 panic(0, "Packing unknown WSP PDU type %ld", (long) pdu->type);
00319 }
00320
00321 return data;
00322 }
00323
00324 void wsp_pdu_dump(WSP_PDU *pdu, int level) {
00325 char *dbg = "wap.wsp";
00326
00327 switch (pdu->type) {
00328 #define PDU(name, docstring, fields, is_valid) \
00329 case name: { \
00330 struct name *p = &pdu->u.name; \
00331 debug(dbg, 0, "%*sWSP %s PDU at %p:", \
00332 level, "", #name, (void *)pdu); \
00333 fields \
00334 } break;
00335 #define UINT(field, docstring, bits) \
00336 debug(dbg, 0, "%*s %s: %lu", level, "", docstring, p->field);
00337 #define UINTVAR(field, docstring) \
00338 debug(dbg, 0, "%*s %s: %lu", level, "", docstring, p->field);
00339 #define OCTSTR(field, docstring, lengthfield) \
00340 debug(dbg, 0, "%*s %s:", level, "", docstring); \
00341 octstr_dump(p->field, level + 1);
00342 #define REST(field, docstring) \
00343 debug(dbg, 0, "%*s %s:", level, "", docstring); \
00344 octstr_dump(p->field, level + 1);
00345 #define TYPE(bits, value)
00346 #define RESERVED(bits)
00347 #include "wsp_pdu.def"
00348 #undef RESERVED
00349 #undef TYPE
00350 #undef REST
00351 #undef OCTSTR
00352 #undef UINTVAR
00353 #undef UINT
00354 #undef PDU
00355 default:
00356 debug(dbg, 0, "%*sWSP PDU at %p:", level, "", (void *)pdu);
00357 debug(dbg, 0, "%*s unknown type %u", level, "", pdu->type);
00358 break;
00359 }
00360 debug("wap.wsp", 0, "%*sWSP PDU dump ends.", level, "");
00361 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.