Пример #1
0
static void upnpc_subscribe_response(struct evhttp_request * req, void * pvoid)
{
	size_t len;
	unsigned char * data;
	struct evbuffer * input_buffer;
	upnpc_device_t * d = (upnpc_device_t *)pvoid;

	if(req == NULL) {
		debug_printf("%s(%p, %p) NULL argument !\n", __func__, req, pvoid);
		return;
	}
	input_buffer = evhttp_request_get_input_buffer(req);
	len = evbuffer_get_length(input_buffer);
	data = evbuffer_pullup(input_buffer, len);
	debug_printf("%s %d (%d bytes)\n", __func__, evhttp_request_get_response_code(req), (int)len);
	d->state &= ~UPNPC_DEVICE_SOAP_REQ;
	if(evhttp_request_get_response_code(req) != HTTP_OK) {
		/* TODO ERROR */
	} else {
		const char * sid;
		struct evkeyvalq * headers = evhttp_request_get_input_headers(req);
		sid = evhttp_find_header(headers, "sid");
		debug_printf("SID=%s\n", sid);
		if(sid) {
			if(d->event_conn_sid)
				free(d->event_conn_sid);
			d->event_conn_sid = strdup(sid);
		}
	}
}
Пример #2
0
void dump_http_header(struct evhttp_request *req, struct evbuffer *evb, void *ctx)
{
	struct evkeyvalq *head = evhttp_request_get_input_headers(req);
	struct evkeyval *entry;
	TAILQ_FOREACH(entry, head, next) {
		evbuffer_add_printf(evb, "%s:%s<br>", entry->key, entry->value);
	}
Пример #3
0
static char *read_req_buffer(struct evhttp_request *req) {
    struct evkeyvalq *headers = 
        evhttp_request_get_input_headers(req);
    int content_length = MAX_CONTENT_LENGTH;
    //TODO: use evhttp_find_header
    for(struct evkeyval *header = headers->tqh_first; header;
            header = header->next.tqe_next) {
        //TODO: should be strcmp ignoring case
        if(0 == strcmp(header->key, CONTENT_LENGTH_HEADER)) {
            content_length = atoi(header->value);
            break;
        }
    }
    char *str = (char *)malloc(content_length + 1);
    if(!str) {
        return NULL;
    }

    struct evbuffer *buf = evhttp_request_get_input_buffer(req);
    int nread = 0;
    while (evbuffer_get_length(buf)) {
        char cbuf[128];
        int n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
        if(n > 0) {
            memmove(str + nread, cbuf, n);
            nread += n;
        }
    }
    str[nread] = '\0';

    return str;
}
Пример #4
0
std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
{
    const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
    assert(headers);
    const char* val = evhttp_find_header(headers, hdr.c_str());
    if (val)
        return std::make_pair(true, val);
    else
        return std::make_pair(false, "");
}
Пример #5
0
void xBlog::DebugHttpHeader(struct evhttp_request *req)
{
    struct evkeyval *header;
    struct evkeyvalq *headers;

    headers = evhttp_request_get_input_headers(req);
    for (header = headers->tqh_first; header; header = header->next.tqe_next)
    {
        log_debug("%s: %s\n", header->key, header->value);
    }
}
Пример #6
0
void upnpc_event_conn_req(struct evhttp_request * req, void * data)
{
	size_t len;
	char * xml_data;
	struct evbuffer * input_buffer;
	struct evkeyvalq * headers;
	const char * sid;
	const char * nts;
	const char * nt;
	const char * seq;
	struct NameValueParserData parsed_data;
	struct NameValue * nv;
	upnpc_device_t * d = (upnpc_device_t *)data;

	debug_printf("%s(%p, %p)\n", __func__, req, d);
	headers = evhttp_request_get_input_headers(req);
	input_buffer = evhttp_request_get_input_buffer(req);
	len = evbuffer_get_length(input_buffer);
	sid = evhttp_find_header(headers, "sid");
	nts = evhttp_find_header(headers, "nts");
	nt = evhttp_find_header(headers, "nt");
	seq = evhttp_find_header(headers, "seq");
	if(len == 0 || nts == NULL || nt == NULL) {
		/* 400 Bad request :
		 * The NT or NTS header field is missing
		 * or the request is malformed. */
		evhttp_send_reply(req, 400, "Bad Request", NULL);
		return;
	}
	debug_printf("SID=%s NTS=%s SEQ=%s\n", sid, nts, seq);
	if(sid == NULL || 0 != strcmp(sid, d->event_conn_sid)
	   || 0 != strcmp(nt, "upnp:event") || 0 != strcmp(nts, "upnp:propchange")) {
		/* 412 Precondition Failed :
		 *  An SID does not correspond to a known, un-expired subscription
		 *  or the NT header field does not equal upnp:event
		 *  or the NTS header field does not equal upnp:propchange
		 *  or the SID header field is missing or empty.  */
		evhttp_send_reply(req, 412, "Precondition Failed", NULL);
		return;
	}
	xml_data = (char *)evbuffer_pullup(input_buffer, len);
	/*debug_printf("%.*s\n", len, xml_data);*/
	ParseNameValue(xml_data, len, &parsed_data);
	for(nv = parsed_data.l_head; nv != NULL; nv = nv->l_next) {
		if(d->parent->value_changed_cb) {
			d->parent->value_changed_cb(d->parent, d, d->parent->cb_data, d->conn_service_type, nv->name, nv->value);
		} else {
			debug_printf("%s=%s\n", nv->name, nv->value);
		}
	}
	ClearNameValueList(&parsed_data);
	/* response : 200 OK */
	evhttp_send_reply(req, 200, "OK", NULL);
}
static void parseRequest(RequestInfo& requestInfo) {
  const struct evhttp_uri* uri = evhttp_request_get_evhttp_uri(requestInfo.req);
  /*const*/ struct evhttp_connection* conn = evhttp_request_get_connection(requestInfo.req);
  
  requestInfo.method = evhttp_request_get_command(requestInfo.req);
  requestInfo.uriHost = evhttp_uri_get_host(uri);
  requestInfo.uriPath = evhttp_uri_get_path(uri);
  requestInfo.uriQuery = evhttp_uri_get_query(uri);
  requestInfo.uriScheme = evhttp_uri_get_scheme(uri);
  requestInfo.requestHeaders = evhttp_request_get_input_headers(requestInfo.req);
  requestInfo.requestBody = evhttp_request_get_input_buffer(requestInfo.req);
  evhttp_connection_get_peer(conn, &requestInfo.remoteAddress, (ev_uint16_t*) &requestInfo.remotePort);
}
Пример #8
0
char *http_get_cookie(struct evhttp_request *req, const char *key) {
    struct evkeyvalq *headers;
    struct evkeyval *header;
    headers = evhttp_request_get_input_headers(req);

	for (header = headers->tqh_first; header; header = header->next.tqe_next) {
	        // find cookie header
            if (strcmp(header->key, "Cookie") == 0) {
                return header->value;
            }
	}
	
    return " ";
}
int HttpServerMsgHandler::processMessage(void *arg) {
	struct evhttp_request *req = (struct evhttp_request *)arg;

	const char *cmdtype;
	struct evkeyvalq *headers;
	struct evkeyval *header;

	switch (evhttp_request_get_command(req)) {
	case EVHTTP_REQ_GET: cmdtype = "GET"; break;
	case EVHTTP_REQ_POST: cmdtype = "POST"; break;
	case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
	case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
	case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
	case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
	case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
	case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
	case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
	default: cmdtype = "unknown"; break;
	}

	printf("Received a %s request for %s\nHeaders:\n",
		cmdtype, evhttp_request_get_uri(req));

	headers = evhttp_request_get_input_headers(req);
	for (header = headers->tqh_first; header;
		header = header->next.tqe_next) {
			printf("  %s: %s\n", header->key, header->value);
	}

	ConnectionManager *conn = ConnectionManager::getInstance();
	struct evbuffer *return_buffer=evbuffer_new();

	long long total_req = conn->getTotalRequests();
	long long total_res = conn->getTotalResponses();
	unsigned int conns = conn->getConnections();

	long long timeouts = conn->getTimeoutRequests();
	long long err_res = conn->getErrorResponses();
	long long conn_except = conn->getConnExceptions();
	long long ok_res = conn->getOkResponses();

	evbuffer_add_printf(return_buffer,"    total request: %lld<br>	   total response: %lld<br>	   connnections: %u<br><br><hr><br>	ok: %lld	\
		<br>	timeout: %lld<br>	http error: %lld<br>    connExcept: %u<br>"
		, total_req, total_res, conns, ok_res, timeouts, err_res, conn_except);
	evhttp_send_reply(req, HTTP_OK, "OK", return_buffer);
	evbuffer_free(return_buffer);

	return 0;
}
Пример #10
0
static int
ev_hdr_cb(struct evhttp_request *ev_req,
	  void *data)
{
	int ret;
	struct op *op = (struct op *)data;
	struct evkeyvalq *ev_in_hdrs;
	struct evkeyval *ev_hdr;

	ev_in_hdrs = evhttp_request_get_input_headers(ev_req);
	if (ev_in_hdrs == NULL) {
		dbg(0, "header callback with NULL queue\n");
		goto err_disconnect;
	}

	if (op->rsp.num_hdrs > 0) {
		/* headers should only be processed once */
		dbg(0, "unexpected multiple header callbacks!\n");
		goto err_disconnect;
	}

	TAILQ_FOREACH(ev_hdr, ev_in_hdrs, next) {
		dbg(3, "received hdr: %s = %s\n", ev_hdr->key, ev_hdr->value);

		ret = op_rsp_hdr_add(op, ev_hdr->key, ev_hdr->value);
		if (ret < 0) {
			goto err_disconnect;
		}

		if (!strcmp(ev_hdr->key, "Content-Length")) {
			char *eptr;
			uint64_t len;

			errno = 0;
			len = strtoull(ev_hdr->value, &eptr, 10);
			if ((eptr == ev_hdr->value) || (errno != 0)) {
				goto err_disconnect;
			}

			if (op->rsp.write_cbs > 0) {
				dbg(0, "clen header received after data callback!\n");
				goto err_disconnect;
			}
			/* allocate recv buffer in write callback */
			op->rsp.clen_recvd = true;
			op->rsp.clen = len;
		}
	}
Пример #11
0
Файл: http.c Проект: snip/aprsc
static int http_check_req_compressed(struct evhttp_request *r)
{
	struct evkeyvalq *req_headers;
	const char *accept_enc;
	
	req_headers = evhttp_request_get_input_headers(r);
	accept_enc = evhttp_find_header(req_headers, "Accept-Encoding");
	
	if (!accept_enc)
		return 0;
	
	if (strstr(accept_enc, "gzip") != NULL)
		return HTTP_COMPR_GZIP;
	
	return 0;
}
Пример #12
0
static int
request_header_cb(struct evhttp_request *req, void *arg)
{
  struct http_client_ctx *ctx;

  ctx = (struct http_client_ctx *)arg;

  if (!ctx->headers)
    {
      DPRINTF(E_LOG, L_HTTP, "BUG: Header callback invoked but caller did not say where to save the headers\n");
      return -1;
    }

  headers_save(ctx->headers, evhttp_request_get_input_headers(req));

  return -1;
}
Пример #13
0
void httpHandler(evhttp_request *request, void *arg) {
	GithubWebhooks * parent = static_cast<GithubWebhooks*>(arg);
	std::string githubHeader;

	auto *inputHeader = evhttp_request_get_input_headers(request);
	for (auto header = inputHeader->tqh_first; header; header = header->next.tqe_next)
	{
		auto headerName = toLower(std::string(header->key));
		if (headerName == "x-github-event")
			githubHeader = std::string(header->value);
	}

	if (githubHeader.empty())
	{
		auto *output = evhttp_request_get_output_buffer(request);
		evhttp_send_reply(request, HTTP_BADREQUEST, "Not a github webhook", output);
		evbuffer_add_printf(output, "X-GitHub-Event is missing");
		return;
	}

	auto *input = evhttp_request_get_input_buffer(request);
	auto *output = evhttp_request_get_output_buffer(request);
	size_t length = evbuffer_get_length(input);

	std::vector<char> buffer;
	buffer.resize(length);
	evbuffer_remove(input, buffer.data(), length);

	std::string textResponse;
	auto formatStatus = GithubWebhookFormatter::FormatWebhookMessage(githubHeader, buffer, textResponse);

	switch (formatStatus)
	{
	case GithubWebhookFormatter::FormatResult::JSONParseError:
		LOG(ERROR) << "Can't parse json payload";
		evhttp_send_reply(request, HTTP_INTERNAL, "Can't parse json payload", output);
		evbuffer_add_printf(output, "Can't parse json");
		return;

	case GithubWebhookFormatter::FormatResult::OK:
		parent->SendMessage(textResponse);

	case GithubWebhookFormatter::FormatResult::IgnoredHook:
		evhttp_send_reply(request, HTTP_OK, "OK", output);
	}
}
Пример #14
0
/*
 * Get request input headers
 * @return [Hash]
 */
static VALUE t_get_input_headers(VALUE self) {
    Libevent_HttpRequest *http_request;
    struct evkeyvalq *ev_headers;
    struct evkeyval *ev_header;
    VALUE headers;

    Data_Get_Struct(self, Libevent_HttpRequest, http_request);

    headers = rb_hash_new();

    ev_headers = evhttp_request_get_input_headers(http_request->ev_request);

    for ( ev_header = ev_headers->tqh_first; ev_header; ev_header = ev_header->next.tqe_next ) {
        rb_hash_aset(headers, rb_str_new2(ev_header->key), rb_str_new2(ev_header->value));
    }

    return headers;
}
Пример #15
0
/* Callback used for the /dump URI, and for every non-GET request:
 * dumps all information to stdout and gives back a trivial 200 ok */
static void
dump_request_cb(struct evhttp_request *req, void *arg)
{
	const char *cmdtype;
	struct evkeyvalq *headers;
	struct evkeyval *header;
	struct evbuffer *buf;

	switch (evhttp_request_get_command(req)) {
	case EVHTTP_REQ_GET: cmdtype = "GET"; break;
	case EVHTTP_REQ_POST: cmdtype = "POST"; break;
	case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break;
	case EVHTTP_REQ_PUT: cmdtype = "PUT"; break;
	case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break;
	case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break;
	case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break;
	case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break;
	case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break;
	default: cmdtype = "unknown"; break;
	}

	printf("Received a %s request for %s\nHeaders:\n",
	    cmdtype, evhttp_request_get_uri(req));

	headers = evhttp_request_get_input_headers(req);
	for (header = headers->tqh_first; header;
	    header = header->next.tqe_next) {
		printf("  %s: %s\n", header->key, header->value);
	}

	buf = evhttp_request_get_input_buffer(req);
	puts("Input data: <<<");
	while (evbuffer_get_length(buf)) {
		int n;
		char cbuf[128];
		n = evbuffer_remove(buf, cbuf, sizeof(cbuf));
		if (n > 0)
			(void) fwrite(cbuf, 1, n, stdout);
	}
	puts(">>>");

	evhttp_send_reply(req, 200, "OK", NULL);
}
Пример #16
0
void HttpClient_YPL::onRequestDone(struct evhttp_request *req, void *arg)
{
    HttpClient_YPL *self = (HttpClient_YPL *)arg;
    printf("req->response_code = %d \n", req->response_code);
    printf("req->major = %d, req->minor = %d \n", req->major, req->minor);
    printf("req->chunked = %d \n", req->chunked);
    struct evkeyvalq *headers = evhttp_request_get_input_headers(req);
    struct evkeyval *header;
    for (header = headers->tqh_first; header;
        header = header->next.tqe_next) {
        printf("  %s: %s\n", header->key, header->value);
    }


    int length = evbuffer_get_length(req->input_buffer);
    printf("body length = %d \n", length);

    if(!self->m_buffer)
    {
        self->m_buffer = (char *)malloc(length);
        if(!self->m_buffer)
            return;
        self->m_bufferSize = length;
    }
    else
    {
        if(self->m_bufferSize < length)
        {
            self->m_buffer = (char *)realloc(self->m_buffer, length);
            if(!self->m_buffer)
                return;
            self->m_bufferSize = length;
        }
    }


    int realSize = evbuffer_remove(req->input_buffer, self->m_buffer, length);
    printf("body realSize = %d \n", realSize);
    self->m_buffer[realSize] = '\0';
    printf("buffer = %s \n", self->m_buffer);

    event_base_loopbreak(self->m_base);
}
    static Array HHVM_METHOD(EventHttpRequest, getInputHeaders) {
        EventHttpRequestResourceData *event_http_request_resource_data = FETCH_RESOURCE(this_, EventHttpRequestResourceData, s_event_http_request);
        evkeyvalq_t *headers;
        evkeyval_t  *header;

        Array ret = Array::Create();

        if((headers = evhttp_request_get_input_headers((evhttp_request_t *) event_http_request_resource_data->getInternalResourceData())) == NULL){
            return ret;
        }

        header = headers->tqh_first;

        while(header){
            ret.set(String(header->key, CopyString), String(header->value, CopyString));
            header = header->next.tqe_next;
        }
        return ret;
    }
Пример #18
0
static void s3http_connection_on_responce_cb (struct evhttp_request *req, void *ctx)
{
    RequestData *data = (RequestData *) ctx;
    struct evbuffer *inbuf;
    const char *buf = NULL;
    size_t buf_len;

    LOG_debug (CON_LOG, "Got HTTP response from server !");

    if (!req) {
        LOG_err (CON_LOG, "Request failed !");
        if (data->error_cb)
            data->error_cb (data->con, data->ctx);
        goto done;
    }

    // XXX: handle redirect
    // 200 and 204 (No Content) are ok
    if (evhttp_request_get_response_code (req) != 200 && evhttp_request_get_response_code (req) != 204
        && evhttp_request_get_response_code (req) != 307) {
        LOG_err (CON_LOG, "Server returned HTTP error: %d !", evhttp_request_get_response_code (req));
        LOG_debug (CON_LOG, "Error str: %s", req->response_code_line);
        if (data->error_cb)
            data->error_cb (data->con, data->ctx);
        goto done;
    }

    inbuf = evhttp_request_get_input_buffer (req);
    buf_len = evbuffer_get_length (inbuf);
    buf = (const char *) evbuffer_pullup (inbuf, buf_len);
    
    if (data->responce_cb)
        data->responce_cb (data->con, data->ctx, buf, buf_len, evhttp_request_get_input_headers (req));
    else
        LOG_debug (CON_LOG, ">>> NO callback function !");

done:
    g_free (data);
}
Пример #19
0
    Request make_request_from_evhttp_request(evhttp_request* req) {
      Request r;

      switch (evhttp_request_get_command(req)) {
        case EVHTTP_REQ_GET:     r.method = "GET";     break;
        case EVHTTP_REQ_POST:    r.method = "POST";    break;
        case EVHTTP_REQ_HEAD:    r.method = "HEAD";    break;
        case EVHTTP_REQ_PUT:     r.method = "PUT";     break;
        case EVHTTP_REQ_DELETE:  r.method = "DELETE";  break;
        case EVHTTP_REQ_OPTIONS: r.method = "OPTIONS"; break;
        case EVHTTP_REQ_TRACE:   r.method = "TRACE";   break;
        case EVHTTP_REQ_CONNECT: r.method = "CONNECT"; break;
        case EVHTTP_REQ_PATCH:   r.method = "PATCH";   break;
      }

      evkeyvalq* headers = evhttp_request_get_input_headers(req);
      for (evkeyval* header = headers->tqh_first; header; header = header->next.tqe_next) {
        r.headers[header->key] = header->value;
      }

      evbuffer* body = evhttp_request_get_input_buffer(req);
      if (body) {
        std::stringstream body_buffer;
        while (evbuffer_get_length(body)) {
          char tmp[128];
          int n = evbuffer_remove(body, tmp, sizeof(tmp));
          if (n > 0)
            body_buffer.write(tmp, n);
        }
        r.body = body_buffer.str();
      }

      char* decoded_uri_str = evhttp_decode_uri(evhttp_request_get_uri(req));
      r.uri = URI(decoded_uri_str);
      ::free(decoded_uri_str);
      return r;
    }
Пример #20
0
int
httpd_basic_auth(struct evhttp_request *req, char *user, char *passwd, char *realm)
{
  struct evbuffer *evbuf;
  struct evkeyvalq *headers;
  char *header;
  const char *auth;
  char *authuser;
  char *authpwd;
  int len;
  int ret;

  headers = evhttp_request_get_input_headers(req);
  auth = evhttp_find_header(headers, "Authorization");
  if (!auth)
    {
      DPRINTF(E_DBG, L_HTTPD, "No Authorization header\n");

      goto need_auth;
    }

  if (strncmp(auth, "Basic ", strlen("Basic ")) != 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Bad Authentication header\n");

      goto need_auth;
    }

  auth += strlen("Basic ");

  authuser = b64_decode(auth);
  if (!authuser)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not decode Authentication header\n");

      goto need_auth;
    }

  authpwd = strchr(authuser, ':');
  if (!authpwd)
    {
      DPRINTF(E_LOG, L_HTTPD, "Malformed Authentication header\n");

      free(authuser);
      goto need_auth;
    }

  *authpwd = '\0';
  authpwd++;

  if (user)
    {
      if (strcmp(user, authuser) != 0)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Username mismatch\n");

	  free(authuser);
	  goto need_auth;
	}
    }

  if (strcmp(passwd, authpwd) != 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Bad password\n");

      free(authuser);
      goto need_auth;
    }

  free(authuser);

  return 0;

 need_auth:
  len = strlen(realm) + strlen("Basic realm=") + 3;
  header = (char *)malloc(len);
  if (!header)
    {
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
      return -1;
    }

  ret = snprintf(header, len, "Basic realm=\"%s\"", realm);
  if ((ret < 0) || (ret >= len))
    {
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
      return -1;
    }

  evbuf = evbuffer_new();
  if (!evbuf)
    {
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");
      return -1;
    }

  headers = evhttp_request_get_output_headers(req);
  evhttp_add_header(headers, "WWW-Authenticate", header);
  evbuffer_add(evbuf, http_reply_401, strlen(http_reply_401));
  evhttp_send_reply(req, 401, "Unauthorized", evbuf);

  free(header);
  evbuffer_free(evbuf);

  return -1;
}
Пример #21
0
char *
httpd_fixup_uri(struct evhttp_request *req)
{
  struct evkeyvalq *headers;
  const char *ua;
  const char *uri;
  const char *u;
  const char *q;
  char *fixed;
  char *f;
  int len;

  uri = evhttp_request_get_uri(req);
  if (!uri)
    return NULL;

  /* No query string, nothing to do */
  q = strchr(uri, '?');
  if (!q)
    return strdup(uri);

  headers = evhttp_request_get_input_headers(req);
  ua = evhttp_find_header(headers, "User-Agent");
  if (!ua)
    return strdup(uri);

  if ((strncmp(ua, "iTunes", strlen("iTunes")) != 0)
      && (strncmp(ua, "Remote", strlen("Remote")) != 0)
      && (strncmp(ua, "Roku", strlen("Roku")) != 0))
    return strdup(uri);

  /* Reencode + as %2B and space as + in the query,
     which iTunes and Roku devices don't do */
  len = strlen(uri);

  u = q;
  while (*u)
    {
      if (*u == '+')
	len += 2;

      u++;
    }

  fixed = (char *)malloc(len + 1);
  if (!fixed)
    return NULL;

  strncpy(fixed, uri, q - uri);

  f = fixed + (q - uri);
  while (*q)
    {
      switch (*q)
	{
	  case '+':
	    *f = '%';
	    f++;
	    *f = '2';
	    f++;
	    *f = 'B';
	    break;

	  case ' ':
	    *f = '+';
	    break;

	  default:
	    *f = *q;
	    break;
	}

      q++;
      f++;
    }

  *f = '\0';

  return fixed;
}
Пример #22
0
Файл: http.c Проект: snip/aprsc
static void http_route_static(struct evhttp_request *r, const char *uri)
{
	struct http_static_t *cmdp;
	struct stat st;
	char fname[HTTP_FNAME_LEN];
	char last_modified[128];
	char *contenttype;
	int fd;
	int file_size;
	char *buf;
	struct evkeyvalq *req_headers;
	const char *ims;
	
	for (cmdp = http_static_files; cmdp->name != NULL; cmdp++)
		if (strcmp(cmdp->name, uri) == 0)
			break;
			
	if (cmdp->name == NULL) {
		hlog(LOG_DEBUG, "HTTP: 404");
		evhttp_send_error(r, HTTP_NOTFOUND, "Not found");
		return;
	}
	
	snprintf(fname, HTTP_FNAME_LEN, "%s/%s", webdir, cmdp->filename);
	
	//hlog(LOG_DEBUG, "static file request %s", uri);
	
	fd = open(fname, 0, O_RDONLY);
	if (fd < 0) {
		if (errno == ENOENT) {
			/* don't complain about missing motd.html - it's optional. */
			int level = LOG_ERR;
			if (strcmp(cmdp->filename, "motd.html") == 0)
				level = LOG_DEBUG;
			hlog(level, "http static file '%s' not found", fname);
			evhttp_send_error(r, HTTP_NOTFOUND, "Not found");
			return;
		}
		
		hlog(LOG_ERR, "http static file '%s' could not be opened for reading: %s", fname, strerror(errno));
		evhttp_send_error(r, HTTP_INTERNAL, "Could not access file");
		return;
	}
	
	if (fstat(fd, &st) == -1) {
		hlog(LOG_ERR, "http static file '%s' could not fstat() after opening: %s", fname, strerror(errno));
		evhttp_send_error(r, HTTP_INTERNAL, "Could not access file");
		if (close(fd) < 0)
			hlog(LOG_ERR, "http static file '%s' could not be closed after failed stat: %s", fname, strerror(errno));
		return;
	}
	
	http_date(last_modified, sizeof(last_modified), st.st_mtime);
	
	contenttype = http_content_type(cmdp->filename);
	//hlog(LOG_DEBUG, "found content-type %s", contenttype);
	
	struct evkeyvalq *headers = evhttp_request_get_output_headers(r);
	http_header_base(headers, st.st_mtime);
	evhttp_add_header(headers, "Content-Type", contenttype);
	
	/* Consider an IMS hit */
	req_headers = evhttp_request_get_input_headers(r);
	ims = evhttp_find_header(req_headers, "If-Modified-Since");
	
	if ((ims) && strcasecmp(ims, last_modified) == 0) {
		hlog(LOG_DEBUG, "http static file '%s' IMS hit", fname);
		evhttp_send_reply(r, HTTP_NOTMODIFIED, "Not modified", NULL);
		if (close(fd) < 0)
			hlog(LOG_ERR, "http static file '%s' could not be closed after failed stat: %s", fname, strerror(errno));
		return;
	}
	
	file_size = st.st_size;
	
	/* yes, we are not going to serve large files. */
	buf = hmalloc(file_size);
	int n = read(fd, buf, file_size);
	
	if (close(fd) < 0) {
		hlog(LOG_ERR, "http static file '%s' could not be closed after reading: %s", fname, strerror(errno));
		evhttp_send_error(r, HTTP_INTERNAL, "Could not access file");
		hfree(buf);
		return;
	}
	
	if (n != file_size) {
		hlog(LOG_ERR, "http static file '%s' could only read %d of %d bytes", fname, n, file_size);
		evhttp_send_error(r, HTTP_INTERNAL, "Could not access file");
		hfree(buf);
		return;
	}
	
	int allow_compress;
	if (strncmp(contenttype, "image/", 6) == 0)
		allow_compress = 0;
	else
		allow_compress = 1;
	
	http_send_reply_ok(r, headers, buf, n, allow_compress);
	hfree(buf);
}
 ALWAYS_INLINE evkeyvalq_t *get_http_req_headers(evhttp_request_t *request, int64_t type){
     if (type == EVENT_REQ_HEADER_OUTPUT){
         return evhttp_request_get_output_headers(request);
     }
     return evhttp_request_get_input_headers(request);
 }
