Esempio n. 1
0
// NULL=失败
struct http_request *http_request_parse( struct buffer *buf ) {
  struct http_request *request = NEW(struct http_request);
  if (request == NULL) return NULL;
  memset(request, 0, sizeof(request));
  {
    // 请求行处理
    char *line = buffer_readline(buf);
    if (line == NULL) {
      http_request_free(request);
      return NULL; 
    }
    int ret = parse_init_line(request, line);
    free(line);
    line = NULL;
    if(ret != 0) {
      http_request_free(request);
      return NULL;
    }
  }

  request->headers = http_header_new();
  // parse headers
  char *line = buffer_readline(buf) ;
  int ret = 0;
  // 头和Body之间有一个空行
  while(line != NULL && *line != '\0') {
    ret = http_add_header_line(request->headers, line);
    if(ret != 0) break;
    free(line);
    line = buffer_readline(buf);
  }
  if (line) free(line);
  // 忽略body数据,现在还不支持
  return request;
}
Esempio n. 2
0
/* Receives an HTTP request from socket SOCKFD; returns a decoded KVMessage.
 * Returns NULL if there is an error. */
kvrequest_t *kvrequest_recieve(int sockfd) {
  kvrequest_t *kvreq = calloc(1, sizeof(kvrequest_t));
  kvreq->type = EMPTY;

  struct url_params *params = NULL;
  struct http_request *req = http_request_parse(sockfd);
  if (!req) goto error;
  params = url_decode(req->path);
  if (!params) goto error;

  if (!strcmp(req->method, "GET")) {
    if (!params->key) {
      kvreq->type = INDEX;
    } else {
      kvreq->type = GETREQ;
    }
  } else if (!strcmp(req->method, "PUT")) {
    if (!params->key || !params->val) goto error;
    kvreq->type = PUTREQ;
  } else if (!strcmp(req->method, "DELETE")) {
    if (!params->key) goto error;
    kvreq->type = DELREQ;
  } else if (!strcmp(req->method, "POST")) {  /* REGISTER, COMMIT, ABORT */
    if (!params->path) goto error;
    if (!strcmp(params->path, REGISTER_PATH)) {
      if (!params->key || !params->val) goto error;
      kvreq->type = REGISTER;
    } else if (!strcmp(params->path, COMMIT_PATH)) {
      kvreq->type = COMMIT;
    } else if (!strcmp(params->path, ABORT_PATH)) {
      kvreq->type = ABORT;
    }
  }
  if (kvreq->type == EMPTY)
    goto error;
  kvreq->key = params->key;
  kvreq->val = params->val;

  http_request_free(req);
  free(params->path);
  free(params);
  return kvreq;

error:
  http_request_free(req);
  url_params_free(params);
  kvrequest_free(kvreq);
  return NULL;
}
Esempio n. 3
0
static void
http_request_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data)
{
	struct http_request *request = data;

	http_request_free(request);
}
Esempio n. 4
0
/**
 * A HTTP request is finished: invoke its callback and free it.
 */
