wps_upnp_event.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * UPnP WPS Device - Event processing
  3. * Copyright (c) 2000-2003 Intel Corporation
  4. * Copyright (c) 2006-2007 Sony Corporation
  5. * Copyright (c) 2008-2009 Atheros Communications
  6. * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  7. *
  8. * See wps_upnp.c for more details on licensing and code history.
  9. */
  10. #include "includes.h"
  11. #include <assert.h>
  12. #include "common.h"
  13. #include "eloop.h"
  14. #include "uuid.h"
  15. #include "http_client.h"
  16. #include "wps_defs.h"
  17. #include "wps_upnp.h"
  18. #include "wps_upnp_i.h"
  19. /*
  20. * Event message generation (to subscribers)
  21. *
  22. * We make a separate copy for each message for each subscriber. This memory
  23. * wasted could be limited (adding code complexity) by sharing copies, keeping
  24. * a usage count and freeing when zero.
  25. *
  26. * Sending a message requires using a HTTP over TCP NOTIFY
  27. * (like a PUT) which requires a number of states..
  28. */
  29. #define MAX_EVENTS_QUEUED 20 /* How far behind queued events */
  30. #define MAX_FAILURES 10 /* Drop subscription after this many failures */
  31. /* How long to wait before sending event */
  32. #define EVENT_DELAY_SECONDS 0
  33. #define EVENT_DELAY_MSEC 0
  34. /*
  35. * Event information that we send to each subscriber is remembered in this
  36. * struct. The event cannot be sent by simple UDP; it has to be sent by a HTTP
  37. * over TCP transaction which requires various states.. It may also need to be
  38. * retried at a different address (if more than one is available).
  39. *
  40. * TODO: As an optimization we could share data between subscribers.
  41. */
  42. struct wps_event_ {
  43. struct dl_list list;
  44. struct subscription *s; /* parent */
  45. unsigned subscriber_sequence; /* which event for this subscription*/
  46. unsigned int retry; /* which retry */
  47. struct subscr_addr *addr; /* address to connect to */
  48. struct wpabuf *data; /* event data to send */
  49. struct http_client *http_event;
  50. };
  51. /* event_clean -- clean sockets etc. of event
  52. * Leaves data, retry count etc. alone.
  53. */
  54. static void event_clean(struct wps_event_ *e)
  55. {
  56. if (e->s->current_event == e)
  57. e->s->current_event = NULL;
  58. http_client_free(e->http_event);
  59. e->http_event = NULL;
  60. }
  61. /* event_delete -- delete single unqueued event
  62. * (be sure to dequeue first if need be)
  63. */
  64. static void event_delete(struct wps_event_ *e)
  65. {
  66. wpa_printf(MSG_DEBUG, "WPS UPnP: Delete event %p", e);
  67. event_clean(e);
  68. wpabuf_free(e->data);
  69. os_free(e);
  70. }
  71. /* event_dequeue -- get next event from the queue
  72. * Returns NULL if empty.
  73. */
  74. static struct wps_event_ *event_dequeue(struct subscription *s)
  75. {
  76. struct wps_event_ *e;
  77. e = dl_list_first(&s->event_queue, struct wps_event_, list);
  78. if (e) {
  79. wpa_printf(MSG_DEBUG, "WPS UPnP: Dequeue event %p for "
  80. "subscription %p", e, s);
  81. dl_list_del(&e->list);
  82. }
  83. return e;
  84. }
  85. /* event_delete_all -- delete entire event queue and current event */
  86. void event_delete_all(struct subscription *s)
  87. {
  88. struct wps_event_ *e;
  89. while ((e = event_dequeue(s)) != NULL)
  90. event_delete(e);
  91. if (s->current_event) {
  92. event_delete(s->current_event);
  93. /* will set: s->current_event = NULL; */
  94. }
  95. }
  96. /**
  97. * event_retry - Called when we had a failure delivering event msg
  98. * @e: Event
  99. * @do_next_address: skip address e.g. on connect fail
  100. */
  101. static void event_retry(struct wps_event_ *e, int do_next_address)
  102. {
  103. struct subscription *s = e->s;
  104. struct upnp_wps_device_sm *sm = s->sm;
  105. wpa_printf(MSG_DEBUG, "WPS UPnP: Retry event %p for subscription %p",
  106. e, s);
  107. event_clean(e);
  108. /* will set: s->current_event = NULL; */
  109. if (do_next_address) {
  110. e->retry++;
  111. wpa_printf(MSG_DEBUG, "WPS UPnP: Try address %d", e->retry);
  112. }
  113. if (e->retry >= dl_list_len(&s->addr_list)) {
  114. wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event "
  115. "for %s", e->addr->domain_and_port);
  116. event_delete(e);
  117. s->last_event_failed = 1;
  118. if (!dl_list_empty(&s->event_queue))
  119. event_send_all_later(s->sm);
  120. return;
  121. }
  122. dl_list_add(&s->event_queue, &e->list);
  123. event_send_all_later(sm);
  124. }
  125. static struct wpabuf * event_build_message(struct wps_event_ *e)
  126. {
  127. struct wpabuf *buf;
  128. char *b;
  129. buf = wpabuf_alloc(1000 + wpabuf_len(e->data));
  130. if (buf == NULL)
  131. return NULL;
  132. wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path);
  133. wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n");
  134. wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port);
  135. wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
  136. "NT: upnp:event\r\n"
  137. "NTS: upnp:propchange\r\n");
  138. wpabuf_put_str(buf, "SID: uuid:");
  139. b = wpabuf_put(buf, 0);
  140. uuid_bin2str(e->s->uuid, b, 80);
  141. wpabuf_put(buf, os_strlen(b));
  142. wpabuf_put_str(buf, "\r\n");
  143. wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence);
  144. wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n",
  145. (int) wpabuf_len(e->data));
  146. wpabuf_put_str(buf, "\r\n"); /* terminating empty line */
  147. wpabuf_put_buf(buf, e->data);
  148. return buf;
  149. }
  150. static void event_addr_failure(struct wps_event_ *e)
  151. {
  152. struct subscription *s = e->s;
  153. e->addr->num_failures++;
  154. wpa_printf(MSG_DEBUG, "WPS UPnP: Failed to send event %p to %s "
  155. "(num_failures=%u)",
  156. e, e->addr->domain_and_port, e->addr->num_failures);
  157. if (e->addr->num_failures < MAX_FAILURES) {
  158. /* Try other addresses, if available */
  159. event_retry(e, 1);
  160. return;
  161. }
  162. /*
  163. * If other side doesn't like what we say, forget about them.
  164. * (There is no way to tell other side that we are dropping them...).
  165. */
  166. wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription %p "
  167. "address %s due to errors", s, e->addr->domain_and_port);
  168. dl_list_del(&e->addr->list);
  169. subscr_addr_delete(e->addr);
  170. e->addr = NULL;
  171. if (dl_list_empty(&s->addr_list)) {
  172. /* if we've given up on all addresses */
  173. wpa_printf(MSG_DEBUG, "WPS UPnP: Removing subscription %p "
  174. "with no addresses", s);
  175. dl_list_del(&s->list);
  176. subscription_destroy(s);
  177. return;
  178. }
  179. /* Try other addresses, if available */
  180. event_retry(e, 0);
  181. }
  182. static void event_http_cb(void *ctx, struct http_client *c,
  183. enum http_client_event event)
  184. {
  185. struct wps_event_ *e = ctx;
  186. struct subscription *s = e->s;
  187. wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP client callback: e=%p c=%p "
  188. "event=%d", e, c, event);
  189. switch (event) {
  190. case HTTP_CLIENT_OK:
  191. wpa_printf(MSG_DEBUG,
  192. "WPS UPnP: Got event %p reply OK from %s",
  193. e, e->addr->domain_and_port);
  194. e->addr->num_failures = 0;
  195. s->last_event_failed = 0;
  196. event_delete(e);
  197. /* Schedule sending more if there is more to send */
  198. if (!dl_list_empty(&s->event_queue))
  199. event_send_all_later(s->sm);
  200. break;
  201. case HTTP_CLIENT_FAILED:
  202. wpa_printf(MSG_DEBUG, "WPS UPnP: Event send failure");
  203. event_addr_failure(e);
  204. break;
  205. case HTTP_CLIENT_INVALID_REPLY:
  206. wpa_printf(MSG_DEBUG, "WPS UPnP: Invalid reply");
  207. event_addr_failure(e);
  208. break;
  209. case HTTP_CLIENT_TIMEOUT:
  210. wpa_printf(MSG_DEBUG, "WPS UPnP: Event send timeout");
  211. event_addr_failure(e);
  212. break;
  213. }
  214. }
  215. /* event_send_start -- prepare to send a event message to subscriber
  216. *
  217. * This gets complicated because:
  218. * -- The message is sent via TCP and we have to keep the stream open
  219. * for 30 seconds to get a response... then close it.
  220. * -- But we might have other event happen in the meantime...
  221. * we have to queue them, if we lose them then the subscriber will
  222. * be forced to unsubscribe and subscribe again.
  223. * -- If multiple URLs are provided then we are supposed to try successive
  224. * ones after 30 second timeout.
  225. * -- The URLs might use domain names instead of dotted decimal addresses,
  226. * and resolution of those may cause unwanted sleeping.
  227. * -- Doing the initial TCP connect can take a while, so we have to come
  228. * back after connection and then send the data.
  229. *
  230. * Returns nonzero on error;
  231. *
  232. * Prerequisite: No current event send (s->current_event == NULL)
  233. * and non-empty queue.
  234. */
  235. static int event_send_start(struct subscription *s)
  236. {
  237. struct wps_event_ *e;
  238. unsigned int itry;
  239. struct wpabuf *buf;
  240. /*
  241. * Assume we are called ONLY with no current event and ONLY with
  242. * nonempty event queue and ONLY with at least one address to send to.
  243. */
  244. if (dl_list_empty(&s->addr_list))
  245. return -1;
  246. if (s->current_event)
  247. return -1;
  248. if (dl_list_empty(&s->event_queue))
  249. return -1;
  250. s->current_event = e = event_dequeue(s);
  251. /* Use address according to number of retries */
  252. itry = 0;
  253. dl_list_for_each(e->addr, &s->addr_list, struct subscr_addr, list)
  254. if (itry++ == e->retry)
  255. break;
  256. if (itry < e->retry)
  257. return -1;
  258. buf = event_build_message(e);
  259. if (buf == NULL) {
  260. event_retry(e, 0);
  261. return -1;
  262. }
  263. e->http_event = http_client_addr(&e->addr->saddr, buf, 0,
  264. event_http_cb, e);
  265. if (e->http_event == NULL) {
  266. wpabuf_free(buf);
  267. event_retry(e, 0);
  268. return -1;
  269. }
  270. return 0;
  271. }
  272. /* event_send_all_later_handler -- actually send events as needed */
  273. static void event_send_all_later_handler(void *eloop_data, void *user_ctx)
  274. {
  275. struct upnp_wps_device_sm *sm = user_ctx;
  276. struct subscription *s, *tmp;
  277. int nerrors = 0;
  278. sm->event_send_all_queued = 0;
  279. dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
  280. list) {
  281. if (s->current_event == NULL /* not busy */ &&
  282. !dl_list_empty(&s->event_queue) /* more to do */) {
  283. if (event_send_start(s))
  284. nerrors++;
  285. }
  286. }
  287. if (nerrors) {
  288. /* Try again later */
  289. event_send_all_later(sm);
  290. }
  291. }
  292. /* event_send_all_later -- schedule sending events to all subscribers
  293. * that need it.
  294. * This avoids two problems:
  295. * -- After getting a subscription, we should not send the first event
  296. * until after our reply is fully queued to be sent back,
  297. * -- Possible stack depth or infinite recursion issues.
  298. */
  299. void event_send_all_later(struct upnp_wps_device_sm *sm)
  300. {
  301. /*
  302. * The exact time in the future isn't too important. Waiting a bit
  303. * might let us do several together.
  304. */
  305. if (sm->event_send_all_queued)
  306. return;
  307. sm->event_send_all_queued = 1;
  308. eloop_register_timeout(EVENT_DELAY_SECONDS, EVENT_DELAY_MSEC,
  309. event_send_all_later_handler, NULL, sm);
  310. }
  311. /* event_send_stop_all -- cleanup */
  312. void event_send_stop_all(struct upnp_wps_device_sm *sm)
  313. {
  314. if (sm->event_send_all_queued)
  315. eloop_cancel_timeout(event_send_all_later_handler, NULL, sm);
  316. sm->event_send_all_queued = 0;
  317. }
  318. /**
  319. * event_add - Add a new event to a queue
  320. * @s: Subscription
  321. * @data: Event data (is copied; caller retains ownership)
  322. * @probereq: Whether this is a Probe Request event
  323. * Returns: 0 on success, -1 on error, 1 on max event queue limit reached
  324. */
  325. int event_add(struct subscription *s, const struct wpabuf *data, int probereq)
  326. {
  327. struct wps_event_ *e;
  328. unsigned int len;
  329. len = dl_list_len(&s->event_queue);
  330. if (len >= MAX_EVENTS_QUEUED) {
  331. wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for "
  332. "subscriber %p", s);
  333. if (probereq)
  334. return 1;
  335. /* Drop oldest entry to allow EAP event to be stored. */
  336. e = event_dequeue(s);
  337. if (!e)
  338. return 1;
  339. event_delete(e);
  340. }
  341. if (s->last_event_failed && probereq && len > 0) {
  342. /*
  343. * Avoid queuing frames for subscribers that may have left
  344. * without unsubscribing.
  345. */
  346. wpa_printf(MSG_DEBUG, "WPS UPnP: Do not queue more Probe "
  347. "Request frames for subscription %p since last "
  348. "delivery failed", s);
  349. return -1;
  350. }
  351. e = os_zalloc(sizeof(*e));
  352. if (e == NULL)
  353. return -1;
  354. dl_list_init(&e->list);
  355. e->s = s;
  356. e->data = wpabuf_dup(data);
  357. if (e->data == NULL) {
  358. os_free(e);
  359. return -1;
  360. }
  361. e->subscriber_sequence = s->next_subscriber_sequence++;
  362. if (s->next_subscriber_sequence == 0)
  363. s->next_subscriber_sequence++;
  364. wpa_printf(MSG_DEBUG, "WPS UPnP: Queue event %p for subscriber %p "
  365. "(queue len %u)", e, s, len + 1);
  366. dl_list_add_tail(&s->event_queue, &e->list);
  367. event_send_all_later(s->sm);
  368. return 0;
  369. }