Пример #24
0
http_delivery_status_t
buffer_delivery(
        struct evhttp_request* req,
        char* decoded_path)
{
    char* my_decoded_path           = NULL;
    char* my_client_ip              = NULL;
    char* my_client_user_agent      = NULL;
    buffer_xact_ctx* p_ctx          = NULL;
    prmm_req prmm_r                 = NULL;
    int content_on_disk             = 0;

    http_delivery_status_t stat;
    stat = http_delivery_internal_error;

    channel_info_t* p_channel;
    p_channel = get_channel(decoded_path);
    if(!p_channel) {
        debug_msg("channel not identified for %s", decoded_path);
        stat = http_delivery_not_found;
        return stat; /*we don't allocate anything, so just return*/
    }

    /*
     * doecode_path points to memory owned by libevent,
     * and will be modified later, so we have keep a copy.
     */
    my_decoded_path = strdup(decoded_path);
    if(!my_decoded_path) {
        debug_msg("strdup");
        goto error;
    }

    char* host;
    uint16_t port;
    evhttp_connection_get_peer(
            evhttp_request_get_connection(req),
            &host,
            &port);
    my_client_ip = strdup(host);
    if(!my_client_ip) {
        debug_msg("strdup");
        goto error;
    }

    struct evkeyvalq* input_headers;
    input_headers = evhttp_request_get_input_headers(req);
    const char* user_agent = evhttp_find_header(input_headers, "User-Agent");
    if(user_agent) {
        my_client_user_agent = strdup(user_agent);
        if(!my_client_user_agent) {
            debug_msg("strdup");
            goto error;
        }
    }

    p_ctx = malloc(sizeof(buffer_xact_ctx));
    if(!p_ctx) {
        debug_msg("malloc");
        goto error;
    }
    p_ctx->client_req           = req;
    p_ctx->data_sent            = 0;
    p_ctx->data_total           = 0;
    p_ctx->decoded_path         = my_decoded_path;
    p_ctx->client_ip            = my_client_ip;
    p_ctx->client_user_agent    = my_client_user_agent;

    prmm_conn prmm_c;
    prmm_c = get_prmm_conn(
            p_channel->channel_id,
            p_channel->maddress,
            p_channel->mport);
    if(!prmm_c) {
        debug_msg("get_prmm_conn");
        goto error;
    }

    prmm_r = prmm_request_new(
            prmm_c,
            decoded_path,
            http_prmm_cb,
            p_ctx);
    if(!prmm_r) {
        debug_msg("prmm_request_new");
        goto error;
    }
    p_ctx->prmm_r = prmm_r;

    prmm_request_stat_t prmm_stat;
    prmm_stat = prmm_request_start(prmm_r);
    switch(prmm_stat) {
        case prmm_request_success:
            break;
        case prmm_request_failed:
            debug_msg("can't get content via prmm");
            stat = http_delivery_not_found;
            goto error;
        case prmm_request_on_disk:
            debug_msg("content has been written to disk just now,");
            debug_msg("so use local delivery instead.");
            content_on_disk = 1;
            goto error; /*this isn't error actually, we just need to free memory*/
        default:
            debug_msg("?! invalid stat: %d", stat);
            goto error;
    }

    /*for memory leak detect when debugging*/
    debug_msg("buffer_xact_ctx[%p] created", p_ctx);

    return http_delivery_success;

error:
    if(my_decoded_path)
        free(my_decoded_path);
    if(my_client_ip)
        free(my_client_ip);
    if(my_client_user_agent)
        free(my_client_user_agent);
    if(p_ctx)
        free(p_ctx);
    if(prmm_r)
        prmm_request_free(prmm_r);

    if(content_on_disk)
        return local_delivery(req, decoded_path);
        
    return stat;
}
Пример #25
0
Файл: http.c Проект: snip/aprsc
static void http_upload_position(struct evhttp_request *r, const char *remote_host)
{
	struct evbuffer *bufin, *bufout;
	struct evkeyvalq *req_headers;
	const char *ctype, *clength;
	int clength_i;
	char post[MAX_HTTP_POST_DATA+1];
	ev_ssize_t l;
	char *login_string = NULL;
	char *packet = NULL;
	char *username = NULL;
	char validated;
	int e;
	int packet_len;
	
	req_headers = evhttp_request_get_input_headers(r);
	ctype = evhttp_find_header(req_headers, "Content-Type");
	
	if (!ctype || strcasecmp(ctype, "application/octet-stream") != 0) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Bad request, wrong or missing content-type");
		return;
	}
	
	clength = evhttp_find_header(req_headers, "Content-Length");
	if (!clength) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Bad request, missing content-length");
		return;
	}
	
	clength_i = atoi(clength);
	if (clength_i > MAX_HTTP_POST_DATA) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Bad request, too large body");
		return;
	}
	
	/* get the HTTP POST body */
	bufin = evhttp_request_get_input_buffer(r);
	l = evbuffer_copyout(bufin, post, MAX_HTTP_POST_DATA);
	
	/* Just for convenience and safety, null-terminate. Easier to log. */
	post[MAX_HTTP_POST_DATA] = 0;
	if (l <= MAX_HTTP_POST_DATA)
		post[l] = 0;
	
	if (l != clength_i) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Body size does not match content-length");
		return;
	}
	
	hlog(LOG_DEBUG, "got post data: %s", post);
	
	packet_len = loginpost_split(post, l, &login_string, &packet);
	if (packet_len == -1) {
		evhttp_send_error(r, HTTP_BADREQUEST, "No newline (LF) found in data");
		return;
	}
	
	if (!login_string) {
		evhttp_send_error(r, HTTP_BADREQUEST, "No login string in data");
		return;
	}
	
	if (!packet) {
		evhttp_send_error(r, HTTP_BADREQUEST, "No packet data found in data");
		return;
	}
	
	hlog(LOG_DEBUG, "login string: %s", login_string);
	hlog(LOG_DEBUG, "packet: %s", packet);
	
	/* process the login string */
	validated = http_udp_upload_login(remote_host, login_string, &username, "HTTP POST");
	if (validated < 0) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Invalid login string");
		return;
	}
	
	if (validated != 1) {
		evhttp_send_error(r, 403, "Invalid passcode");
		return;
	}
	
	/* packet size limits */
	if (packet_len < PACKETLEN_MIN) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Packet too short");
		return;
	}
	
	if (packet_len > PACKETLEN_MAX-2) {
		evhttp_send_error(r, HTTP_BADREQUEST, "Packet too long");
		return;
	}
	
	e = pseudoclient_push_packet(http_worker, http_pseudoclient, username, packet, packet_len);

	if (e < 0) {
		hlog(LOG_DEBUG, "http incoming packet parse failure code %d: %s", e, packet);
		evhttp_send_error(r, HTTP_BADREQUEST, "Packet parsing failure");
		return;
	}
	
	bufout = evbuffer_new();
	evbuffer_add(bufout, "ok\n", 3);
	
	struct evkeyvalq *headers = evhttp_request_get_output_headers(r);
	http_header_base(headers, 0);
	evhttp_add_header(headers, "Content-Type", "text/plain; charset=UTF-8");
	
	evhttp_send_reply(r, HTTP_OK, "OK", bufout);
	evbuffer_free(bufout);
}
Пример #26
0
static void
http_request_done(struct evhttp_request *req, void *ctx) {
    char buffer[256];
    ev_ssize_t nread;
    struct evkeyval *header;


    if (req == NULL) {
        /* If req is NULL, it means an error occurred, but
         * sadly we are mostly left guessing what the error
         * might have been.  We'll do our best... */
        struct bufferevent *bev = (struct bufferevent *) ctx;


        int errcode = EVUTIL_SOCKET_ERROR();
        fprintf(stderr, "some request failed - no idea which one though!\n");
        /* Print out the OpenSSL error queue that libevent
         * squirreled away for us, if any. */

        /* If the OpenSSL error queue was empty, maybe it was a
         * socket error; let's try printing that. */

        fprintf(stderr, "socket error = %s (%d)\n",
                evutil_socket_error_to_string(errcode),
                errcode);
        return;
    }

    /*fprintf(stderr, "Response line: %d %s\n",
            evhttp_request_get_response_code(req),
            evhttp_request_get_response_code_line(req));

    struct evkeyvalq *headers = evhttp_request_get_input_headers(req);
    if (NULL != headers) {
        fprintf(stderr, "Response headers:\n");

        TAILQ_FOREACH(header, headers, next) {
            fprintf(stderr, "%s: %s\r\n",
                    header->key, header->value);
        }

        fprintf(stderr, "\n");
    }*/


    const int http_code = evhttp_request_get_response_code(req);
    struct evhttp_connection *evcon = evhttp_request_get_connection(req);


    if (HTTP_MOVEPERM == http_code || HTTP_MOVETEMP == http_code) {

        const char *location = evhttp_find_header(evhttp_request_get_input_headers(req), "Location");
        if (NULL != location) {
            //fprintf(stderr, "Location: %s\n", location);

            create_request(location);
        }
    }

    if (HTTP_OK == http_code) {

        struct evbuffer *input_buffer = evhttp_request_get_input_buffer(req);

        int found = 0;
        while ((nread = evbuffer_remove(input_buffer, buffer, sizeof (buffer))) > 0) {
            if (0 == search_find(&search_list, buffer, nread)) {
                found = 1;
                break;
            }
        }

        fprintf(stderr, "%s: %d\n", evhttp_find_header(evhttp_request_get_output_headers(req), "Host"), found);


    }


    if (--n_pending_requests == 0)
        event_base_loopexit(base, NULL);
}
Пример #27
0
/* Thread: httpd */
void
httpd_stream_file(struct evhttp_request *req, int id)
{
  struct media_file_info *mfi;
  struct stream_ctx *st;
  void (*stream_cb)(int fd, short event, void *arg);
  struct stat sb;
  struct timeval tv;
  struct evhttp_connection *evcon;
  struct evkeyvalq *input_headers;
  struct evkeyvalq *output_headers;
  const char *param;
  const char *param_end;
  const char *ua;
  const char *client_codecs;
  char buf[64];
  int64_t offset;
  int64_t end_offset;
  off_t pos;
  int transcode;
  int ret;

  offset = 0;
  end_offset = 0;

  input_headers = evhttp_request_get_input_headers(req);

  param = evhttp_find_header(input_headers, "Range");
  if (param)
    {
      DPRINTF(E_DBG, L_HTTPD, "Found Range header: %s\n", param);

      /* Start offset */
      ret = safe_atoi64(param + strlen("bytes="), &offset);
      if (ret < 0)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Invalid start offset, will stream whole file (%s)\n", param);
	  offset = 0;
	}
      /* End offset, if any */
      else
	{
	  param_end = strchr(param, '-');
	  if (param_end && (strlen(param_end) > 1))
	    {
	      ret = safe_atoi64(param_end + 1, &end_offset);
	      if (ret < 0)
		{
		  DPRINTF(E_LOG, L_HTTPD, "Invalid end offset, will stream to end of file (%s)\n", param);
		  end_offset = 0;
		}

	      if (end_offset < offset)
		{
		  DPRINTF(E_LOG, L_HTTPD, "End offset < start offset, will stream to end of file (%" PRIi64 " < %" PRIi64 ")\n", end_offset, offset);
		  end_offset = 0;
		}
	    }
	}
    }

  mfi = db_file_fetch_byid(id);
  if (!mfi)
    {
      DPRINTF(E_LOG, L_HTTPD, "Item %d not found\n", id);

      evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
      return;
    }

  if (mfi->data_kind != DATA_KIND_FILE)
    {
      evhttp_send_error(req, 500, "Cannot stream radio station");

      goto out_free_mfi;
    }

  st = (struct stream_ctx *)malloc(sizeof(struct stream_ctx));
  if (!st)
    {
      DPRINTF(E_LOG, L_HTTPD, "Out of memory for struct stream_ctx\n");

      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

      goto out_free_mfi;
    }
  memset(st, 0, sizeof(struct stream_ctx));
  st->fd = -1;

  ua = evhttp_find_header(input_headers, "User-Agent");
  client_codecs = evhttp_find_header(input_headers, "Accept-Codecs");

  transcode = transcode_needed(ua, client_codecs, mfi->codectype);

  output_headers = evhttp_request_get_output_headers(req);

  if (transcode)
    {
      DPRINTF(E_INFO, L_HTTPD, "Preparing to transcode %s\n", mfi->path);

      stream_cb = stream_chunk_xcode_cb;

      st->xcode = transcode_setup(mfi, XCODE_PCM16_HEADER, &st->size);
      if (!st->xcode)
	{
	  DPRINTF(E_WARN, L_HTTPD, "Transcoding setup failed, aborting streaming\n");

	  evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

	  goto out_free_st;
	}

      if (!evhttp_find_header(output_headers, "Content-Type"))
	evhttp_add_header(output_headers, "Content-Type", "audio/wav");
    }
  else
    {
      /* Stream the raw file */
      DPRINTF(E_INFO, L_HTTPD, "Preparing to stream %s\n", mfi->path);

      st->buf = (uint8_t *)malloc(STREAM_CHUNK_SIZE);
      if (!st->buf)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Out of memory for raw streaming buffer\n");

	  evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

	  goto out_free_st;
	}

      stream_cb = stream_chunk_raw_cb;

      st->fd = open(mfi->path, O_RDONLY);
      if (st->fd < 0)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Could not open %s: %s\n", mfi->path, strerror(errno));

	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

	  goto out_cleanup;
	}

      ret = stat(mfi->path, &sb);
      if (ret < 0)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Could not stat() %s: %s\n", mfi->path, strerror(errno));

	  evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");

	  goto out_cleanup;
	}
      st->size = sb.st_size;

      pos = lseek(st->fd, offset, SEEK_SET);
      if (pos == (off_t) -1)
	{
	  DPRINTF(E_LOG, L_HTTPD, "Could not seek into %s: %s\n", mfi->path, strerror(errno));

	  evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");

	  goto out_cleanup;
	}
      st->offset = offset;
      st->end_offset = end_offset;

      /* Content-Type for video files is different than for audio files
       * and overrides whatever may have been set previously, like
       * application/x-dmap-tagged when we're speaking DAAP.
       */
      if (mfi->has_video)
	{
	  /* Front Row and others expect video/<type> */
	  ret = snprintf(buf, sizeof(buf), "video/%s", mfi->type);
	  if ((ret < 0) || (ret >= sizeof(buf)))
	    DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n");
	  else
	    {
	      evhttp_remove_header(output_headers, "Content-Type");
	      evhttp_add_header(output_headers, "Content-Type", buf);
	    }
	}
      /* If no Content-Type has been set and we're streaming audio, add a proper
       * Content-Type for the file we're streaming. Remember DAAP streams audio
       * with application/x-dmap-tagged as the Content-Type (ugh!).
       */
      else if (!evhttp_find_header(output_headers, "Content-Type") && mfi->type)
	{
	  ret = snprintf(buf, sizeof(buf), "audio/%s", mfi->type);
	  if ((ret < 0) || (ret >= sizeof(buf)))
	    DPRINTF(E_LOG, L_HTTPD, "Content-Type too large for buffer, dropping\n");
	  else
	    evhttp_add_header(output_headers, "Content-Type", buf);
	}
    }

  st->evbuf = evbuffer_new();
  if (!st->evbuf)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not allocate an evbuffer for streaming\n");

      evhttp_clear_headers(output_headers);
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

      goto out_cleanup;
    }

  ret = evbuffer_expand(st->evbuf, STREAM_CHUNK_SIZE);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not expand evbuffer for streaming\n");

      evhttp_clear_headers(output_headers);
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

      goto out_cleanup;
    }

  st->ev = event_new(evbase_httpd, -1, EV_TIMEOUT, stream_cb, st);
  evutil_timerclear(&tv);
  if (!st->ev || (event_add(st->ev, &tv) < 0))
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not add one-shot event for streaming\n");

      evhttp_clear_headers(output_headers);
      evhttp_send_error(req, HTTP_SERVUNAVAIL, "Internal Server Error");

      goto out_cleanup;
    }

  st->id = mfi->id;
  st->start_offset = offset;
  st->stream_size = st->size;
  st->req = req;

  if ((offset == 0) && (end_offset == 0))
    {
      /* If we are not decoding, send the Content-Length. We don't do
       * that if we are decoding because we can only guesstimate the
       * size in this case and the error margin is unknown and variable.
       */
      if (!transcode)
	{
	  ret = snprintf(buf, sizeof(buf), "%" PRIi64, (int64_t)st->size);
	  if ((ret < 0) || (ret >= sizeof(buf)))
	    DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n");
	  else
	    evhttp_add_header(output_headers, "Content-Length", buf);
	}

      evhttp_send_reply_start(req, HTTP_OK, "OK");
    }
  else
    {
      if (offset > 0)
	st->stream_size -= offset;
      if (end_offset > 0)
	st->stream_size -= (st->size - end_offset);

      DPRINTF(E_DBG, L_HTTPD, "Stream request with range %" PRIi64 "-%" PRIi64 "\n", offset, end_offset);

      ret = snprintf(buf, sizeof(buf), "bytes %" PRIi64 "-%" PRIi64 "/%" PRIi64,
		     offset, (end_offset) ? end_offset : (int64_t)st->size, (int64_t)st->size);
      if ((ret < 0) || (ret >= sizeof(buf)))
	DPRINTF(E_LOG, L_HTTPD, "Content-Range too large for buffer, dropping\n");
      else
	evhttp_add_header(output_headers, "Content-Range", buf);

      ret = snprintf(buf, sizeof(buf), "%" PRIi64, ((end_offset) ? end_offset + 1 : (int64_t)st->size) - offset);
      if ((ret < 0) || (ret >= sizeof(buf)))
	DPRINTF(E_LOG, L_HTTPD, "Content-Length too large for buffer, dropping\n");
      else
	evhttp_add_header(output_headers, "Content-Length", buf);

      evhttp_send_reply_start(req, 206, "Partial Content");
    }

