wps_upnp_event.c revision 209158
1228753Smm/* 2228753Smm * UPnP WPS Device - Event processing 3228753Smm * Copyright (c) 2000-2003 Intel Corporation 4228753Smm * Copyright (c) 2006-2007 Sony Corporation 5228753Smm * Copyright (c) 2008-2009 Atheros Communications 6228753Smm * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 7228753Smm * 8228753Smm * See wps_upnp.c for more details on licensing and code history. 9228753Smm */ 10228753Smm 11228753Smm#include "includes.h" 12228753Smm#include <assert.h> 13228753Smm#include <fcntl.h> 14228753Smm 15228753Smm#include "common.h" 16228753Smm#include "eloop.h" 17228753Smm#include "uuid.h" 18228753Smm#include "httpread.h" 19228753Smm#include "wps_defs.h" 20228753Smm#include "wps_upnp.h" 21228753Smm#include "wps_upnp_i.h" 22228753Smm 23228753Smm/* 24228753Smm * Event message generation (to subscribers) 25228753Smm * 26228763Smm * We make a separate copy for each message for each subscriber. This memory 27228753Smm * wasted could be limited (adding code complexity) by sharing copies, keeping 28228753Smm * a usage count and freeing when zero. 29228753Smm * 30228753Smm * Sending a message requires using a HTTP over TCP NOTIFY 31228753Smm * (like a PUT) which requires a number of states.. 32228753Smm */ 33228753Smm 34228753Smm#define MAX_EVENTS_QUEUED 20 /* How far behind queued events */ 35228753Smm#define EVENT_TIMEOUT_SEC 30 /* Drop sending event after timeout */ 36228753Smm 37228753Smm/* How long to wait before sending event */ 38228753Smm#define EVENT_DELAY_SECONDS 0 39228753Smm#define EVENT_DELAY_MSEC 0 40228753Smm 41228753Smm/* 42228753Smm * Event information that we send to each subscriber is remembered in this 43228753Smm * struct. The event cannot be sent by simple UDP; it has to be sent by a HTTP 44228753Smm * over TCP transaction which requires various states.. It may also need to be 45228753Smm * retried at a different address (if more than one is available). 46228753Smm * 47228753Smm * TODO: As an optimization we could share data between subscribers. 48228753Smm */ 49228753Smmstruct wps_event_ { 50228753Smm struct wps_event_ *next; 51228753Smm struct wps_event_ *prev; /* double linked list */ 52228753Smm struct subscription *s; /* parent */ 53228753Smm unsigned subscriber_sequence; /* which event for this subscription*/ 54228753Smm int retry; /* which retry */ 55228753Smm struct subscr_addr *addr; /* address to connect to */ 56228753Smm struct wpabuf *data; /* event data to send */ 57228753Smm /* The following apply while we are sending an event message. */ 58228753Smm int sd; /* -1 or socket descriptor for open connection */ 59228753Smm int sd_registered; /* nonzero if we must cancel registration */ 60228753Smm struct httpread *hread; /* NULL or open connection for event msg */ 61228753Smm}; 62228753Smm 63228753Smm 64228753Smmstatic void event_timeout_handler(void *eloop_data, void *user_ctx); 65228753Smm 66228753Smm/* event_clean -- clean sockets etc. of event 67228753Smm * Leaves data, retry count etc. alone. 68228753Smm */ 69228753Smmstatic void event_clean(struct wps_event_ *e) 70228753Smm{ 71228753Smm if (e->s->current_event == e) { 72228753Smm eloop_cancel_timeout(event_timeout_handler, NULL, e); 73228753Smm e->s->current_event = NULL; 74228753Smm } 75228753Smm if (e->sd_registered) { 76228753Smm eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); 77228753Smm e->sd_registered = 0; 78228753Smm } 79228753Smm if (e->sd != -1) { 80228753Smm close(e->sd); 81228753Smm e->sd = -1; 82228753Smm } 83228753Smm if (e->hread) 84228753Smm httpread_destroy(e->hread); 85228753Smm e->hread = NULL; 86228753Smm} 87228753Smm 88228753Smm 89228753Smm/* event_delete -- delete single unqueued event 90228753Smm * (be sure to dequeue first if need be) 91228753Smm */ 92228753Smmstatic void event_delete(struct wps_event_ *e) 93228753Smm{ 94228753Smm event_clean(e); 95228753Smm wpabuf_free(e->data); 96228753Smm os_free(e); 97228753Smm} 98228753Smm 99228753Smm 100228753Smm/* event_dequeue -- get next event from the queue 101228753Smm * Returns NULL if empty. 102228753Smm */ 103228753Smmstatic struct wps_event_ *event_dequeue(struct subscription *s) 104228753Smm{ 105228753Smm struct wps_event_ **event_head = &s->event_queue; 106228753Smm struct wps_event_ *e = *event_head; 107228753Smm if (e == NULL) 108228753Smm return NULL; 109228753Smm e->next->prev = e->prev; 110228753Smm e->prev->next = e->next; 111228753Smm if (*event_head == e) { 112228753Smm if (e == e->next) { 113228753Smm /* last in queue */ 114228753Smm *event_head = NULL; 115228753Smm } else { 116228753Smm *event_head = e->next; 117228753Smm } 118228753Smm } 119228753Smm s->n_queue--; 120228753Smm e->next = e->prev = NULL; 121228753Smm /* but parent "s" is still valid */ 122228753Smm return e; 123228753Smm} 124228753Smm 125228753Smm 126228753Smm/* event_enqueue_at_end -- add event to end of queue */ 127228753Smmstatic void event_enqueue_at_end(struct subscription *s, struct wps_event_ *e) 128228753Smm{ 129228753Smm struct wps_event_ **event_head = &s->event_queue; 130228753Smm if (*event_head == NULL) { 131228753Smm *event_head = e->next = e->prev = e; 132228753Smm } else { 133228753Smm e->next = *event_head; 134228753Smm e->prev = e->next->prev; 135228753Smm e->prev->next = e; 136228753Smm e->next->prev = e; 137228753Smm } 138228753Smm s->n_queue++; 139228753Smm} 140228753Smm 141228753Smm 142228753Smm/* event_enqueue_at_begin -- add event to begin of queue 143228753Smm * (appropriate for retrying event only) 144228753Smm */ 145228753Smmstatic void event_enqueue_at_begin(struct subscription *s, 146228753Smm struct wps_event_ *e) 147228753Smm{ 148228753Smm struct wps_event_ **event_head = &s->event_queue; 149228753Smm if (*event_head == NULL) { 150228753Smm *event_head = e->next = e->prev = e; 151228753Smm } else { 152228753Smm e->prev = *event_head; 153228753Smm e->next = e->prev->next; 154228753Smm e->prev->next = e; 155228753Smm e->next->prev = e; 156228753Smm *event_head = e; 157228753Smm } 158228753Smm s->n_queue++; 159228753Smm} 160228753Smm 161228753Smm 162228753Smm/* event_delete_all -- delete entire event queue and current event */ 163228753Smmvoid event_delete_all(struct subscription *s) 164228753Smm{ 165228753Smm struct wps_event_ *e; 166228753Smm while ((e = event_dequeue(s)) != NULL) 167228753Smm event_delete(e); 168228753Smm if (s->current_event) { 169228753Smm event_delete(s->current_event); 170228753Smm /* will set: s->current_event = NULL; */ 171228753Smm } 172228753Smm} 173228753Smm 174228753Smm 175228753Smm/** 176228753Smm * event_retry - Called when we had a failure delivering event msg 177228753Smm * @e: Event 178228753Smm * @do_next_address: skip address e.g. on connect fail 179228753Smm */ 180228753Smmstatic void event_retry(struct wps_event_ *e, int do_next_address) 181228753Smm{ 182228753Smm struct subscription *s = e->s; 183228753Smm struct upnp_wps_device_sm *sm = s->sm; 184228753Smm 185228753Smm event_clean(e); 186228753Smm /* will set: s->current_event = NULL; */ 187 188 if (do_next_address) 189 e->retry++; 190 if (e->retry >= s->n_addr) { 191 wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event " 192 "for %s", e->addr->domain_and_port); 193 return; 194 } 195 event_enqueue_at_begin(s, e); 196 event_send_all_later(sm); 197} 198 199 200/* called if the overall event-sending process takes too long */ 201static void event_timeout_handler(void *eloop_data, void *user_ctx) 202{ 203 struct wps_event_ *e = user_ctx; 204 struct subscription *s = e->s; 205 206 assert(e == s->current_event); 207 208 wpa_printf(MSG_DEBUG, "WPS UPnP: Event send timeout"); 209 event_retry(e, 1); 210} 211 212 213/* event_got_response_handler -- called back when http response is received. */ 214static void event_got_response_handler(struct httpread *handle, void *cookie, 215 enum httpread_event en) 216{ 217 struct wps_event_ *e = cookie; 218 struct subscription *s = e->s; 219 struct upnp_wps_device_sm *sm = s->sm; 220 struct httpread *hread = e->hread; 221 int reply_code = 0; 222 223 assert(e == s->current_event); 224 eloop_cancel_timeout(event_timeout_handler, NULL, e); 225 226 if (en == HTTPREAD_EVENT_FILE_READY) { 227 if (httpread_hdr_type_get(hread) == HTTPREAD_HDR_TYPE_REPLY) { 228 reply_code = httpread_reply_code_get(hread); 229 if (reply_code == HTTP_OK) { 230 wpa_printf(MSG_DEBUG, 231 "WPS UPnP: Got event reply OK from " 232 "%s", e->addr->domain_and_port); 233 event_delete(e); 234 goto send_more; 235 } else { 236 wpa_printf(MSG_DEBUG, "WPS UPnP: Got event " 237 "error reply code %d from %s", 238 reply_code, 239 e->addr->domain_and_port); 240 goto bad; 241 } 242 } else { 243 wpa_printf(MSG_DEBUG, "WPS UPnP: Got bogus event " 244 "response %d from %s", en, 245 e->addr->domain_and_port); 246 } 247 } else { 248 wpa_printf(MSG_DEBUG, "WPS UPnP: Event response timeout/fail " 249 "for %s", e->addr->domain_and_port); 250 goto bad; 251 } 252 event_retry(e, 1); 253 goto send_more; 254 255send_more: 256 /* Schedule sending more if there is more to send */ 257 if (s->event_queue) 258 event_send_all_later(sm); 259 return; 260 261bad: 262 /* 263 * If other side doesn't like what we say, forget about them. 264 * (There is no way to tell other side that we are dropping 265 * them...). 266 * Alternately, we could just do event_delete(e) 267 */ 268 wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription due to errors"); 269 subscription_unlink(s); 270 subscription_destroy(s); 271} 272 273 274/* event_send_tx_ready -- actually write event message 275 * 276 * Prequisite: subscription socket descriptor has become ready to 277 * write (because connection to subscriber has been made). 278 * 279 * It is also possible that we are called because the connect has failed; 280 * it is possible to test for this, or we can just go ahead and then 281 * the write will fail. 282 */ 283static void event_send_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) 284{ 285 struct wps_event_ *e = sock_ctx; 286 struct subscription *s = e->s; 287 struct wpabuf *buf; 288 char *b; 289 290 assert(e == s->current_event); 291 assert(e->sd == sock); 292 293 buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); 294 if (buf == NULL) { 295 event_retry(e, 0); 296 goto bad; 297 } 298 wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); 299 wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"); 300 wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port); 301 wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n" 302 "NT: upnp:event\r\n" 303 "NTS: upnp:propchange\r\n"); 304 wpabuf_put_str(buf, "SID: uuid:"); 305 b = wpabuf_put(buf, 0); 306 uuid_bin2str(s->uuid, b, 80); 307 wpabuf_put(buf, os_strlen(b)); 308 wpabuf_put_str(buf, "\r\n"); 309 wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence); 310 wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n", 311 (int) wpabuf_len(e->data)); 312 wpabuf_put_str(buf, "\r\n"); /* terminating empty line */ 313 wpabuf_put_buf(buf, e->data); 314 315 /* Since the message size is pretty small, we should be 316 * able to get the operating system to buffer what we give it 317 * and not have to come back again later to write more... 318 */ 319#if 0 320 /* we could: Turn blocking back on? */ 321 fcntl(e->sd, F_SETFL, 0); 322#endif 323 wpa_printf(MSG_DEBUG, "WPS UPnP: Sending event to %s", 324 e->addr->domain_and_port); 325 if (send_wpabuf(e->sd, buf) < 0) { 326 event_retry(e, 1); 327 goto bad; 328 } 329 wpabuf_free(buf); 330 buf = NULL; 331 332 if (e->sd_registered) { 333 e->sd_registered = 0; 334 eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); 335 } 336 /* Set up to read the reply */ 337 e->hread = httpread_create(e->sd, event_got_response_handler, 338 e /* cookie */, 339 0 /* no data expected */, 340 EVENT_TIMEOUT_SEC); 341 if (e->hread == NULL) { 342 wpa_printf(MSG_ERROR, "WPS UPnP: httpread_create failed"); 343 event_retry(e, 0); 344 goto bad; 345 } 346 return; 347 348bad: 349 /* Schedule sending more if there is more to send */ 350 if (s->event_queue) 351 event_send_all_later(s->sm); 352 wpabuf_free(buf); 353} 354 355 356/* event_send_start -- prepare to send a event message to subscriber 357 * 358 * This gets complicated because: 359 * -- The message is sent via TCP and we have to keep the stream open 360 * for 30 seconds to get a response... then close it. 361 * -- But we might have other event happen in the meantime... 362 * we have to queue them, if we lose them then the subscriber will 363 * be forced to unsubscribe and subscribe again. 364 * -- If multiple URLs are provided then we are supposed to try successive 365 * ones after 30 second timeout. 366 * -- The URLs might use domain names instead of dotted decimal addresses, 367 * and resolution of those may cause unwanted sleeping. 368 * -- Doing the initial TCP connect can take a while, so we have to come 369 * back after connection and then send the data. 370 * 371 * Returns nonzero on error; 372 * 373 * Prerequisite: No current event send (s->current_event == NULL) 374 * and non-empty queue. 375 */ 376static int event_send_start(struct subscription *s) 377{ 378 struct wps_event_ *e; 379 int itry; 380 381 /* 382 * Assume we are called ONLY with no current event and ONLY with 383 * nonempty event queue and ONLY with at least one address to send to. 384 */ 385 assert(s->addr_list != NULL); 386 assert(s->current_event == NULL); 387 assert(s->event_queue != NULL); 388 389 s->current_event = e = event_dequeue(s); 390 391 /* Use address acc. to no. of retries */ 392 e->addr = s->addr_list; 393 for (itry = 0; itry < e->retry; itry++) 394 e->addr = e->addr->next; 395 396 e->sd = socket(AF_INET, SOCK_STREAM, 0); 397 if (e->sd < 0) { 398 event_retry(e, 0); 399 return -1; 400 } 401 /* set non-blocking so we don't sleep waiting for connection */ 402 if (fcntl(e->sd, F_SETFL, O_NONBLOCK) != 0) { 403 event_retry(e, 0); 404 return -1; 405 } 406 /* 407 * Start the connect. It might succeed immediately but more likely will 408 * return errno EINPROGRESS. 409 */ 410 if (connect(e->sd, (struct sockaddr *) &e->addr->saddr, 411 sizeof(e->addr->saddr))) { 412 if (errno != EINPROGRESS) { 413 event_retry(e, 1); 414 return -1; 415 } 416 } 417 /* Call back when ready for writing (or on failure...). */ 418 if (eloop_register_sock(e->sd, EVENT_TYPE_WRITE, event_send_tx_ready, 419 NULL, e)) { 420 event_retry(e, 0); 421 return -1; 422 } 423 e->sd_registered = 1; 424 /* Don't wait forever! */ 425 if (eloop_register_timeout(EVENT_TIMEOUT_SEC, 0, event_timeout_handler, 426 NULL, e)) { 427 event_retry(e, 0); 428 return -1; 429 } 430 return 0; 431} 432 433 434/* event_send_all_later_handler -- actually send events as needed */ 435static void event_send_all_later_handler(void *eloop_data, void *user_ctx) 436{ 437 struct upnp_wps_device_sm *sm = user_ctx; 438 struct subscription *s; 439 struct subscription *s_old; 440 int nerrors = 0; 441 442 sm->event_send_all_queued = 0; 443 s = sm->subscriptions; 444 if (s == NULL) 445 return; 446 do { 447 if (s->addr_list == NULL) { 448 /* if we've given up on all addresses */ 449 wpa_printf(MSG_DEBUG, "WPS UPnP: Removing " 450 "subscription with no addresses"); 451 s_old = s; 452 s = s_old->next; 453 subscription_unlink(s_old); 454 subscription_destroy(s_old); 455 } else { 456 if (s->current_event == NULL /* not busy */ && 457 s->event_queue != NULL /* more to do */) { 458 if (event_send_start(s)) 459 nerrors++; 460 } 461 s = s->next; 462 } 463 } while (sm->subscriptions != NULL && s != sm->subscriptions); 464 465 if (nerrors) { 466 /* Try again later */ 467 event_send_all_later(sm); 468 } 469} 470 471 472/* event_send_all_later -- schedule sending events to all subscribers 473 * that need it. 474 * This avoids two problems: 475 * -- After getting a subscription, we should not send the first event 476 * until after our reply is fully queued to be sent back, 477 * -- Possible stack depth or infinite recursion issues. 478 */ 479void event_send_all_later(struct upnp_wps_device_sm *sm) 480{ 481 /* 482 * The exact time in the future isn't too important. Waiting a bit 483 * might let us do several together. 484 */ 485 if (sm->event_send_all_queued) 486 return; 487 sm->event_send_all_queued = 1; 488 eloop_register_timeout(EVENT_DELAY_SECONDS, EVENT_DELAY_MSEC, 489 event_send_all_later_handler, NULL, sm); 490} 491 492 493/* event_send_stop_all -- cleanup */ 494void event_send_stop_all(struct upnp_wps_device_sm *sm) 495{ 496 if (sm->event_send_all_queued) 497 eloop_cancel_timeout(event_send_all_later_handler, NULL, sm); 498 sm->event_send_all_queued = 0; 499} 500 501 502/** 503 * event_add - Add a new event to a queue 504 * @s: Subscription 505 * @data: Event data (is copied; caller retains ownership) 506 * Returns: 0 on success, 1 on error 507 */ 508int event_add(struct subscription *s, const struct wpabuf *data) 509{ 510 struct wps_event_ *e; 511 512 if (s->n_queue >= MAX_EVENTS_QUEUED) { 513 wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " 514 "subscriber"); 515 return 1; 516 } 517 518 e = os_zalloc(sizeof(*e)); 519 if (e == NULL) 520 return 1; 521 e->s = s; 522 e->sd = -1; 523 e->data = wpabuf_dup(data); 524 if (e->data == NULL) { 525 os_free(e); 526 return 1; 527 } 528 e->subscriber_sequence = s->next_subscriber_sequence++; 529 if (s->next_subscriber_sequence == 0) 530 s->next_subscriber_sequence++; 531 event_enqueue_at_end(s, e); 532 event_send_all_later(s->sm); 533 return 0; 534} 535