// 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; }
/* 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; }
static void http_request_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) { struct http_request *request = data; http_request_free(request); }
/** * 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); }
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; }
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; }
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); }
/** * 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); }
/** * 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); }
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; }
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; }
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); }
/** * 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); }
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; }
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); }
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; }
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; }
/* 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; }
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; }
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; }
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); }
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(); }
/* 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; }