wsp_pdu.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:7k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* wsp_pdu.c - pack and unpack WSP packets
  2.  *
  3.  * Generates packing and unpacking code from wsp_pdu.def.
  4.  * Code is very similar to wsp_pdu.c, please make any changes in both files.
  5.  *
  6.  * Richard Braakman
  7.  */
  8. #include "gwlib/gwlib.h"
  9. #include "wsp_pdu.h"
  10. WSP_PDU *wsp_pdu_create(int type) {
  11. WSP_PDU *pdu;
  12. pdu = gw_malloc(sizeof(*pdu));
  13. pdu->type = type;
  14. switch (pdu->type) {
  15. #define PDU(name, docstring, fields, is_valid) 
  16. case name: {
  17. struct name *p; p = &pdu->u.name; 
  18. fields 
  19. } break;
  20. #define UINT(field, docstring, bits) p->field = 0;
  21. #define UINTVAR(field, docstring) p->field = 0;
  22. #define OCTSTR(field, docstring, lengthfield) p->field = NULL;
  23. #define REST(field, docstring) p->field = NULL;
  24. #define TYPE(bits, value)
  25. #define RESERVED(bits)
  26. #include "wsp_pdu.def"
  27. #undef RESERVED
  28. #undef TYPE
  29. #undef REST
  30. #undef OCTSTR
  31. #undef UINTVAR
  32. #undef UINT
  33. #undef PDU
  34. default:
  35. panic(0, "Internal error: Unknown PDU type %d", pdu->type);
  36. break;
  37. }
  38. return pdu;
  39. }
  40. void wsp_pdu_destroy(WSP_PDU *pdu) {
  41. if (pdu == NULL)
  42. return;
  43. switch (pdu->type) {
  44. #define PDU(name, docstring, fields, is_valid) 
  45. case name: {
  46. struct name *p; p = &pdu->u.name; 
  47. fields 
  48. } break;
  49. #define UINT(field, docstring, bits)
  50. #define UINTVAR(field, docstring)
  51. #define OCTSTR(field, docstring, lengthfield) octstr_destroy(p->field);
  52. #define REST(field, docstring) octstr_destroy(p->field);
  53. #define TYPE(bits, value)
  54. #define RESERVED(bits)
  55. #include "wsp_pdu.def"
  56. #undef RESERVED
  57. #undef TYPE
  58. #undef REST
  59. #undef OCTSTR
  60. #undef UINTVAR
  61. #undef UINT
  62. #undef PDU
  63. default:
  64. panic(0, "Cannot destroy unknown WSP PDU type %d", pdu->type);
  65. break;
  66. }
  67. gw_free(pdu);
  68. }
  69. /* Determine which type of PDU this is, using the TYPE macros in
  70.  * the definition file. */
  71. static int wsp_pdu_type(Octstr *data) {
  72. long bitpos;
  73. long lastpos = -1;
  74. long lastnumbits = -1;
  75. long lastval = -1;
  76. int thistype;
  77. /* This code looks slow, but an optimizing compiler will
  78.  * reduce it considerably.  gcc -O2 will produce a single
  79.  * call to octstr_get_bits, folllowed by a sequence of
  80.  * tests on lastval. */
  81. /* Only UINT and RESERVED fields may precede the TYPE */
  82. #define PDU(name, docstring, fields, is_valid) 
  83. bitpos = 0; 
  84. thistype = name; 
  85. fields
  86. #define UINT(field, docstring, bits) bitpos += (bits);
  87. #define UINTVAR(field, docstring)
  88. #define OCTSTR(field, docstring, lengthfield)
  89. #define REST(field, docstring)
  90. #define TYPE(bits, value) 
  91. if ((bits) != lastnumbits || bitpos != lastpos) { 
  92. lastval = octstr_get_bits(data, bitpos, (bits)); 
  93. if (lastval == (value)) 
  94. return thistype; 
  95. lastnumbits = (bits); 
  96. lastpos = bitpos;
  97. #define RESERVED(bits) bitpos += (bits);
  98. #include "wsp_pdu.def"
  99. #undef RESERVED
  100. #undef TYPE
  101. #undef REST
  102. #undef OCTSTR
  103. #undef UINTVAR
  104. #undef UINT
  105. #undef PDU
  106. return -1;
  107. }
  108. WSP_PDU *wsp_pdu_unpack(Octstr *data) {
  109. WSP_PDU *pdu = NULL;
  110. long bitpos = 0;
  111. gw_assert(data != NULL);
  112. pdu = gw_malloc(sizeof(*pdu));
  113. pdu->type = wsp_pdu_type(data);
  114. switch (pdu->type) {
  115. #define PDU(name, docstring, fields, is_valid) 
  116. case name: { 
  117. struct name *p = &pdu->u.name; 
  118. fields 
  119. gw_assert(bitpos % 8 == 0); 
  120. if (bitpos / 8 != octstr_len(data)) { 
  121. warning(0, "Bad length for " #name " PDU, " 
  122. "expected %ld", bitpos / 8); 
  123. if (!(is_valid)) { 
  124. warning(0, #name " PDU failed %s", #is_valid); 
  125. } break;
  126. #define UINT(field, docstring, bits) 
  127. p->field = octstr_get_bits(data, bitpos, (bits)); 
  128. bitpos += (bits);
  129. #define UINTVAR(field, docstring) 
  130. gw_assert(bitpos % 8 == 0); 
  131. p->field = octstr_get_bits(data, bitpos + 1, 7); 
  132. while (octstr_get_bits(data, bitpos, 1)) { 
  133. bitpos += 8; 
  134. p->field <<= 7; 
  135. p->field |= octstr_get_bits(data, bitpos + 1, 7); 
  136. bitpos += 8;
  137. #define OCTSTR(field, docstring, lengthfield) 
  138. gw_assert(bitpos % 8 == 0); 
  139. p->field = octstr_copy(data, bitpos / 8, p->lengthfield); 
  140. bitpos += 8 * p->lengthfield;
  141. #define REST(field, docstring) 
  142. gw_assert(bitpos % 8 == 0); 
  143. if (bitpos / 8 <= octstr_len(data)) { 
  144. p->field = octstr_copy(data, bitpos / 8, 
  145. octstr_len(data) - bitpos / 8); 
  146. bitpos = octstr_len(data) * 8; 
  147. } else { 
  148. p->field = octstr_create(""); 
  149. }
  150. #define TYPE(bits, value) bitpos += (bits);
  151. #define RESERVED(bits) bitpos += (bits);
  152. #include "wsp_pdu.def"
  153. #undef RESERVED
  154. #undef TYPE
  155. #undef REST
  156. #undef OCTSTR
  157. #undef UINTVAR
  158. #undef UINT
  159. #undef PDU
  160. default:
  161. warning(0, "WSP PDU with unknown type %d", pdu->type);
  162. gw_free(pdu);
  163. return NULL;
  164. }
  165. return pdu;
  166. }
  167. static void fixup_length_fields(WSP_PDU *pdu) {
  168. switch (pdu->type) {
  169. #define PDU(name, docstring, fields, is_valid) 
  170. case name: { 
  171. struct name *p; p = &pdu->u.name; 
  172. fields 
  173. } break;
  174. #define UINT(field, docstring, bits)
  175. #define UINTVAR(field, docstring)
  176. #define OCTSTR(field, docstring, lengthfield) 
  177. p->lengthfield = octstr_len(p->field);
  178. #define REST(field, docstring)
  179. #define TYPE(bits, value)
  180. #define RESERVED(bits)
  181. #include "wsp_pdu.def"
  182. #undef RESERVED
  183. #undef TYPE
  184. #undef REST
  185. #undef OCTSTR
  186. #undef UINTVAR
  187. #undef UINT
  188. #undef PDU
  189. }
  190. }
  191. Octstr *wsp_pdu_pack(WSP_PDU *pdu) {
  192. Octstr *data;
  193. long bitpos;
  194. /* We rely on octstr_set_bits to lengthen our octstr as needed. */
  195. data = octstr_create("");
  196. fixup_length_fields(pdu);
  197. bitpos = 0;
  198. switch (pdu->type) {
  199. #define PDU(name, docstring, fields, is_valid) 
  200. case name: { 
  201. struct name *p = &pdu->u.name; 
  202. fields 
  203. gw_assert(bitpos % 8 == 0); 
  204. } break;
  205. #define UINT(field, docstring, bits) 
  206. octstr_set_bits(data, bitpos, (bits), p->field); 
  207. bitpos += (bits);
  208. #define UINTVAR(field, docstring) 
  209. gw_assert(bitpos % 8 == 0); 
  210. octstr_append_uintvar(data, p->field); 
  211. bitpos = 8 * octstr_len(data);
  212. #define OCTSTR(field, docstring, lengthfield) 
  213. gw_assert(bitpos % 8 == 0); 
  214. if (p->field != NULL) 
  215. octstr_append(data, p->field); 
  216. bitpos += 8 * octstr_len(p->field);
  217. #define REST(field, docstring) 
  218. gw_assert(bitpos % 8 == 0); 
  219. if (p->field != NULL) 
  220. octstr_append(data, p->field); 
  221. bitpos += 8 * octstr_len(p->field);
  222. #define TYPE(bits, value) 
  223. octstr_set_bits(data, bitpos, (bits), (value)); 
  224. bitpos += (bits);
  225. #define RESERVED(bits) bitpos += (bits);
  226. #include "wsp_pdu.def"
  227. #undef RESERVED
  228. #undef TYPE
  229. #undef REST
  230. #undef OCTSTR
  231. #undef UINTVAR
  232. #undef UINT
  233. #undef PDU
  234. default:
  235. panic(0, "Packing unknown WSP PDU type %ld", (long) pdu->type);
  236. }
  237. return data;
  238. }
  239. void wsp_pdu_dump(WSP_PDU *pdu, int level) {
  240. unsigned char *dbg = "wap.wsp";
  241. switch (pdu->type) {
  242. #define PDU(name, docstring, fields, is_valid) 
  243. case name: { 
  244. struct name *p = &pdu->u.name; 
  245. debug(dbg, 0, "%*sWSP %s PDU at %p:", 
  246. level, "", #name, (void *)pdu); 
  247. fields 
  248. } break;
  249. #define UINT(field, docstring, bits) 
  250. debug(dbg, 0, "%*s %s: %lu", level, "", docstring, p->field);
  251. #define UINTVAR(field, docstring) 
  252. debug(dbg, 0, "%*s %s: %lu", level, "", docstring, p->field);
  253. #define OCTSTR(field, docstring, lengthfield) 
  254. debug(dbg, 0, "%*s %s:", level, "", docstring); 
  255. octstr_dump(p->field, level + 1);
  256. #define REST(field, docstring) 
  257. debug(dbg, 0, "%*s %s:", level, "", docstring); 
  258. octstr_dump(p->field, level + 1);
  259. #define TYPE(bits, value)
  260. #define RESERVED(bits)
  261. #include "wsp_pdu.def"
  262. #undef RESERVED
  263. #undef TYPE
  264. #undef REST
  265. #undef OCTSTR
  266. #undef UINTVAR
  267. #undef UINT
  268. #undef PDU
  269. default:
  270. debug(dbg, 0, "%*sWSP PDU at %p:", level, "", (void *)pdu);
  271. debug(dbg, 0, "%*s unknown type %u", level, "", pdu->type);
  272. break;
  273. }
  274. debug("wap.wsp", 0, "%*sWSP PDU dump ends.", level, "");
  275. }