static void
http_request_done(struct http_request *request, CURLcode result, long status)
{
	/* invoke the handler method */

	if (result == CURLE_WRITE_ERROR &&
	    /* handle the postponed error that was caught in
	       http_request_writefunction() */
	    request->body->len > MAX_RESPONSE_BODY) {
		GError *error =
			g_error_new_literal(curl_quark(), 0,
					    "response body is too large");
		request->handler->error(error, request->handler_ctx);
	} else if (result != CURLE_OK) {
		GError *error = g_error_new(curl_quark(), result,
					    "curl failed: %s",
					    request->error);
		request->handler->error(error, request->handler_ctx);
	} else if (status < 200 || status >= 300) {
		GError *error = g_error_new(curl_quark(), 0,
					    "got HTTP status %ld",
					    status);
		request->handler->error(error, request->handler_ctx);
	} else
		request->handler->response(request->body->len,
					   request->body->str,
					   request->handler_ctx);

	/* remove it from the list and free resources */
	http_client.requests = g_slist_remove(http_client.requests, request);
	http_request_free(request);
}
Esempio n. 5
0
http_request_t * http_request_init(void * handler_data, struct log_context_t * log, header_list_t * const header_list)
{
  http_request_t * const request = malloc(sizeof(http_request_t));

  request->handler_data = handler_data;
  request->data = NULL;
  request->log = log;

  request->params = multimap_init_with_string_keys();

  request->path = NULL;
  request->query_string = NULL;
  request->host = NULL;
  request->method = NULL;
  request->scheme = NULL;
  request->authority = NULL;
  request->headers = header_list;

  if (!http_request_headers_finalize(request)) {
    http_request_free(request);
    return NULL;
  }

  return request;
}
Esempio n. 6
0
wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken)
{
	wStream* s;
	HttpRequest* request;
	char* base64NtlmToken = NULL;

	request = http_request_new();

	if (ntlmToken)
		base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);

	http_request_set_method(request, method);

	request->ContentLength = contentLength;
	http_request_set_uri(request, http->URI);

	if (base64NtlmToken)
	{
		http_request_set_auth_scheme(request, "NTLM");
		http_request_set_auth_param(request, base64NtlmToken);
	}

	s = http_request_write(http, request);
	http_request_free(request);

	free(base64NtlmToken);

	return s;
}
Esempio n. 7
0
http_client_soup_callback(SoupMessage *msg, gpointer data)
#endif
{
	struct http_request *request = data;

	http_client.requests = g_list_remove(http_client.requests, request);

	/* NOTE: does not support redirects */
	if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
#ifdef HAVE_SOUP_24
		request->handler->response(msg->response_body->length,
					   msg->response_body->data,
					   request->handler_ctx);
#else
		request->handler->response(msg->response.length,
					   msg->response.body,
					   request->handler_ctx);
#endif
	} else {
		GError *error = g_error_new(soup_quark(), 0,
					    "got HTTP status %d (%s)",
					    msg->status_code,
					    msg->reason_phrase);
		request->handler->error(error, request->handler_ctx);
	}

	http_request_free(request);
}
Esempio n. 8
0
/**
 * Aborts and frees a running HTTP request and report an error to its
 * callback.
 */
static void http_request_abort(struct http_request *request)
{
	http_client.requests = g_slist_remove(http_client.requests, request);

	request->callback(0, NULL, request->callback_data);
	http_request_free(request);
}
Esempio n. 9
0
/**
 * Aborts and frees a running HTTP request and report an error to its
 * handler.
 */
static void
http_request_abort(struct http_request *request, GError *error)
{
	http_client.requests = g_slist_remove(http_client.requests, request);

	request->handler->error(error, request->handler_ctx);
	http_request_free(request);
}
Esempio n. 10
0
wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
{
	wStream* s;
	HttpRequest* request = NULL;
	SecBuffer* ntlmToken = NULL;
	char* base64NtlmToken = NULL;

	assert(method != NULL);

	request = http_request_new();

	if (!request)
		return NULL;

	http_request_set_method(request, method);
	http_request_set_uri(request, rdg->http->URI);

	if (!request->Method || !request->URI)
		return NULL;

	if (rdg->ntlm)
	{
		ntlmToken = rdg->ntlm->outputBuffer;

		if (ntlmToken)
			base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);

		if (base64NtlmToken)
		{
			http_request_set_auth_scheme(request, "NTLM");
			http_request_set_auth_param(request, base64NtlmToken);

			free(base64NtlmToken);

			if (!request->AuthScheme || !request->AuthParam)
				return NULL;
		}
	}

	if (rdg->state == RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED)
	{
		http_request_set_transfer_encoding(request, "chunked");
	}

	s = http_request_write(rdg->http, request);
	http_request_free(request);

	if (s)
		Stream_SealLength(s);

	return s;
}
Esempio n. 11
0
gboolean handle_read( GIOChannel *sock, GIOCondition cond, http_request *h ) {
    g_debug( "entering handle_read");

    if (http_request_read( h )) {
        if (! http_request_ok(h))
            return TRUE;
        handle_request(h);
    }

    http_request_free( h );
    g_debug( "exiting handle_read" );
    return FALSE;
}
Esempio n. 12
0
static void http_client_loop(struct http_thread_env *hte)
{
	gchar *line = NULL;
	gsize nbyte = 0;
	HttpRequest *req = NULL;
	gint n;

	while ((n = getline(&line, &nbyte, hte->fp)) >= 0) {
		line[n] = '\0';
		if (n && line[n - 1] == '\n') line[--n] = '\0';
		if (n && line[n - 1] == '\r') line[--n] = '\0';

		if (n) mbb_log_lvl(MBB_LOG_HTTP, "recv: %s", line);

		if (req == NULL) {
			if ((req = http_request_new(line)) == NULL) {
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}

			if (! parse_url(req->url, &hte->json, &hte->method)) {
				push_http_error_msg(hte, "invalid url %s", req->url);
				break;
			}
		} else if (n) {
			if (http_request_add_header(req, line) == FALSE) {
				mbb_log_lvl(MBB_LOG_HTTP, "invalid header");
				push_http_msg(hte, MBB_MSG_INVALID_HEADER, line);
				break;
			}
		} else {
			if (req->method == HTTP_METHOD_POST) {
				if (process_http_body(hte, req) == FALSE)
					break;
			}

			process_http(hte, req);
			break;
		}
	}

	if (req != NULL)
		http_request_free(req);

	if (hte->root_tag != NULL) {
		xml_tag_free(hte->root_tag);
		hte->root_tag = NULL;
	}

	g_free(line);
}
Esempio n. 13
0
/**
 * A HTTP request is finished: invoke its callback and free it.
 */
