VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/http.cpp@ 43682

Last change on this file since 43682 was 43679, checked in by vboxsync, 12 years ago

iprt/http: introduced RTHttpSetProxy()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1
2/* $Id: http.cpp 43679 2012-10-18 12:26:04Z vboxsync $ */
3/** @file
4 * IPRT - HTTP communication API.
5 */
6
7/*
8 * Copyright (C) 2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * The contents of this file may alternatively be used under the terms
19 * of the Common Development and Distribution License Version 1.0
20 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
21 * VirtualBox OSE distribution, in which case the provisions of the
22 * CDDL are applicable instead of those of the GPL.
23 *
24 * You may elect to license modified versions of this file under the
25 * terms and conditions of either the GPL or the CDDL or both.
26 */
27
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32#include <iprt/http.h>
33#include <iprt/assert.h>
34#include <iprt/err.h>
35#include <iprt/mem.h>
36#include <iprt/string.h>
37
38#include <curl/curl.h>
39#include "internal/magics.h"
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45typedef struct RTHTTPINTERNAL
46{
47 uint32_t u32Magic;
48 CURL *pCurl;
49 long lLastResp;
50} RTHTTPINTERNAL;
51typedef RTHTTPINTERNAL *PRTHTTPINTERNAL;
52
53typedef struct RTHTTPMEMCHUNK
54{
55 char *pszMem;
56 size_t cb;
57} RTHTTPMEMCHUNK;
58typedef RTHTTPMEMCHUNK *PRTHTTPMEMCHUNK;
59
60/*******************************************************************************
61* Defined Constants And Macros *
62*******************************************************************************/
63#define CURL_FAILED(rcCurl) (RT_UNLIKELY(rcCurl != CURLE_OK))
64
65/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
66#define RTHTTP_VALID_RETURN_RC(hHttp, rcCurl) \
67 do { \
68 AssertPtrReturn((hHttp), (rcCurl)); \
69 AssertReturn((hHttp)->u32Magic == RTHTTP_MAGIC, (rcCurl)); \
70 } while (0)
71
72/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
73#define RTHTTP_VALID_RETURN(hHTTP) RTHTTP_VALID_RETURN_RC((hHttp), VERR_INVALID_HANDLE)
74
75/** Validates a handle and returns (void) if not valid. */
76#define RTHTTP_VALID_RETURN_VOID(hHttp) \
77 do { \
78 AssertPtrReturnVoid(hHttp); \
79 AssertReturnVoid((hHttp)->u32Magic == RTHTTP_MAGIC); \
80 } while (0)
81
82
83RTR3DECL(int) RTHttpCreate(PRTHTTP phHttp)
84{
85 AssertPtrReturn(phHttp, VERR_INVALID_PARAMETER);
86
87 CURLcode rcCurl = curl_global_init(CURL_GLOBAL_ALL);
88 if (CURL_FAILED(rcCurl))
89 return VERR_INTERNAL_ERROR;
90
91 CURL* pCurl = curl_easy_init();
92 if (!pCurl)
93 return VERR_INTERNAL_ERROR;
94
95 PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)RTMemAllocZ(sizeof(RTHTTPINTERNAL));
96 if (!pHttpInt)
97 return VERR_NO_MEMORY;
98
99 pHttpInt->u32Magic = RTHTTP_MAGIC;
100 pHttpInt->pCurl = pCurl;
101
102 *phHttp = (RTHTTP)pHttpInt;
103
104 return VINF_SUCCESS;
105}
106
107RTR3DECL(void) RTHttpDestroy(RTHTTP hHttp)
108{
109 if (!hHttp)
110 return;
111
112 PRTHTTPINTERNAL pHttpInt = hHttp;
113 RTHTTP_VALID_RETURN_VOID(pHttpInt);
114
115 pHttpInt->u32Magic = RTHTTP_MAGIC_DEAD;
116
117 curl_easy_cleanup(pHttpInt->pCurl);
118
119 RTMemFree(pHttpInt);
120
121 curl_global_cleanup();
122}
123
124static size_t rtHttpWriteData(void *pvBuf, size_t cb, size_t n, void *pvUser)
125{
126 PRTHTTPMEMCHUNK pMem = (PRTHTTPMEMCHUNK)pvUser;
127 size_t cbAll = cb * n;
128
129 pMem->pszMem = (char*)RTMemRealloc(pMem->pszMem, pMem->cb + cbAll + 1);
130 if (pMem->pszMem)
131 {
132 memcpy(&pMem->pszMem[pMem->cb], pvBuf, cbAll);
133 pMem->cb += cbAll;
134 pMem->pszMem[pMem->cb] = '\0';
135 }
136 return cbAll;
137}
138
139RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pcszProxy, uint32_t uPort,
140 const char *pcszProxyUser, const char *pcszProxyPwd)
141{
142 PRTHTTPINTERNAL pHttpInt = hHttp;
143 RTHTTP_VALID_RETURN(pHttpInt);
144 AssertPtrReturn(pcszProxy, VERR_INVALID_PARAMETER);
145
146 int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXY, pcszProxy);
147 if (CURL_FAILED(rcCurl))
148 return VERR_INVALID_PARAMETER;
149
150 if (uPort != 0)
151 {
152 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPORT, (long)uPort);
153 if (CURL_FAILED(rcCurl))
154 return VERR_INVALID_PARAMETER;
155 }
156
157 if (pcszProxyUser && pcszProxyPwd)
158 {
159 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYUSERNAME, pcszProxyUser);
160 if (CURL_FAILED(rcCurl))
161 return VERR_INVALID_PARAMETER;
162
163 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROXYPASSWORD, pcszProxyPwd);
164 if (CURL_FAILED(rcCurl))
165 return VERR_INVALID_PARAMETER;
166 }
167
168 return VINF_SUCCESS;
169}
170
171RTR3DECL(int) RTHttpGet(RTHTTP hHttp, const char *pcszUrl, char **ppszResponse)
172{
173 PRTHTTPINTERNAL pHttpInt = hHttp;
174 RTHTTP_VALID_RETURN(pHttpInt);
175
176 int rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_URL, pcszUrl);
177 if (CURL_FAILED(rcCurl))
178 return VERR_INVALID_PARAMETER;
179
180 /* XXX */
181 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt");
182 if (CURL_FAILED(rcCurl))
183 return VERR_INTERNAL_ERROR;
184
185 RTHTTPMEMCHUNK chunk = { NULL, 0 };
186 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData);
187 if (CURL_FAILED(rcCurl))
188 return VERR_INTERNAL_ERROR;
189 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void*)&chunk);
190 if (CURL_FAILED(rcCurl))
191 return VERR_INTERNAL_ERROR;
192
193 rcCurl = curl_easy_perform(pHttpInt->pCurl);
194 int rc = VERR_INTERNAL_ERROR;
195 if (rcCurl == CURLE_OK)
196 {
197 curl_easy_getinfo(pHttpInt->pCurl, CURLINFO_RESPONSE_CODE, &pHttpInt->lLastResp);
198 switch (pHttpInt->lLastResp)
199 {
200 case 200:
201 /* OK, request was fulfilled */
202 case 204:
203 /* empty response */
204 rc = VINF_SUCCESS;
205 break;
206 case 400:
207 /* bad request */
208 rc = VERR_HTTP_BAD_REQUEST;
209 break;
210 case 403:
211 /* forbidden, authorization will not help */
212 rc = VERR_HTTP_ACCESS_DENIED;
213 break;
214 case 404:
215 /* URL not found */
216 rc = VERR_HTTP_NOT_FOUND;
217 break;
218 }
219 }
220 else
221 {
222 switch (rcCurl)
223 {
224 case CURLE_URL_MALFORMAT:
225 case CURLE_COULDNT_RESOLVE_HOST:
226 rc = VERR_HTTP_NOT_FOUND;
227 break;
228 default:
229 break;
230 }
231 }
232
233 *ppszResponse = chunk.pszMem;
234
235 return rc;
236}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette