Example #1
0
void wps_er_ssdp_deinit(struct wps_er *er)
{
	if (er->multicast_sd >= 0) {
		eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
		close(er->multicast_sd);
	}
	if (er->ssdp_sd >= 0) {
		eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
		close(er->ssdp_sd);
	}
}
Example #2
0
static void remove_watch(DBusWatch *watch, void *data)
{
	unsigned int flags;
	int fd;

	flags = dbus_watch_get_flags(watch);
	fd = dbus_watch_get_unix_fd(watch);

	eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);

	if (flags & DBUS_WATCH_READABLE)
		eloop_unregister_sock(fd, EVENT_TYPE_READ);
	if (flags & DBUS_WATCH_WRITABLE)
		eloop_unregister_sock(fd, EVENT_TYPE_WRITE);

	dbus_watch_set_data(watch, NULL, NULL);
}
Example #3
0
static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface,
					  DBusWatch *watch)
{
	unsigned int flags;
	int fd;

	flags = dbus_watch_get_flags(watch);
	fd = dbus_watch_get_unix_fd(watch);

	eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);

	if (flags & DBUS_WATCH_READABLE)
		eloop_unregister_sock(fd, EVENT_TYPE_READ);
	if (flags & DBUS_WATCH_WRITABLE)
		eloop_unregister_sock(fd, EVENT_TYPE_WRITE);

	dbus_watch_set_data(watch, NULL, NULL);
}
Example #4
0
static void http_client_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct http_client *c = eloop_ctx;
	int res;

	wpa_printf(MSG_DEBUG, "HTTP: Send client request to %s:%d (%lu of %lu "
		   "bytes remaining)",
		   inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port),
		   (unsigned long) wpabuf_len(c->req),
		   (unsigned long) wpabuf_len(c->req) - c->req_pos);

	res = send(c->sd, wpabuf_head(c->req) + c->req_pos,
		   wpabuf_len(c->req) - c->req_pos, 0);
	if (res < 0) {
		wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s",
			   strerror(errno));
		eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
		c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED);
		return;
	}

	if ((size_t) res < wpabuf_len(c->req) - c->req_pos) {
		wpa_printf(MSG_DEBUG, "HTTP: Sent %d of %lu bytes; %lu bytes "
			   "remaining",
			   res, (unsigned long) wpabuf_len(c->req),
			   (unsigned long) wpabuf_len(c->req) - c->req_pos -
			   res);
		c->req_pos += res;
		return;
	}

	wpa_printf(MSG_DEBUG, "HTTP: Full client request sent to %s:%d",
		   inet_ntoa(c->dst.sin_addr), ntohs(c->dst.sin_port));
	eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
	wpabuf_free(c->req);
	c->req = NULL;

	c->hread = httpread_create(c->sd, http_client_got_response, c,
				   c->max_response, HTTP_CLIENT_TIMEOUT_SEC);
	if (c->hread == NULL) {
		c->cb(c->cb_ctx, c, HTTP_CLIENT_FAILED);
		return;
	}
}
Example #5
0
void http_client_free(struct http_client *c)
{
	if (c == NULL)
		return;
	httpread_destroy(c->hread);
	wpabuf_free(c->req);
	if (c->sd >= 0) {
		eloop_unregister_sock(c->sd, EVENT_TYPE_WRITE);
		close(c->sd);
	}
	eloop_cancel_timeout(http_client_timeout, c, NULL);
	os_free(c);
}
Example #6
0
/* httpread_destroy -- if h is non-NULL, clean up
 * This must eventually be called by the application following
 * call of the application's callback and may be called
 * earlier if desired.
 */
void httpread_destroy(struct httpread *h)
{
	wpa_printf(MSG_DEBUG, "httpread_destroy(%p)", h);
	if (!h)
		return;

	eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
	eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
	os_free(h->body);
	os_free(h->uri);
	os_memset(h, 0, sizeof(*h));  /* aid debugging */
	h->sd = -1;     /* aid debugging */
	os_free(h);
}
/* event_clean -- clean sockets etc. of event
 * Leaves data, retry count etc. alone.
 */