static void http_request_done(struct http_request *request, CURLcode result)
{
	/* invoke the callback function */
	if (result == CURLE_OK)
		request->callback(request->body->len, request->body->str, request->callback_data);
	else {
		mpdcron_log(LOG_WARNING, "curl failed: %s", request->error);
		request->callback(0, NULL, request->callback_data);
	}

	/* remove it from the list and free resources */
	http_client.requests = g_slist_remove(http_client.requests, request);
	http_request_free(request);
}
Esempio n. 14
0
bool http_request_parse(HttpRequest* request, const char* text) {
  // Clear the error buffer. If set during this function, there was an error.
  clear_error_message(request);

  // Clear any existing data and reset the object
  http_request_free(request);

  // Copy the text
  char* textcopy = strdup(text);
  char* textcopy_start = textcopy;

  // Parse the HTTP request line (the first line): HTTP method, URI, version
  char* curline = strsep(&textcopy, "\n");
  http_request_parse_request_line(request, curline);

  // Parse headers
  while(textcopy) {
    // Get next line. Break if "\r\n" is reached (or in our case, "\r\0").
    curline = strsep(&textcopy, "\n");
    if(!curline) {
      set_error_message(request, "Unexpected end of text while parsing HTTP request\n");
      break;
    }
    if(curline[0] == '\r' && curline[1] == '\0') {
      break;
    }

    // Store header key and value
    char* curline_orig = curline;
    if(!http_request_parse_header_line(request, curline)) {
      set_error_message(request, "Error parsing HTTP header line %s", curline_orig);
      continue;
    }
  }

  // Store the remaining text as the body
  if(textcopy && textcopy[0]) {
    const size_t textlen = strlen(textcopy);
    request->body = malloc(textlen + 1);
    memcpy(request->body, textcopy, textlen + 1);
    request->body[textlen] = 0;
  }

  // Clean up our copy of the text
  free(textcopy_start);

  // Return success if there was no error
  return !request->error;
}
Esempio n. 15
0
int main(int argc, char* argv[]){
  size_t reqlen;
  HTTPRequest* req;
  const char* test_req;
  
  req = http_request_new();
  test_req ="GET /index.html HTTP/1.1" CRLF\
            "Content-Length: 1" CRLF\
            "A:       B" CRLF\
            "C:          D" CRLF\
            CRLF\
            "x";

  reqlen =  strlen(test_req) - 1;

  //http_request_parse_feed(req, test_req, strlen(test_req));

  
  for(size_t i = 0;  i < reqlen / 9; i+=9){
    http_request_parse_feed(req,test_req,9);
    test_req+=9;
  }
  http_request_parse_feed(req,test_req,reqlen - reqlen / 9);
  
  /*while(*test_req!='\0'){
    http_request_parse_feed(req,test_req,1);
    ++test_req;
    };*/

  printf("method: %d\n, URI:\"%s\"\n, version: %d\n"\
	 "header1: \"%s\": \"%s\"\n"\
	 "header3: \"%s\": %s\n"\
	 "err : %d\n"\
	 "body: %s\n",
	 req->method,
	 req->URI,
	 req->http_version,
	 req->headers[0].name, req->headers[0].value,
	 req->headers[2].name, req->headers[2].value,
	 req->err,
	 req->body);
  
  http_request_free(req);
  exit(EXIT_SUCCESS);
}
Esempio n. 16
0
wStream* rpc_ntlm_http_request(rdpRpc* rpc, SecBuffer* ntlm_token, int content_length, TSG_CHANNEL channel)
{
	wStream* s;
	HttpContext* http_context;
	HttpRequest* http_request;
	char* base64_ntlm_token = NULL;

	http_request = http_request_new();

	if (ntlm_token)
		base64_ntlm_token = crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer);

	if (channel == TSG_CHANNEL_IN)
	{
		http_context = rpc->NtlmHttpIn->context;
		http_request_set_method(http_request, "RPC_IN_DATA");
	}
	else if (channel == TSG_CHANNEL_OUT)
	{
		http_context = rpc->NtlmHttpOut->context;
		http_request_set_method(http_request, "RPC_OUT_DATA");
	}
	else
	{
		return NULL;
	}

	http_request->ContentLength = content_length;
	http_request_set_uri(http_request, http_context->URI);

	if (base64_ntlm_token)
	{
		http_request_set_auth_scheme(http_request, "NTLM");
		http_request_set_auth_param(http_request, base64_ntlm_token);
	}

	s = http_request_write(http_context, http_request);
	http_request_free(http_request);

	free(base64_ntlm_token);

	return s;
}
Esempio n. 17
0
static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method,
                                       const char* transferEncoding)
{
	wStream* s = NULL;
	HttpRequest* request = NULL;
	assert(method != NULL);
	request = http_request_new();

	if (!request)
		return NULL;

	http_request_set_method(request, method);
	http_request_set_uri(request, rdg->http->URI);

	if (!request->Method || !request->URI)
		goto out;

	if (rdg->ntlm)
	{
		if (!rdg_set_ntlm_auth_header(rdg->ntlm, request))
			goto out;
	}

	if (transferEncoding)
	{
		http_request_set_transfer_encoding(request, transferEncoding);
	}

	s = http_request_write(rdg->http, request);
out:
	http_request_free(request);

	if (s)
		Stream_SealLength(s);

	return s;
}
Esempio n. 18
0
/* Queue: pairing */
static int
pairing_request_cb(struct http_connection *c, struct http_request *req, struct http_response *r, void *arg)
{
  struct remote_info *ri;
  struct evbuffer *body;
  char guid[17];
  const char *reason;
  uint8_t *response;
  size_t bodylen;
  int code;
  int len;
  int i;
  int ret;

  ri = (struct remote_info *)arg;

  code = http_response_get_status(r, &reason);
  if (code != HTTP_OK)
    {
      DPRINTF(E_LOG, L_REMOTE, "Pairing failed with Remote %s/%s, HTTP response code %d (%s)\n", ri->pi.remote_id, ri->pi.name, code, reason);

      goto cleanup;
    }

  body = http_response_get_body(r);
  if (!body || (EVBUFFER_LENGTH(body) < 8))
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response too short\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  bodylen = EVBUFFER_LENGTH(body);
  response = EVBUFFER_DATA(body);

  if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'a'))
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: unknown pairing response, expected cmpa\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  len = (response[4] << 24) | (response[5] << 16) | (response[6] << 8) | (response[7]);
  if (bodylen < 8 + len)
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: pairing response truncated (got %d expected %d)\n",
	      ri->pi.remote_id, ri->pi.name, (int)bodylen, len + 8);

      goto cleanup;
    }

  response += 8;

  for (; len > 0; len--, response++)
    {
      if ((response[0] != 'c') || (response[1] != 'm') || (response[2] != 'p') || (response[3] != 'g'))
	continue;
      else
	{
	  len -= 8;
	  response += 8;

	  break;
	}
    }

  if (len < 8)
    {
      DPRINTF(E_LOG, L_REMOTE, "Remote %s/%s: cmpg truncated in pairing response\n", ri->pi.remote_id, ri->pi.name);

      goto cleanup;
    }

  for (i = 0; i < 8; i++)
    sprintf(guid + (2 * i), "%02X", response[i]);

  ri->pi.guid = strdup(guid);

  DPRINTF(E_INFO, L_REMOTE, "Pairing succeeded with Remote '%s' (id %s), GUID: %s\n", ri->pi.name, ri->pi.remote_id, guid);

  ret = db_pool_get();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_REMOTE, "Could not acquire database connection; cannot register pairing with %s\n", ri->pi.name);

      goto cleanup;
    }

  ret = db_pairing_add(&ri->pi);
  db_pool_release();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_REMOTE, "Failed to register pairing!\n");

      goto cleanup;
    }

 cleanup:
  http_request_free(req);
  http_client_free(c);

  return 0;
}
Esempio n. 19
0
int http_parse_request_line(const char *line, struct http_request *request)
{
    const char *p, *q;
    struct uri *uri;
    char *uri_s;

    http_request_init(request);

    p = line;
    while (*p == ' ')
        p++;

    /* Method (CONNECT, GET, etc.). */
    q = p;
    while (is_token_char(*q))
        q++;
    if (p == q)
        goto badreq;
    request->method = mkstr(p, q);

    /* URI. */
    p = q;
    while (*p == ' ')
        p++;
    q = p;
    while (*q != '\0' && *q != ' ')
        q++;
    if (p == q)
        goto badreq;
    uri_s = mkstr(p, q);

    /* RFC 2616, section 5.1.1: The method is case-sensitive.
       RFC 2616, section 5.1.2:
         Request-URI    = "*" | absoluteURI | abs_path | authority
       The absoluteURI form is REQUIRED when the request is being made to a
       proxy... The authority form is only used by the CONNECT method. */
    if (strcmp(request->method, "CONNECT") == 0) {
        uri = uri_parse_authority(&request->uri, uri_s);
    } else {
        uri = uri_parse(&request->uri, uri_s);
    }
    free(uri_s);
    if (uri == NULL)
        /* The URI parsing failed. */
        goto badreq;

    /* Version number. */
    p = q;
    while (*p == ' ')
        p++;
    if (*p == '\0') {
        /* No HTTP/X.X version number indicates version 0.9. */
        request->version = HTTP_09;
    } else {
        q = parse_http_version(p, &request->version);
        if (p == q)
            goto badreq;
    }

    return 0;

badreq:
    http_request_free(request);
    return 400;
}
Esempio n. 20
0
int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    log_init("client.log", 1);

    char buffer[2049];
    int buflen;
    char url[256], host[256], res[256];
    printf("URL to access: ");
    gets(url);
    if(strncmp(url, "http://", 7)) {
        printf("error: url should started with http://\n");
        return -1;
    }

    int i, len = strlen(url), hostlen = 0;
    for(i = 7; i < len; i++, hostlen++) {
        if(url[i] == ':') {
            strncpy(host, url + 7, hostlen);
            portno = atoi(url + i + 1);
            while(i < len && url[i] != '/') i++;
            if(i >= len) strcpy(res, "/");
            else strcpy(res, url + i);
            break;
        } else if(url[i] == '/') {
            strncpy(host, url + 7, hostlen);
            portno = 80;
            strcpy(res, url + i);
            break;
        }
    }
    if(i >= len) {
        printf("error: malformed url");
        return 0;
    }

    printf("connecting to host %s at port %d with url %s\n", host, portno, res);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        perror("error while opening socket: ");
    server = gethostbyname(host);
    if (server == NULL) {
        perror("host not found: ");
        return 0;
    }
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
        perror("error while connecting: ");
        return 0;
    }

    http_request_t req;
    http_response_t resp;
    http_request_init(&req);
    http_response_init(&resp);
    req.type = HTTP_GET;
    strcpy(req.url, res);
    req.version = HTTP_VERSION_1_1;
    sprintf(host, "%s:%d", host, portno);
    dict_put(req.fields, "Host", host);
    if(0 > http_assemble_request(&req, sockfd)) {
        perror("error while writing: ");
        return 0;
    }

    buflen = 0;
    do {
        n = read(sockfd, buffer + buflen, 2048 - buflen);
        if(n > 0)
            buflen += n;
    } while(n > 0 && buflen < 2048);

    puts("===raw resp===");
    for(i = 0; i < buflen; i++) {
        putchar(buffer[i]);
    }
    puts("\n===end===\n");

    if(http_parse_response(&resp, buffer, buflen)) {
        printf("error while parsing response\n");
        return 0;
    }
    printf("%s\n", resp.document);
    http_request_free(&req);
    http_response_free(&resp);
    close(sockfd);
    log_close();
    return 0;
}
Esempio n. 21
0
void http_client_request(const char *url, const char *post_data,
		http_client_callback_t *callback, void *data)
{
	struct http_request *request = g_new(struct http_request, 1);
	CURLcode code;
	CURLMcode mcode;
	bool success;

	request->callback = callback;
	request->callback_data = data;

	/* create a CURL request */

	request->curl = curl_easy_init();
	if (request->curl == NULL) {
		g_free(request);
		callback(0, NULL, data);
		return;
	}

	mcode = curl_multi_add_handle(http_client.multi, request->curl);
	if (mcode != CURLM_OK) {
		curl_easy_cleanup(request->curl);
		g_free(request);
		callback(0, NULL, data);
		return;
	}

	/* .. and set it up */
	curl_easy_setopt(request->curl, CURLOPT_USERAGENT, "mpdcron/" VERSION);
	curl_easy_setopt(request->curl, CURLOPT_WRITEFUNCTION, http_request_writefunction);
	curl_easy_setopt(request->curl, CURLOPT_WRITEDATA, request);
	curl_easy_setopt(request->curl, CURLOPT_FAILONERROR, true);
	curl_easy_setopt(request->curl, CURLOPT_ERRORBUFFER, request->error);
	curl_easy_setopt(request->curl, CURLOPT_BUFFERSIZE, 2048);

	if (file_config.proxy != NULL)
		curl_easy_setopt(request->curl, CURLOPT_PROXY, file_config.proxy);

	request->post_data = g_strdup(post_data);
	if (request->post_data != NULL) {
		curl_easy_setopt(request->curl, CURLOPT_POST, true);
		curl_easy_setopt(request->curl, CURLOPT_POSTFIELDS, request->post_data);
	}

	code = curl_easy_setopt(request->curl, CURLOPT_URL, url);
	if (code != CURLE_OK) {
		curl_multi_remove_handle(http_client.multi, request->curl);
		curl_easy_cleanup(request->curl);
		g_free(request);
		callback(0, NULL, data);
		return;
	}

	request->body = g_string_sized_new(256);

	http_client.requests = g_slist_prepend(http_client.requests, request);

	/* initiate the transfer */

	success = http_multi_perform();
	if (!success) {
		http_client.requests = g_slist_remove(http_client.requests, request);
		http_request_free(request);
		callback(0, NULL, data);
		return;
	}

	http_multi_info_read();
}
static void http_server_handler(int c)
{
    int code;
    struct socket_buffer sock;
    struct http_request request;
    char *buf;

    socket_buffer_init(&sock, c);
#if HAVE_OPENSSL
    if (o.ssl) {
        sock.fdn.ssl = new_ssl(sock.fdn.fd);
        if (SSL_accept(sock.fdn.ssl) != 1) {
            loguser("Failed SSL connection: %s\n",
                ERR_error_string(ERR_get_error(), NULL));
            fdinfo_close(&sock.fdn);
            return;
        }
    }
#endif

    code = http_read_request_line(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Request-Line: %s", buf);
    code = http_parse_request_line(buf, &request);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing Request-Line.\n");
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    if (!method_is_known(request.method)) {
        if (o.debug > 1)
            logdebug("Bad method: %s.\n", request.method);
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(405));
        fdinfo_close(&sock.fdn);
        return;
    }

    code = http_read_header(&sock, &buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error reading header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }
    if (o.debug > 1)
        logdebug("Header:\n%s", buf);
    code = http_request_parse_header(&request, buf);
    free(buf);
    if (code != 0) {
        if (o.verbose)
            logdebug("Error parsing header.\n");
        http_request_free(&request);
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    /* Check authentication. */
    if (o.proxy_auth) {
        struct http_credentials credentials;
        int ret, stale;

        if (http_header_get_proxy_credentials(request.header, &credentials) == NULL) {
            /* No credentials or a parsing error. */
            send_proxy_authenticate(&sock.fdn, 0);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }

        ret = check_auth(&request, &credentials, &stale);
        http_credentials_free(&credentials);
        if (!ret) {
            /* Password doesn't match. */
            /* RFC 2617, section 1.2: "If a proxy does not accept the
               credentials sent with a request, it SHOULD return a 407 (Proxy
               Authentication Required). */
            send_proxy_authenticate(&sock.fdn, stale);
            http_request_free(&request);
            fdinfo_close(&sock.fdn);
            return;
        }
    }

    if (strcmp(request.method, "CONNECT") == 0) {
        code = handle_connect(&sock, &request);
    } else if (strcmp(request.method, "GET") == 0
        || strcmp(request.method, "HEAD") == 0
        || strcmp(request.method, "POST") == 0) {
        code = handle_method(&sock, &request);
    } else {
        code = 500;
    }
    http_request_free(&request);

    if (code != 0) {
        send_string(&sock.fdn, http_code2str(code));
        fdinfo_close(&sock.fdn);
        return;
    }

    fdinfo_close(&sock.fdn);
}
Esempio n. 23
0
void
http_client_request(const char *url, const char *post_data,
		    const struct http_client_handler *handler, void *ctx)
{
	struct http_request *request = g_new(struct http_request, 1);
	CURLcode code;
	CURLMcode mcode;
	bool success;

	request->handler = handler;
	request->handler_ctx = ctx;

	/* create a CURL request */

	request->curl = curl_easy_init();
	if (request->curl == NULL) {
		g_free(request);

		GError *error = g_error_new_literal(curl_quark(), 0,
						    "curl_easy_init() failed");
		handler->error(error, ctx);
		return;
	}

	mcode = curl_multi_add_handle(http_client.multi, request->curl);
	if (mcode != CURLM_OK) {
		curl_easy_cleanup(request->curl);
		g_free(request);

		GError *error = g_error_new_literal(curl_quark(), 0,
						    "curl_multi_add_handle() failed");
		handler->error(error, ctx);
		return;
	}

	/* .. and set it up */

	curl_easy_setopt(request->curl, CURLOPT_USERAGENT,
			 "mpdscribble/" VERSION);
	curl_easy_setopt(request->curl, CURLOPT_WRITEFUNCTION,
			 http_request_writefunction);
	curl_easy_setopt(request->curl, CURLOPT_WRITEDATA, request);
	curl_easy_setopt(request->curl, CURLOPT_FAILONERROR, true);
	curl_easy_setopt(request->curl, CURLOPT_ERRORBUFFER, request->error);
	curl_easy_setopt(request->curl, CURLOPT_BUFFERSIZE, 2048);

	if (file_config.proxy != NULL)
		curl_easy_setopt(request->curl, CURLOPT_PROXY, file_config.proxy);

	request->post_data = g_strdup(post_data);
	if (request->post_data != NULL) {
		curl_easy_setopt(request->curl, CURLOPT_POST, true);
		curl_easy_setopt(request->curl, CURLOPT_POSTFIELDS,
				 request->post_data);
	}

	code = curl_easy_setopt(request->curl, CURLOPT_URL, url);
	if (code != CURLE_OK) {
		curl_multi_remove_handle(http_client.multi, request->curl);
		curl_easy_cleanup(request->curl);
		g_free(request);

		GError *error = g_error_new_literal(curl_quark(), code,
						    "curl_easy_setopt() failed");
		handler->error(error, ctx);
		return;
	}

	request->body = g_string_sized_new(256);

	http_client.requests = g_slist_prepend(http_client.requests, request);

	/* initiate the transfer */

	success = http_multi_perform();
	if (!success) {
		http_client.requests = g_slist_remove(http_client.requests,
						      request);
		http_request_free(request);

		GError *error = g_error_new_literal(curl_quark(), code,
						    "http_multi_perform() failed");
		handler->error(error, ctx);
		return;
	}

	if (!http_client.locked)
		http_multi_info_read();
}
Esempio n. 24
0
/* Queue: pairing */
static int
send_pairing_request(struct remote_info *ri, char *req_uri, int family)
{
  struct http_connection *c;
  struct http_request *req;
  char *address;
  unsigned short port;
  int ret;

  switch (family)
    {
      case AF_INET:
	if (!ri->v4_address)
	  return -1;

	address = ri->v4_address;
	port = ri->v4_port;
	break;

      case AF_INET6:
	if (!ri->v6_address)
	  return -1;

	address = ri->v6_address;
	port = ri->v6_port;
	break;

      default:
	return -1;
    }

  c = http_client_new(L_REMOTE, address, port, pairing_fail_cb, pairing_free_cb, ri);
  if (!c)
    {
      DPRINTF(E_LOG, L_REMOTE, "Could not create HTTP client for pairing with %s\n", ri->pi.name);

      return -1;
    }

  req = http_client_request_new(HTTP_GET, P_VER_1_1, req_uri, pairing_request_cb);
  if (!req)
    {
      DPRINTF(E_WARN, L_REMOTE, "Could not create HTTP request for pairing\n");

      goto request_fail;
    }

  ret = http_request_add_header(req, "Connection", "close");
  if (ret < 0)
    DPRINTF(E_WARN, L_REMOTE, "Could not add Connection: close header\n");

  ret = http_client_request_run(c, req);
  if (ret < 0)
    {
      DPRINTF(E_WARN, L_REMOTE, "Could not run pairing request\n");

      goto run_fail;
    }

  return 0;

 run_fail:
  http_request_free(req);
 request_fail:
  http_client_free(c);

  return -1;
}