mns.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * OBEX Server
  5. *
  6. * Copyright (C) 2013 BMW Car IT GmbH. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <string.h>
  15. #include <errno.h>
  16. #include <glib.h>
  17. #include <fcntl.h>
  18. #include <inttypes.h>
  19. #include <stdbool.h>
  20. #include <stdlib.h>
  21. #include "gobex/gobex.h"
  22. #include "gobex/gobex-apparam.h"
  23. #include "obexd/src/obexd.h"
  24. #include "obexd/src/plugin.h"
  25. #include "obexd/src/log.h"
  26. #include "obexd/src/obex.h"
  27. #include "obexd/src/service.h"
  28. #include "obexd/src/mimetype.h"
  29. #include "obexd/src/map_ap.h"
  30. #include "map-event.h"
  31. #include "obexd/src/manager.h"
  32. struct mns_session {
  33. GString *buffer;
  34. GObexApparam *inparams;
  35. char *remote_address;
  36. uint8_t mas_instance_id;
  37. };
  38. static const uint8_t MNS_TARGET[TARGET_SIZE] = {
  39. 0xbb, 0x58, 0x2b, 0x41, 0x42, 0x0c, 0x11, 0xdb,
  40. 0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 };
  41. static int get_params(struct obex_session *os, struct mns_session *mns)
  42. {
  43. const uint8_t *buffer;
  44. ssize_t size;
  45. size = obex_get_apparam(os, &buffer);
  46. if (size < 0)
  47. size = 0;
  48. mns->inparams = g_obex_apparam_decode(buffer, size);
  49. if (mns->inparams == NULL) {
  50. DBG("Error when parsing parameters!");
  51. return -EBADR;
  52. }
  53. return 0;
  54. }
  55. static void reset_request(struct mns_session *mns)
  56. {
  57. if (mns->buffer) {
  58. g_string_free(mns->buffer, TRUE);
  59. mns->buffer = NULL;
  60. }
  61. if (mns->inparams) {
  62. g_obex_apparam_free(mns->inparams);
  63. mns->inparams = NULL;
  64. }
  65. }
  66. static void mns_session_free(struct mns_session *mns)
  67. {
  68. reset_request(mns);
  69. if (mns->remote_address)
  70. g_free(mns->remote_address);
  71. g_free(mns);
  72. }
  73. static void *mns_connect(struct obex_session *os, int *err)
  74. {
  75. struct mns_session *mns;
  76. char *address;
  77. manager_register_session(os);
  78. mns = g_new0(struct mns_session, 1);
  79. if (obex_getpeername(os, &address) == 0) {
  80. mns->remote_address = g_strdup(address);
  81. g_free(address);
  82. }
  83. DBG("MNS connected to %s", mns->remote_address);
  84. if (err)
  85. *err = 0;
  86. return mns;
  87. }
  88. static void mns_disconnect(struct obex_session *os, void *user_data)
  89. {
  90. struct mns_session *mns = user_data;
  91. DBG("MNS disconnected from %s", mns->remote_address);
  92. manager_unregister_session(os);
  93. mns_session_free(mns);
  94. }
  95. static int mns_put(struct obex_session *os, void *user_data)
  96. {
  97. struct mns_session *mns = user_data;
  98. const char *type = obex_get_type(os);
  99. const char *name = obex_get_name(os);
  100. int ret;
  101. DBG("PUT: name %s type %s mns %p", name, type, mns);
  102. if (type == NULL)
  103. return -EBADR;
  104. ret = get_params(os, mns);
  105. if (ret < 0)
  106. goto failed;
  107. ret = obex_put_stream_start(os, name);
  108. if (ret < 0)
  109. goto failed;
  110. return 0;
  111. failed:
  112. reset_request(mns);
  113. return ret;
  114. }
  115. static void parse_event_report_type(struct map_event *event, const char *value)
  116. {
  117. if (!g_ascii_strcasecmp(value, "NewMessage"))
  118. event->type = MAP_ET_NEW_MESSAGE;
  119. else if (!g_ascii_strcasecmp(value, "DeliverySuccess"))
  120. event->type = MAP_ET_DELIVERY_SUCCESS;
  121. else if (!g_ascii_strcasecmp(value, "SendingSuccess"))
  122. event->type = MAP_ET_SENDING_SUCCESS;
  123. else if (!g_ascii_strcasecmp(value, "DeliveryFailure"))
  124. event->type = MAP_ET_DELIVERY_FAILURE;
  125. else if (!g_ascii_strcasecmp(value, "SendingFailure"))
  126. event->type = MAP_ET_SENDING_FAILURE;
  127. else if (!g_ascii_strcasecmp(value, "MemoryFull"))
  128. event->type = MAP_ET_MEMORY_FULL;
  129. else if (!g_ascii_strcasecmp(value, "MemoryAvailable"))
  130. event->type = MAP_ET_MEMORY_AVAILABLE;
  131. else if (!g_ascii_strcasecmp(value, "MessageDeleted"))
  132. event->type = MAP_ET_MESSAGE_DELETED;
  133. else if (!g_ascii_strcasecmp(value, "MessageShift"))
  134. event->type = MAP_ET_MESSAGE_SHIFT;
  135. }
  136. static void parse_event_report_handle(struct map_event *event,
  137. const char *value)
  138. {
  139. event->handle = strtoull(value, NULL, 16);
  140. }
  141. static void parse_event_report_folder(struct map_event *event,
  142. const char *value)
  143. {
  144. g_free(event->folder);
  145. if (g_str_has_prefix(value, "/"))
  146. event->folder = g_strdup(value);
  147. else
  148. event->folder = g_strconcat("/", value, NULL);
  149. }
  150. static void parse_event_report_old_folder(struct map_event *event,
  151. const char *value)
  152. {
  153. g_free(event->old_folder);
  154. if (g_str_has_prefix(value, "/"))
  155. event->old_folder = g_strdup(value);
  156. else
  157. event->old_folder = g_strconcat("/", value, NULL);
  158. }
  159. static void parse_event_report_msg_type(struct map_event *event,
  160. const char *value)
  161. {
  162. g_free(event->msg_type);
  163. event->msg_type = g_strdup(value);
  164. }
  165. static void parse_event_report_date_time(struct map_event *event,
  166. const char *value)
  167. {
  168. g_free(event->datetime);
  169. event->datetime = g_strdup(value);
  170. }
  171. static void parse_event_report_subject(struct map_event *event,
  172. const char *value)
  173. {
  174. g_free(event->subject);
  175. event->subject = g_strdup(value);
  176. }
  177. static void parse_event_report_sender_name(struct map_event *event,
  178. const char *value)
  179. {
  180. g_free(event->sender_name);
  181. event->sender_name = g_strdup(value);
  182. }
  183. static void parse_event_report_priority(struct map_event *event,
  184. const char *value)
  185. {
  186. g_free(event->priority);
  187. event->priority = g_strdup(value);
  188. }
  189. static struct map_event_report_parser {
  190. const char *name;
  191. void (*func) (struct map_event *event, const char *value);
  192. } event_report_parsers[] = {
  193. { "type", parse_event_report_type },
  194. { "handle", parse_event_report_handle },
  195. { "folder", parse_event_report_folder },
  196. { "old_folder", parse_event_report_old_folder },
  197. { "msg_type", parse_event_report_msg_type },
  198. { "datetime", parse_event_report_date_time },
  199. { "subject", parse_event_report_subject },
  200. { "sender_name", parse_event_report_sender_name },
  201. { "priority", parse_event_report_priority },
  202. { }
  203. };
  204. static void event_report_element(GMarkupParseContext *ctxt,
  205. const char *element, const char **names,
  206. const char **values, gpointer user_data,
  207. GError **gerr)
  208. {
  209. struct map_event *event = user_data;
  210. const char *key;
  211. int i;
  212. if (strcasecmp("event", element) != 0)
  213. return;
  214. for (i = 0, key = names[i]; key; key = names[++i]) {
  215. struct map_event_report_parser *parser;
  216. for (parser = event_report_parsers; parser && parser->name;
  217. parser++) {
  218. if (strcasecmp(key, parser->name) == 0) {
  219. if (values[i])
  220. parser->func(event, values[i]);
  221. break;
  222. }
  223. }
  224. }
  225. }
  226. static const GMarkupParser event_report_parser = {
  227. event_report_element,
  228. NULL,
  229. NULL,
  230. NULL,
  231. NULL
  232. };
  233. static void map_event_free(struct map_event *event)
  234. {
  235. g_free(event->folder);
  236. g_free(event->old_folder);
  237. g_free(event->msg_type);
  238. g_free(event->datetime);
  239. g_free(event->subject);
  240. g_free(event->sender_name);
  241. g_free(event->priority);
  242. g_free(event);
  243. }
  244. static void *event_report_open(const char *name, int oflag, mode_t mode,
  245. void *driver_data, size_t *size, int *err)
  246. {
  247. struct mns_session *mns = driver_data;
  248. DBG("");
  249. g_obex_apparam_get_uint8(mns->inparams, MAP_AP_MASINSTANCEID,
  250. &mns->mas_instance_id);
  251. mns->buffer = g_string_new("");
  252. if (err != NULL)
  253. *err = 0;
  254. return mns;
  255. }
  256. static int event_report_close(void *obj)
  257. {
  258. struct mns_session *mns = obj;
  259. GMarkupParseContext *ctxt;
  260. struct map_event *event;
  261. DBG("");
  262. event = g_new0(struct map_event, 1);
  263. ctxt = g_markup_parse_context_new(&event_report_parser, 0, event,
  264. NULL);
  265. g_markup_parse_context_parse(ctxt, mns->buffer->str, mns->buffer->len,
  266. NULL);
  267. g_markup_parse_context_free(ctxt);
  268. map_dispatch_event(mns->mas_instance_id, mns->remote_address, event);
  269. map_event_free(event);
  270. reset_request(mns);
  271. return 0;
  272. }
  273. static ssize_t event_report_write(void *obj, const void *buf, size_t count)
  274. {
  275. struct mns_session *mns = obj;
  276. DBG("");
  277. g_string_append_len(mns->buffer, buf, count);
  278. return count;
  279. }
  280. static struct obex_service_driver mns = {
  281. .name = "Message Notification server",
  282. .service = OBEX_MNS,
  283. .target = MNS_TARGET,
  284. .target_size = TARGET_SIZE,
  285. .connect = mns_connect,
  286. .put = mns_put,
  287. .disconnect = mns_disconnect,
  288. };
  289. static struct obex_mime_type_driver mime_event_report = {
  290. .target = MNS_TARGET,
  291. .target_size = TARGET_SIZE,
  292. .mimetype = "x-bt/MAP-event-report",
  293. .open = event_report_open,
  294. .close = event_report_close,
  295. .write = event_report_write,
  296. };
  297. static int mns_init(void)
  298. {
  299. int err;
  300. err = obex_mime_type_driver_register(&mime_event_report);
  301. if (err < 0)
  302. goto fail_mime_event;
  303. err = obex_service_driver_register(&mns);
  304. if (err < 0)
  305. goto fail_mns_reg;
  306. return 0;
  307. fail_mns_reg:
  308. obex_mime_type_driver_unregister(&mime_event_report);
  309. fail_mime_event:
  310. return err;
  311. }
  312. static void mns_exit(void)
  313. {
  314. obex_service_driver_unregister(&mns);
  315. obex_mime_type_driver_unregister(&mime_event_report);
  316. }
  317. OBEX_PLUGIN_DEFINE(mns, mns_init, mns_exit)