#ifdef HAVE_POSIX_FADVISE
  if (!transcode)
    {
      /* Hint the OS */
      posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_WILLNEED);
      posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_SEQUENTIAL);
      posix_fadvise(st->fd, st->start_offset, st->stream_size, POSIX_FADV_NOREUSE);
    }
#endif

  evcon = evhttp_request_get_connection(req);

  evhttp_connection_set_closecb(evcon, stream_fail_cb, st);

  DPRINTF(E_INFO, L_HTTPD, "Kicking off streaming for %s\n", mfi->path);

  free_mfi(mfi, 0);

  return;

 out_cleanup:
  if (st->evbuf)
    evbuffer_free(st->evbuf);
  if (st->xcode)
    transcode_cleanup(st->xcode);
  if (st->buf)
    free(st->buf);
  if (st->fd > 0)
    close(st->fd);
 out_free_st:
  free(st);
 out_free_mfi:
  free_mfi(mfi, 0);
}
Пример #28
0
static void
rsp_reply_playlist(struct evhttp_request *req, char **uri, struct evkeyvalq *query)
{
  struct query_params qp;
  struct db_media_file_info dbmfi;
  struct evkeyvalq *headers;
  const char *param;
  const char *ua;
  const char *client_codecs;
  char **strval;
  mxml_node_t *reply;
  mxml_node_t *status;
  mxml_node_t *items;
  mxml_node_t *item;
  mxml_node_t *node;
  int mode;
  int records;
  int transcode;
  int32_t bitrate;
  int i;
  int ret;

  memset(&qp, 0, sizeof(struct query_params));

  ret = safe_atoi32(uri[2], &qp.id);
  if (ret < 0)
    {
      rsp_send_error(req, "Invalid playlist ID");
      return;
    }

  if (qp.id == 0)
    qp.type = Q_ITEMS;
  else
    qp.type = Q_PLITEMS;

  mode = F_FULL;
  param = evhttp_find_header(query, "type");
  if (param)
    {
      if (strcasecmp(param, "full") == 0)
	mode = F_FULL;
      else if (strcasecmp(param, "browse") == 0)
	mode = F_BROWSE;
      else if (strcasecmp(param, "id") == 0)
	mode = F_ID;
      else if (strcasecmp(param, "detailed") == 0)
	mode = F_DETAILED;
      else
	DPRINTF(E_LOG, L_RSP, "Unknown browse mode %s\n", param);
    }

  ret = get_query_params(req, query, &qp);
  if (ret < 0)
    return;

  ret = db_query_start(&qp);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_RSP, "Could not start query\n");

      rsp_send_error(req, "Could not start query");

      if (qp.filter)
	free(qp.filter);
      return;
    }

  if (qp.offset > qp.results)
    records = 0;
  else if (qp.limit > (qp.results - qp.offset))
    records = qp.results - qp.offset;
  else
    records = qp.limit;

  /* We'd use mxmlNewXML(), but then we can't put any attributes
   * on the root node and we need some.
   */
  reply = mxmlNewElement(MXML_NO_PARENT, RSP_XML_ROOT);

  node = mxmlNewElement(reply, "response");
  status = mxmlNewElement(node, "status");
  items = mxmlNewElement(node, "items");

  /* Status block */
  node = mxmlNewElement(status, "errorcode");
  mxmlNewText(node, 0, "0");

  node = mxmlNewElement(status, "errorstring");
  mxmlNewText(node, 0, "");

  node = mxmlNewElement(status, "records");
  mxmlNewTextf(node, 0, "%d", records);

  node = mxmlNewElement(status, "totalrecords");
  mxmlNewTextf(node, 0, "%d", qp.results);

  /* Items block (all items) */
  while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id))
    {
      headers = evhttp_request_get_input_headers(req);

      ua = evhttp_find_header(headers, "User-Agent");
      client_codecs = evhttp_find_header(headers, "Accept-Codecs");

      transcode = transcode_needed(ua, client_codecs, dbmfi.codectype);

      /* Item block (one item) */
      item = mxmlNewElement(items, "item");

      for (i = 0; rsp_fields[i].field; i++)
	{
	  if (!(rsp_fields[i].flags & mode))
	    continue;

	  strval = (char **) ((char *)&dbmfi + rsp_fields[i].offset);

	  if (!(*strval) || (strlen(*strval) == 0))
	    continue;

	  node = mxmlNewElement(item, rsp_fields[i].field);

	  if (!transcode)
	    mxmlNewText(node, 0, *strval);
	  else
	    {
	      switch (rsp_fields[i].offset)
		{
		  case dbmfi_offsetof(type):
		    mxmlNewText(node, 0, "wav");
		    break;

		  case dbmfi_offsetof(bitrate):
		    bitrate = 0;
		    ret = safe_atoi32(dbmfi.samplerate, &bitrate);
		    if ((ret < 0) || (bitrate == 0))
		      bitrate = 1411;
		    else
		      bitrate = (bitrate * 8) / 250;

		    mxmlNewTextf(node, 0, "%d", bitrate);
		    break;

		  case dbmfi_offsetof(description):
		    mxmlNewText(node, 0, "wav audio file");
		    break;

		  case dbmfi_offsetof(codectype):
		    mxmlNewText(node, 0, "wav");

		    node = mxmlNewElement(item, "original_codec");
		    mxmlNewText(node, 0, *strval);
		    break;

		  default:
		    mxmlNewText(node, 0, *strval);
		    break;
		}
	    }
	}
    }

  if (qp.filter)
    free(qp.filter);

  if (ret < 0)
    {
      DPRINTF(E_LOG, L_RSP, "Error fetching results\n");

      mxmlDelete(reply);
      db_query_end(&qp);
      rsp_send_error(req, "Error fetching query results");
      return;
    }

  /* HACK
   * Add a dummy empty string to the items element if there is no data
   * to return - this prevents mxml from sending out an empty <items/>
   * tag that the SoundBridge does not handle. It's hackish, but it works.
   */
  if (qp.results == 0)
    mxmlNewText(items, 0, "");

  db_query_end(&qp);

  rsp_send_reply(req, reply);
}
Пример #29
0
/* Thread: httpd */
void
httpd_send_reply(struct evhttp_request *req, int code, const char *reason, struct evbuffer *evbuf)
{
  unsigned char outbuf[128 * 1024];
  z_stream strm;
  struct evbuffer *gzbuf;
  struct evkeyvalq *headers;
  const char *param;
  int flush;
  int zret;
  int ret;

  if (!req)
    return;

  if (!evbuf || (evbuffer_get_length(evbuf) == 0))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping body-less reply\n");

      goto no_gzip;
    }

  headers = evhttp_request_get_input_headers(req);

  param = evhttp_find_header(headers, "Accept-Encoding");
  if (!param)
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; no Accept-Encoding header\n");

      goto no_gzip;
    }
  else if (!strstr(param, "gzip") && !strstr(param, "*"))
    {
      DPRINTF(E_DBG, L_HTTPD, "Not gzipping; gzip not in Accept-Encoding (%s)\n", param);

      goto no_gzip;
    }

  gzbuf = evbuffer_new();
  if (!gzbuf)
    {
      DPRINTF(E_LOG, L_HTTPD, "Could not allocate evbuffer for gzipped reply\n");

      goto no_gzip;
    }

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;

  /* Set up a gzip stream (the "+ 16" in 15 + 16), instead of a zlib stream (default) */
  zret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
  if (zret != Z_OK)
    {
      DPRINTF(E_DBG, L_HTTPD, "zlib setup failed: %s\n", zError(zret));

      goto out_fail_init;
    }

  strm.next_in = evbuffer_pullup(evbuf, -1);
  strm.avail_in = evbuffer_get_length(evbuf);

  flush = Z_NO_FLUSH;

  /* 2 iterations: Z_NO_FLUSH until input is consumed, then Z_FINISH */
  for (;;)
    {
      do
	{
	  strm.next_out = outbuf;
	  strm.avail_out = sizeof(outbuf);

	  zret = deflate(&strm, flush);
	  if (zret == Z_STREAM_ERROR)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Could not deflate data: %s\n", strm.msg);

	      goto out_fail_gz;
	    }

	  ret = evbuffer_add(gzbuf, outbuf, sizeof(outbuf) - strm.avail_out);
	  if (ret < 0)
	    {
	      DPRINTF(E_LOG, L_HTTPD, "Out of memory adding gzipped data to evbuffer\n");

	      goto out_fail_gz;
	    }
	}
      while (strm.avail_out == 0);

      if (flush == Z_FINISH)
	break;

      flush = Z_FINISH;
    }

  if (zret != Z_STREAM_END)
    {
      DPRINTF(E_LOG, L_HTTPD, "Compressed data not finalized!\n");

      goto out_fail_gz;
    }

  deflateEnd(&strm);

  headers = evhttp_request_get_output_headers(req);

  evhttp_add_header(headers, "Content-Encoding", "gzip");
  evhttp_send_reply(req, code, reason, gzbuf);

  evbuffer_free(gzbuf);

  /* Drain original buffer, as would be after evhttp_send_reply() */
  evbuffer_drain(evbuf, evbuffer_get_length(evbuf));

  return;

 out_fail_gz:
  deflateEnd(&strm);
 out_fail_init:
  evbuffer_free(gzbuf);
 no_gzip:
  evhttp_send_reply(req, code, reason, evbuf);
}
Пример #30
0
static void static_dump_request_cb(struct evhttp_request *req, void *arg)
{

	const char *cmdtype;
	struct evkeyvalq *headers;
	struct evkeyval *header;
	struct evbuffer *buf;


	switch (evhttp_request_get_command(req)) {
		case EVHTTP_REQ_GET:
			cmdtype = "GET";
		break;
		case EVHTTP_REQ_POST:
			cmdtype = "POST";
		break;
		default:
			cmdtype = "unknown";
		break;
	}
	printf("Received a %s request for %s\nHeaders:\n",
	    cmdtype, evhttp_request_get_uri(req));

	headers = evhttp_request_get_input_headers(req);
	for (header = headers->tqh_first; header;
	    header = header->next.tqe_next) {
		printf("  %s: %s\n", header->key, header->value);
	}

	buf = evhttp_request_get_input_buffer(req);
	puts("Input data: <<<");
	printf("len:%d", evbuffer_get_length(buf));

	/*
	while (evbuffer_get_length(buf)) {
		int n;
		char cbuf[128];
		n = evbuffer_remove(buf, cbuf, sizeof(buf)-1);
		if (n > 0)
			(void) fwrite(cbuf, 1, n, stdout);
	}
	puts(">>>");
	*/

	//get params
	struct evkeyvalq *query_params_ptr = calloc(sizeof(struct evkeyvalq), 1);
	getParams(req, query_params_ptr);
	char *test = NULL;
	test = getParam(query_params_ptr, "test");
	if (test != NULL) {
		fprintf(stderr, "param test: %s", test);
	}
	evhttp_clear_headers(query_params_ptr);
	free(test);


	//post params
	struct evkeyvalq *post_params_ptr = calloc(sizeof(struct evkeyvalq), 1);
	postParams(req, post_params_ptr);
	char *name = NULL;
	name = postParam(post_params_ptr, "name");
	if (name != NULL) {
		fprintf(stderr, "param name: %s", name);
	}

	evhttp_clear_headers(post_params_ptr);
	free(name);

	evhttp_send_reply(req, 200, "OK", NULL);

	//evhttp_request_free(req);
}