static void event_clean(struct wps_event_ *e)
{
	if (e->s->current_event == e) {
		eloop_cancel_timeout(event_timeout_handler, NULL, e);
		e->s->current_event = NULL;
	}
	if (e->sd_registered) {
		eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE);
		e->sd_registered = 0;
	}
	if (e->sd != -1) {
		close(e->sd);
		e->sd = -1;
	}
	if (e->hread)
		httpread_destroy(e->hread);
	e->hread = NULL;
}
/* event_send_tx_ready -- actually write event message
 *
 * Prequisite: subscription socket descriptor has become ready to
 * write (because connection to subscriber has been made).
 *
 * It is also possible that we are called because the connect has failed;
 * it is possible to test for this, or we can just go ahead and then
 * the write will fail.
 */
static void event_send_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct wps_event_ *e = sock_ctx;
	struct subscription *s = e->s;
	struct wpabuf *buf;
	char *b;

	assert(e == s->current_event);
	assert(e->sd == sock);

	buf = wpabuf_alloc(1000 + wpabuf_len(e->data));
	if (buf == NULL) {
		event_retry(e, 0);
		goto bad;
	}
	wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path);
	wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n");
	wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port);
	wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
		       "NT: upnp:event\r\n"
		       "NTS: upnp:propchange\r\n");
	wpabuf_put_str(buf, "SID: uuid:");
	b = wpabuf_put(buf, 0);
	uuid_bin2str(s->uuid, b, 80);
	wpabuf_put(buf, os_strlen(b));
	wpabuf_put_str(buf, "\r\n");
	wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence);
	wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n",
		      (int) wpabuf_len(e->data));
	wpabuf_put_str(buf, "\r\n"); /* terminating empty line */
	wpabuf_put_buf(buf, e->data);

	/* Since the message size is pretty small, we should be
	 * able to get the operating system to buffer what we give it
	 * and not have to come back again later to write more...
	 */
#if 0
	/* we could: Turn blocking back on? */
	fcntl(e->sd, F_SETFL, 0);
#endif
	wpa_printf(MSG_DEBUG, "WPS UPnP: Sending event to %s",
		   e->addr->domain_and_port);
	if (send_wpabuf(e->sd, buf) < 0) {
		event_retry(e, 1);
		goto bad;
	}
	wpabuf_free(buf);
	buf = NULL;

	if (e->sd_registered) {
		e->sd_registered = 0;
		eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE);
	}
	/* Set up to read the reply */
	e->hread = httpread_create(e->sd, event_got_response_handler,
				   e /* cookie */,
				   0 /* no data expected */,
				   EVENT_TIMEOUT_SEC);
	if (e->hread == NULL) {
		wpa_printf(MSG_ERROR, "WPS UPnP: httpread_create failed");
		event_retry(e, 0);
		goto bad;
	}
	return;

bad:
	/* Schedule sending more if there is more to send */
	if (s->event_queue)
		event_send_all_later(s->sm);
	wpabuf_free(buf);
}
void eloop_unregister_read_sock(int sock)
{
    eloop_unregister_sock(sock, EVENT_TYPE_READ);
}
Example #10
0
/* httpread_read_handler -- called when socket ready to read
 *
 * Note: any extra data we read past end of transmitted file is ignored;
 * if we were to support keeping connections open for multiple files then
 * this would have to be addressed.
 */
static void httpread_read_handler(int sd, void *eloop_ctx, void *sock_ctx)
{
    struct httpread *h = sock_ctx;
    int nread;
    char *rbp;      /* pointer into read buffer */
    char *hbp;      /* pointer into header buffer */
    char *bbp;      /* pointer into body buffer */
    char readbuf[HTTPREAD_READBUF_SIZE];  /* temp use to read into */

    if (httpread_debug >= 20)
        wpa_printf(MSG_DEBUG, "ENTER httpread_read_handler(%p)", h);

    /* read some at a time, then search for the interal
     * boundaries between header and data and etc.
     */
    nread = read(h->sd, readbuf, sizeof(readbuf));
    if (nread < 0)
        goto bad;
    if (nread == 0) {
        /* end of transmission... this may be normal
         * or may be an error... in some cases we can't
         * tell which so we must assume it is normal then.
         */
        if (!h->got_hdr) {
            /* Must at least have completed header */
            wpa_printf(MSG_DEBUG, "httpread premature eof(%p)", h);
            goto bad;
        }
        if (h->chunked || h->got_content_length) {
            /* Premature EOF; e.g. dropped connection */
            wpa_printf(MSG_DEBUG,
                       "httpread premature eof(%p) %d/%d",
                       h, h->body_nbytes,
                       h->content_length);
            goto bad;
        }
        /* No explicit length, hopefully we have all the data
         * although dropped connections can cause false
         * end
         */
        if (httpread_debug >= 10)
            wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h);
        h->got_body = 1;
        goto got_file;
    }
    rbp = readbuf;

    /* Header consists of text lines (terminated by both CR and LF)
     * and an empty line (CR LF only).
     */
    if (!h->got_hdr) {
        hbp = h->hdr + h->hdr_nbytes;
        /* add to headers until:
         *      -- we run out of data in read buffer
         *      -- or, we run out of header buffer room
         *      -- or, we get double CRLF in headers
         */
        for (;;) {
            if (nread == 0)
                goto get_more;
            if (h->hdr_nbytes == HTTPREAD_HEADER_MAX_SIZE) {
                goto bad;
            }
            *hbp++ = *rbp++;
            nread--;
            h->hdr_nbytes++;
            if (h->hdr_nbytes >= 4 &&
                    hbp[-1] == '\n' &&
                    hbp[-2] == '\r' &&
                    hbp[-3] == '\n' &&
                    hbp[-4] == '\r' ) {
                h->got_hdr = 1;
                *hbp = 0;       /* null terminate */
                break;
            }
        }
        /* here we've just finished reading the header */
        if (httpread_hdr_analyze(h)) {
            wpa_printf(MSG_DEBUG, "httpread bad hdr(%p)", h);
            goto bad;
        }
        if (h->max_bytes == 0) {
            if (httpread_debug >= 10)
                wpa_printf(MSG_DEBUG,
                           "httpread no body hdr end(%p)", h);
            goto got_file;
        }
        if (h->got_content_length && h->content_length == 0) {
            if (httpread_debug >= 10)
                wpa_printf(MSG_DEBUG,
                           "httpread zero content length(%p)",
                           h);
            goto got_file;
        }
    }

    /* Certain types of requests never have data and so
     * must be specially recognized.
     */
    if (!os_strncasecmp(h->hdr, "SUBSCRIBE", 9) ||
            !os_strncasecmp(h->hdr, "UNSUBSCRIBE", 11) ||
            !os_strncasecmp(h->hdr, "HEAD", 4) ||
            !os_strncasecmp(h->hdr, "GET", 3)) {
        if (!h->got_body) {
            if (httpread_debug >= 10)
                wpa_printf(MSG_DEBUG,
                           "httpread NO BODY for sp. type");
        }
        h->got_body = 1;
        goto got_file;
    }

    /* Data can be just plain binary data, or if "chunked"
     * consists of chunks each with a header, ending with
     * an ending header.
     */
    if (!h->got_body) {
        /* Here to get (more of) body */
        /* ensure we have enough room for worst case for body
         * plus a null termination character
         */
        if (h->body_alloc_nbytes < (h->body_nbytes + nread + 1)) {
            char *new_body;
            int new_alloc_nbytes;

            if (h->body_nbytes >= h->max_bytes)
                goto bad;
            new_alloc_nbytes = h->body_alloc_nbytes +
                               HTTPREAD_BODYBUF_DELTA;
            /* For content-length case, the first time
             * through we allocate the whole amount
             * we need.
             */
            if (h->got_content_length &&
                    new_alloc_nbytes < (h->content_length + 1))
                new_alloc_nbytes = h->content_length + 1;
            if ((new_body = os_realloc(h->body, new_alloc_nbytes))
                    == NULL)
                goto bad;

            h->body = new_body;
            h->body_alloc_nbytes = new_alloc_nbytes;
        }
        /* add bytes */
        bbp = h->body + h->body_nbytes;
        for (;;) {
            int ncopy;
            /* See if we need to stop */
            if (h->chunked && h->in_chunk_data == 0) {
                /* in chunk header */
                char *cbp = h->body + h->chunk_start;
                if (bbp-cbp >= 2 && bbp[-2] == '\r' &&
                        bbp[-1] == '\n') {
                    /* end of chunk hdr line */
                    /* hdr line consists solely
                     * of a hex numeral and CFLF
                     */
                    if (!isxdigit(*cbp))
                        goto bad;
                    h->chunk_size = strtoul(cbp, NULL, 16);
                    /* throw away chunk header
                     * so we have only real data
                     */
                    h->body_nbytes = h->chunk_start;
                    bbp = cbp;
                    if (h->chunk_size == 0) {
                        /* end of chunking */
                        /* trailer follows */
                        h->in_trailer = 1;
                        if (httpread_debug >= 20)
                            wpa_printf(
                                MSG_DEBUG,
                                "httpread end chunks(%p)", h);
                        break;
                    }
                    h->in_chunk_data = 1;
                    /* leave chunk_start alone */
                }
            } else if (h->chunked) {
                /* in chunk data */
                if ((h->body_nbytes - h->chunk_start) ==
                        (h->chunk_size + 2)) {
                    /* end of chunk reached,
                     * new chunk starts
                     */
                    /* check chunk ended w/ CRLF
                     * which we'll throw away
                     */
                    if (bbp[-1] == '\n' &&
                            bbp[-2] == '\r') {
                    } else
                        goto bad;
                    h->body_nbytes -= 2;
                    bbp -= 2;
                    h->chunk_start = h->body_nbytes;
                    h->in_chunk_data = 0;
                    h->chunk_size = 0; /* just in case */
                }
            } else if (h->got_content_length &&
                       h->body_nbytes >= h->content_length) {
                h->got_body = 1;
                if (httpread_debug >= 10)
                    wpa_printf(
                        MSG_DEBUG,
                        "httpread got content(%p)", h);
                goto got_file;
            }
            if (nread <= 0)
                break;
            /* Now transfer. Optimize using memcpy where we can. */
            if (h->chunked && h->in_chunk_data) {
                /* copy up to remainder of chunk data
                 * plus the required CR+LF at end
                 */
                ncopy = (h->chunk_start + h->chunk_size + 2) -
                        h->body_nbytes;
            } else if (h->chunked) {
                /*in chunk header -- don't optimize */
                *bbp++ = *rbp++;
                nread--;
                h->body_nbytes++;
                continue;
            } else if (h->got_content_length) {
                ncopy = h->content_length - h->body_nbytes;
            } else {
                ncopy = nread;
            }
            /* Note: should never be 0 */
            if (ncopy > nread)
                ncopy = nread;
            os_memcpy(bbp, rbp, ncopy);
            bbp += ncopy;
            h->body_nbytes += ncopy;
            rbp += ncopy;
            nread -= ncopy;
        }       /* body copy loop */
    }       /* !got_body */
    if (h->chunked && h->in_trailer) {
        /* If "chunked" then there is always a trailer,
         * consisting of zero or more non-empty lines
         * ending with CR LF and then an empty line w/ CR LF.
         * We do NOT support trailers except to skip them --
         * this is supported (generally) by the http spec.
         */
        bbp = h->body + h->body_nbytes;
        for (;;) {
            int c;
            if (nread <= 0)
                break;
            c = *rbp++;
            nread--;
            switch (h->trailer_state) {
            case trailer_line_begin:
                if (c == '\r')
                    h->trailer_state = trailer_empty_cr;
                else
                    h->trailer_state = trailer_nonempty;
                break;
            case trailer_empty_cr:
                /* end empty line */
                if (c == '\n') {
                    h->trailer_state = trailer_line_begin;
                    h->in_trailer = 0;
                    if (httpread_debug >= 10)
                        wpa_printf(
                            MSG_DEBUG,
                            "httpread got content(%p)", h);
                    h->got_body = 1;
                    goto got_file;
                }
                h->trailer_state = trailer_nonempty;
                break;
            case trailer_nonempty:
                if (c == '\r')
                    h->trailer_state = trailer_nonempty_cr;
                break;
            case trailer_nonempty_cr:
                if (c == '\n')
                    h->trailer_state = trailer_line_begin;
                else
                    h->trailer_state = trailer_nonempty;
                break;
            }
        }
    }
    goto get_more;

bad:
    /* Error */
    wpa_printf(MSG_DEBUG, "httpread read/parse failure (%p)", h);
    (*h->cb)(h, h->cookie, HTTPREAD_EVENT_ERROR);
    return;

get_more:
    return;

got_file:
    if (httpread_debug >= 10)
        wpa_printf(MSG_DEBUG,
                   "httpread got file %d bytes type %d",
                   h->body_nbytes, h->hdr_type);
    /* Null terminate for convenience of some applications */
    if (h->body)
        h->body[h->body_nbytes] = 0; /* null terminate */
    h->got_file = 1;
    /* Assume that we do NOT support keeping connection alive,
     * and just in case somehow we don't get destroyed right away,
     * unregister now.
     */
    if (h->sd_registered)
        eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
    h->sd_registered = 0;
    /* The application can destroy us whenever they feel like...
     * cancel timeout.
     */
    if (h->to_registered)
        eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
    h->to_registered = 0;
    (*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY);
}