Merge pull request #61 from FedericoStazi:curl

PiperOrigin-RevId: 334994112
Change-Id: Iedd065f33cdb5ebda796722d0a4d158ba719ff2c
This commit is contained in:
Copybara-Service 2020-10-02 03:15:25 -07:00
commit 47ba5c8e39
15 changed files with 396 additions and 343 deletions

6
.gitmodules vendored
View File

@ -7,9 +7,9 @@
[submodule "oss-internship-2020/pffft/master"] [submodule "oss-internship-2020/pffft/master"]
path = oss-internship-2020/pffft/master path = oss-internship-2020/pffft/master
url = https://bitbucket.org/jpommier/pffft/src/master/ url = https://bitbucket.org/jpommier/pffft/src/master/
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
path = oss-internship-2020/curl/curl_wrapper/curl
url = https://github.com/curl/curl
[submodule "oss-internship-2020/gdal/gdal"] [submodule "oss-internship-2020/gdal/gdal"]
path = oss-internship-2020/gdal/gdal path = oss-internship-2020/gdal/gdal
url = https://github.com/OSGeo/gdal/tree/master/gdal url = https://github.com/OSGeo/gdal/tree/master/gdal
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
path = oss-internship-2020/curl/curl_wrapper/curl
url = git@github.com:curl/curl.git

View File

@ -12,15 +12,15 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.12)
project(libcurl_sandbox) project(libcurl_sandbox)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
option(CURL_SAPI_ENABLE_EXAMPLES "" ON) option(SAPI_CURL_ENABLE_EXAMPLES "" ON)
option(CURL_SAPI_ENABLE_TESTS "" ON) option(SAPI_CURL_ENABLE_TESTS "" ON)
# Add callbacks used by examples and tests # Add callbacks used by examples and tests
if (CURL_SAPI_ENABLE_EXAMPLES OR CURL_SAPI_ENABLE_TESTS) if (CURL_SAPI_ENABLE_EXAMPLES OR CURL_SAPI_ENABLE_TESTS)
@ -35,8 +35,8 @@ add_subdirectory(curl_wrapper)
# Setup Sandboxed API # Setup Sandboxed API
set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree") set(SAPI_ROOT "" CACHE PATH "Path to the Sandboxed API source tree")
set(SAPI_ENABLE_EXAMPLES ${CURL_SAPI_ENABLE_EXAMPLES} CACHE BOOL "" FORCE) set(SAPI_ENABLE_EXAMPLES ${SAPI_CURL_ENABLE_EXAMPLES} CACHE BOOL "" FORCE)
set(SAPI_ENABLE_TESTS ${CURL_SAPI_ENABLE_TESTS} CACHE BOOL "" FORCE) set(SAPI_ENABLE_TESTS ${SAPI_CURL_ENABLE_TESTS} CACHE BOOL "" FORCE)
add_subdirectory( add_subdirectory(
"${SAPI_ROOT}" "${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build" "${CMAKE_BINARY_DIR}/sandboxed-api-build"
@ -125,7 +125,7 @@ add_sapi_library(curl_sapi
LIBRARY_NAME Curl LIBRARY_NAME Curl
NAMESPACE "" NAMESPACE curl
) )
# Include generated SAPI header # Include generated SAPI header
@ -134,11 +134,11 @@ target_include_directories(curl_sapi INTERFACE
) )
# Add examples # Add examples
if (CURL_SAPI_ENABLE_EXAMPLES) if (SAPI_CURL_ENABLE_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()
# Add tests # Add tests
if (CURL_SAPI_ENABLE_TESTS) if (SAPI_CURL_ENABLE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()

View File

@ -38,12 +38,15 @@ Variadic methods are currently not supported by Sandboxed API. To solve this,
these methods are defined with an additional explicit parameter in these methods are defined with an additional explicit parameter in
`custom_curl.h`. `custom_curl.h`.
The methods are: - `curl_easy_setopt`. Use `curl_easy_setopt_ptr`, The methods are:
`curl_easy_setopt_long` or `curl_easy_setopt_curl_off_t` instead. -
`curl_easy_getinfo`. Use `curl_easy_getinfo_ptr` instead. - `curl_multi_setopt`. - `curl_easy_setopt`. Use `curl_easy_setopt_ptr`, `curl_easy_setopt_long` or
Use `curl_multi_setopt_ptr`, `curl_multi_setopt_long` or `curl_easy_setopt_curl_off_t` instead.
`curl_multi_setopt_curl_off_t` instead. - `curl_share_setopt`. Use - `curl_easy_getinfo`. Use `curl_easy_getinfo_ptr` instead.
`curl_share_setopt_ptr` or `curl_share_setopt_long` instead - `curl_multi_setopt`. Use `curl_multi_setopt_ptr`, `curl_multi_setopt_long`
or `curl_multi_setopt_curl_off_t` instead.
- `curl_share_setopt`. Use `curl_share_setopt_ptr` or `curl_share_setopt_long`
instead
#### Methods with incomplete array arguments #### Methods with incomplete array arguments
@ -51,8 +54,10 @@ Incomplete array arguments are currently not supported by Sandboxed API. To
solve this, methods taking an incomplete array argument have a wrapper in solve this, methods taking an incomplete array argument have a wrapper in
`custom_curl.h`, and take a pointer as the argument. `custom_curl.h`, and take a pointer as the argument.
The methods are: - `curl_multi_poll`. Use `curl_multi_poll_sapi` instead. - The methods are:
`curl_multi_wait`. Use `curl_multi_wait_sapi` instead.
- `curl_multi_poll`. Use `curl_multi_poll_sapi` instead.
- `curl_multi_wait`. Use `curl_multi_wait_sapi` instead.
#### Methods with conflicts on the generated header #### Methods with conflicts on the generated header
@ -60,11 +65,15 @@ Some methods create conflicts on the generated header because of redefined
`#define` directives from files included by the header. To solve this, the `#define` directives from files included by the header. To solve this, the
conflicting types and methods are redefined in `custom_curl.h`. conflicting types and methods are redefined in `custom_curl.h`.
The types are: - `time_t`. Use `time_t_sapi` instead. - `fd_set`. Use The types are:
`fd_set_sapi` instead.
The methods are: - `curl_getdate`. Use `curl_getdate_sapi` instead. - - `time_t`. Use `time_t_sapi` instead.
`curl_multi_fdset`. Use `curl_multi_fdset_sapi` instead. - `fd_set`. Use `fd_set_sapi` instead.
The methods are:
- `curl_getdate`. Use `curl_getdate_sapi` instead.
- `curl_multi_fdset`. Use `curl_multi_fdset_sapi` instead.
#### Function pointers #### Function pointers

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef TESTS_CALLBACKS_H #ifndef CALLBACKS_H_
#define TESTS_CALLBACKS_H #define CALLBACKS_H_
#include <curl/curl.h> #include <curl/curl.h>
@ -21,4 +21,4 @@
extern "C" size_t WriteToMemory(char* contents, size_t size, size_t num_bytes, extern "C" size_t WriteToMemory(char* contents, size_t size, size_t num_bytes,
void* userp); void* userp);
#endif // TESTS_CALLBACKS_H #endif // CALLBACKS_H_

View File

@ -14,8 +14,8 @@
// Wrapper for curl library // Wrapper for curl library
#ifndef CURL_WRAPPER_H #ifndef CURL_WRAPPER_H_
#define CURL_WRAPPER_H #define CURL_WRAPPER_H_
#include <curl/curl.h> #include <curl/curl.h>
@ -77,6 +77,7 @@ CURLSHcode curl_share_setopt_ptr(CURLSH* handle, CURLSHoption option,
// The wrapper method is needed to make the variadic argument explicit // The wrapper method is needed to make the variadic argument explicit
CURLSHcode curl_share_setopt_long(CURLSH* handle, CURLSHoption option, CURLSHcode curl_share_setopt_long(CURLSH* handle, CURLSHoption option,
long parameter); long parameter);
}
#endif // CURL_WRAPPER_H } // extern "C"
#endif // CURL_WRAPPER_H_

View File

@ -19,59 +19,67 @@
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
namespace {
absl::Status Example1() {
// Initialize sandbox2 and sapi
curl::CurlSapiSandbox sandbox;
SAPI_RETURN_IF_ERROR(sandbox.Init());
curl::CurlApi api(&sandbox);
// Initialize the curl session
curl::CURL* curl_handle;
SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
sapi::v::RemotePtr curl(curl_handle);
if (!curl_handle) {
return absl::UnavailableError("curl_easy_init failed: curl is NULL");
}
int curl_code;
// Specify URL to get
sapi::v::ConstCStr url("http://example.com");
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL,
url.PtrBefore()));
if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
}
// Set the library to follow a redirection
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_long(
&curl, curl::CURLOPT_FOLLOWLOCATION, 1l));
if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
}
// Disable authentication of peer certificate
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_long(
&curl, curl::CURLOPT_SSL_VERIFYPEER, 0l));
if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
}
// Perform the request
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (curl_code != 0) {
return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
}
// Cleanup curl
SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&curl));
return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
absl::Status status; if (absl::Status status = Example1(); !status.ok()) {
LOG(ERROR) << "Example1 failed: " << status.ToString();
// Initialize sandbox2 and sapi return EXIT_FAILURE;
CurlSapiSandbox sandbox;
status = sandbox.Init();
if (!status.ok()) {
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
CurlApi api(&sandbox);
// Initialize the curl session
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init();
if (!curl_handle.ok()) {
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status();
}
sapi::v::RemotePtr curl(curl_handle.value());
if (!curl.GetValue()) LOG(FATAL) << "curl_easy_init failed: curl is NULL";
absl::StatusOr<int> curl_code;
// Specify URL to get
sapi::v::ConstCStr url("http://example.com");
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore());
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status();
}
// Set the library to follow a redirection
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_FOLLOWLOCATION, 1l);
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status();
}
// Disable authentication of peer certificate
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 0l);
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status();
}
// Perform the request
curl_code = api.curl_easy_perform(&curl);
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status();
}
// Cleanup curl
status = api.curl_easy_cleanup(&curl);
if (!status.ok()) {
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -20,87 +20,89 @@
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
int main(int argc, char* argv[]) { namespace {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
absl::Status status;
absl::Status Example2() {
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
CurlSapiSandbox sandbox; curl::CurlSapiSandbox sandbox;
status = sandbox.Init(); SAPI_RETURN_IF_ERROR(sandbox.Init());
if (!status.ok()) { curl::CurlApi api(&sandbox);
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
CurlApi api(&sandbox);
// Generate pointer to WriteMemoryCallback function // Generate pointer to WriteMemoryCallback function
void* function_ptr; void* function_ptr;
status = sandbox.rpc_channel()->Symbol("WriteToMemory", &function_ptr); SAPI_RETURN_IF_ERROR(
if (!status.ok()) { sandbox.rpc_channel()->Symbol("WriteToMemory", &function_ptr));
LOG(FATAL) << "sapi::Sandbox::rpc_channel().Symbol failed: " << status; sapi::v::RemotePtr write_to_memory(function_ptr);
}
sapi::v::RemotePtr remote_function_ptr(function_ptr);
// Initialize the curl session // Initialize the curl session
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init(); curl::CURL* curl_handle;
if (!curl_handle.ok()) { SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status(); sapi::v::RemotePtr curl(curl_handle);
} if (!curl_handle) {
sapi::v::RemotePtr curl(curl_handle.value()); return absl::UnavailableError("curl_easy_init failed: curl is NULL");
if (!curl.GetValue()) {
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
} }
absl::StatusOr<int> curl_code; int curl_code;
// Specify URL to get // Specify URL to get
sapi::v::ConstCStr url("http://example.com"); sapi::v::ConstCStr url("http://example.com");
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore()); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { url.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set WriteMemoryCallback as the write function // Set WriteMemoryCallback as the write function
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEFUNCTION, SAPI_ASSIGN_OR_RETURN(curl_code,
&remote_function_ptr); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEFUNCTION,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { &write_to_memory));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Pass 'chunk' struct to the callback function // Pass 'chunk' struct to the callback function
sapi::v::LenVal chunk(0); sapi::v::LenVal chunk(0);
curl_code = SAPI_ASSIGN_OR_RETURN(curl_code,
api.curl_easy_setopt_ptr(&curl, CURLOPT_WRITEDATA, chunk.PtrBoth()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_WRITEDATA,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { chunk.PtrBoth()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set a user agent // Set a user agent
sapi::v::ConstCStr user_agent("libcurl-agent/1.0"); sapi::v::ConstCStr user_agent("libcurl-agent/1.0");
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_USERAGENT, SAPI_ASSIGN_OR_RETURN(curl_code,
user_agent.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_USERAGENT,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { user_agent.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Perform the request // Perform the request
curl_code = api.curl_easy_perform(&curl); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status(); return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
} }
// Retrieve memory size // Retrieve memory size
status = sandbox.TransferFromSandboxee(&chunk); SAPI_RETURN_IF_ERROR(sandbox.TransferFromSandboxee(&chunk));
if (!status.ok()) {
LOG(FATAL) << "sandbox.TransferFromSandboxee failed: " << status;
}
std::cout << "memory size: " << chunk.GetDataSize() << " bytes" << std::endl; std::cout << "memory size: " << chunk.GetDataSize() << " bytes" << std::endl;
// Cleanup curl // Cleanup curl
status = api.curl_easy_cleanup(&curl); SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&curl));
if (!status.ok()) {
LOG(FATAL) << "curl_easy_cleanup failed: " << status; return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
if (absl::Status status = Example2(); !status.ok()) {
LOG(ERROR) << "Example2 failed: " << status.ToString();
return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -19,7 +19,9 @@
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
class CurlSapiSandboxEx3 : public CurlSapiSandbox { namespace {
class CurlSapiSandboxEx3 : public curl::CurlSapiSandbox {
public: public:
CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key, CurlSapiSandboxEx3(std::string ssl_certificate, std::string ssl_key,
std::string ca_certificates) std::string ca_certificates)
@ -42,7 +44,7 @@ class CurlSapiSandboxEx3 : public CurlSapiSandbox {
.AddFile(ssl_key) .AddFile(ssl_key)
.AddFile(ca_certificates); .AddFile(ca_certificates);
// Provide the new PolicyBuilder to ModifyPolicy in CurlSandbox // Provide the new PolicyBuilder to ModifyPolicy in CurlSandbox
return CurlSapiSandbox::ModifyPolicy(policy_builder.get()); return curl::CurlSapiSandbox::ModifyPolicy(policy_builder.get());
} }
std::string ssl_certificate; std::string ssl_certificate;
@ -50,116 +52,121 @@ class CurlSapiSandboxEx3 : public CurlSapiSandbox {
std::string ca_certificates; std::string ca_certificates;
}; };
int main(int argc, char* argv[]) { absl::Status Example3(std::string ssl_certificate, std::string ssl_key,
gflags::ParseCommandLineFlags(&argc, &argv, true); std::string ssl_key_password,
google::InitGoogleLogging(argv[0]); std::string ca_certificates) {
absl::Status status;
// Get input parameters (should be absolute paths)
if (argc != 5) {
LOG(FATAL) << "wrong number of arguments (4 expected)";
}
std::string ssl_certificate = argv[1];
std::string ssl_key = argv[2];
std::string ssl_key_password = argv[3];
std::string ca_certificates = argv[4];
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates); CurlSapiSandboxEx3 sandbox(ssl_certificate, ssl_key, ca_certificates);
status = sandbox.Init(); SAPI_RETURN_IF_ERROR(sandbox.Init());
if (!status.ok()) { curl::CurlApi api(&sandbox);
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
CurlApi api(&sandbox);
absl::StatusOr<int> curl_code; int curl_code;
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
curl_code = api.curl_global_init(3l); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_global_init failed: " << curl_code.status(); return absl::UnavailableError("curl_global_init failed: " + curl_code);
} }
// Initialize curl easy handle // Initialize curl easy handle
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init(); curl::CURL* curl_handle;
if (!curl_handle.ok()) { SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status(); sapi::v::RemotePtr curl(curl_handle);
} if (!curl_handle) {
sapi::v::RemotePtr curl(curl_handle.value()); return absl::UnavailableError("curl_easy_init failed: curl is NULL");
if (!curl.GetValue()) {
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
} }
// Specify URL to get (using HTTPS) // Specify URL to get (using HTTPS)
sapi::v::ConstCStr url("https://example.com"); sapi::v::ConstCStr url("https://example.com");
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore()); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { url.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set the SSL certificate type to "PEM" // Set the SSL certificate type to "PEM"
sapi::v::ConstCStr ssl_cert_type("PEM"); sapi::v::ConstCStr ssl_cert_type("PEM");
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERTTYPE, SAPI_ASSIGN_OR_RETURN(curl_code,
ssl_cert_type.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERTTYPE,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { ssl_cert_type.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set the certificate for client authentication // Set the certificate for client authentication
sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str()); sapi::v::ConstCStr sapi_ssl_certificate(ssl_certificate.c_str());
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLCERT, SAPI_ASSIGN_OR_RETURN(curl_code,
sapi_ssl_certificate.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLCERT,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { sapi_ssl_certificate.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set the private key for client authentication // Set the private key for client authentication
sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str()); sapi::v::ConstCStr sapi_ssl_key(ssl_key.c_str());
curl_code = SAPI_ASSIGN_OR_RETURN(curl_code,
api.curl_easy_setopt_ptr(&curl, CURLOPT_SSLKEY, sapi_ssl_key.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_SSLKEY,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { sapi_ssl_key.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set the password used to protect the private key // Set the password used to protect the private key
sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str()); sapi::v::ConstCStr sapi_ssl_key_password(ssl_key_password.c_str());
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_KEYPASSWD, SAPI_ASSIGN_OR_RETURN(curl_code,
sapi_ssl_key_password.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_KEYPASSWD,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { sapi_ssl_key_password.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Set the file with the certificates vaildating the server // Set the file with the certificates vaildating the server
sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str()); sapi::v::ConstCStr sapi_ca_certificates(ca_certificates.c_str());
curl_code = api.curl_easy_setopt_ptr(&curl, CURLOPT_CAINFO, SAPI_ASSIGN_OR_RETURN(curl_code,
sapi_ca_certificates.PtrBefore()); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_CAINFO,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { sapi_ca_certificates.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Verify the authenticity of the server // Verify the authenticity of the server
curl_code = api.curl_easy_setopt_long(&curl, CURLOPT_SSL_VERIFYPEER, 1L); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_long(
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { &curl, curl::CURLOPT_SSL_VERIFYPEER, 1L));
LOG(FATAL) << "curl_easy_setopt_long failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_long failed: " + curl_code);
} }
// Perform the request // Perform the request
curl_code = api.curl_easy_perform(&curl); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status(); return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
} }
// Cleanup curl easy handle // Cleanup curl easy handle
status = api.curl_easy_cleanup(&curl); SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&curl));
if (!status.ok()) {
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
}
// Cleanup curl // Cleanup curl
status = api.curl_global_cleanup(); SAPI_RETURN_IF_ERROR(api.curl_global_cleanup());
if (!status.ok()) {
LOG(FATAL) << "curl_global_cleanup failed: " << status; return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
// Get input parameters (should be absolute paths)
if (argc != 5) {
LOG(ERROR) << "wrong number of arguments (4 expected)";
return EXIT_FAILURE;
}
if (absl::Status status = Example3(argv[1], argv[2], argv[3], argv[4]);
!status.ok()) {
LOG(ERROR) << "Example3 failed: " << status.ToString();
return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -21,107 +21,113 @@
#include "curl_sapi.sapi.h" // NOLINT(build/include) #include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
int main(int argc, char* argv[]) { namespace {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
absl::Status status;
absl::Status Example4() {
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
CurlSapiSandbox sandbox; curl::CurlSapiSandbox sandbox;
status = sandbox.Init(); SAPI_RETURN_IF_ERROR(sandbox.Init());
if (!status.ok()) { curl::CurlApi api(&sandbox);
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
CurlApi api(&sandbox);
// Number of running handles // Number of running handles
sapi::v::Int still_running(1); sapi::v::Int still_running(1);
absl::StatusOr<int> curl_code; int curl_code;
// Initialize curl (CURL_GLOBAL_DEFAULT = 3) // Initialize curl (CURL_GLOBAL_DEFAULT = 3)
curl_code = api.curl_global_init(3l); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_global_init failed: " << curl_code.status(); return absl::UnavailableError("curl_global_init failed: " + curl_code);
} }
// Initialize http_handle // Initialize http_handle
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init(); curl::CURL* curl_handle;
if (!curl_handle.ok()) { SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status(); sapi::v::RemotePtr http_handle(curl_handle);
} if (!curl_handle) {
sapi::v::RemotePtr http_handle(curl_handle.value()); return absl::UnavailableError("curl_easy_init failed: curl is NULL");
if (!http_handle.GetValue()) {
LOG(FATAL) << "curl_easy_init failed: http_handle is NULL";
} }
// Specify URL to get // Specify URL to get
sapi::v::ConstCStr url("http://example.com"); sapi::v::ConstCStr url("http://example.com");
curl_code = SAPI_ASSIGN_OR_RETURN(curl_code,
api.curl_easy_setopt_ptr(&http_handle, CURLOPT_URL, url.PtrBefore()); api.curl_easy_setopt_ptr(&http_handle, curl::CURLOPT_URL,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { url.PtrBefore()));
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Initialize multi_handle // Initialize multi_handle
absl::StatusOr<CURLM*> curlm_handle = api.curl_multi_init(); curl::CURLM* curlm_handle;
if (!curlm_handle.ok()) { SAPI_ASSIGN_OR_RETURN(curlm_handle, api.curl_multi_init());
LOG(FATAL) << "curl_multi_init failed: " << curlm_handle.status(); sapi::v::RemotePtr multi_handle(curlm_handle);
} if (!curlm_handle) {
sapi::v::RemotePtr multi_handle(curlm_handle.value()); return absl::UnavailableError(
if (!multi_handle.GetValue()) { "curl_multi_init failed: multi_handle is NULL");
LOG(FATAL) << "curl_multi_init failed: multi_handle is NULL";
} }
// Add http_handle to the multi stack // Add http_handle to the multi stack
curl_code = api.curl_multi_add_handle(&multi_handle, &http_handle); SAPI_ASSIGN_OR_RETURN(curl_code,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { api.curl_multi_add_handle(&multi_handle, &http_handle));
LOG(FATAL) << "curl_multi_add_handle failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_multi_add_handle failed: " + curl_code);
} }
while (still_running.GetValue()) { while (still_running.GetValue()) {
sapi::v::Int numfds(0); sapi::v::Int numfds(0);
// Perform the request // Perform the request
curl_code = api.curl_multi_perform(&multi_handle, still_running.PtrBoth()); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_perform(
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { &multi_handle, still_running.PtrBoth()));
LOG(FATAL) << "curl_mutli_perform failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_mutli_perform failed: " + curl_code);
} }
if (still_running.GetValue()) { if (still_running.GetValue()) {
// Wait for an event or timeout // Wait for an event or timeout
sapi::v::NullPtr null_ptr; sapi::v::NullPtr null_ptr;
curl_code = api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000, SAPI_ASSIGN_OR_RETURN(
numfds.PtrBoth()); curl_code, api.curl_multi_poll_sapi(&multi_handle, &null_ptr, 0, 1000,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { numfds.PtrBoth()));
LOG(FATAL) << "curl_multi_poll_sapi failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_multi_poll_sapi failed: " +
curl_code);
} }
} }
} }
// Remove http_handle from the multi stack // Remove http_handle from the multi stack
curl_code = api.curl_multi_remove_handle(&multi_handle, &http_handle); SAPI_ASSIGN_OR_RETURN(curl_code,
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { api.curl_multi_remove_handle(&multi_handle, &http_handle));
LOG(FATAL) << "curl_multi_remove_handle failed: " << curl_code.status(); if (curl_code != 0) {
return absl::UnavailableError("curl_multi_remove_handle failed: " +
curl_code);
} }
// Cleanup http_handle // Cleanup http_handle
status = api.curl_easy_cleanup(&http_handle); SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&http_handle));
if (!status.ok()) {
LOG(FATAL) << "curl_easy_cleanup failed: " << status;
}
// Cleanup multi_handle // Cleanup multi_handle
curl_code = api.curl_multi_cleanup(&multi_handle); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_multi_cleanup(&multi_handle));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_multi_cleanup failed: " << curl_code.status(); return absl::UnavailableError("curl_multi_cleanup failed: " + curl_code);
} }
// Cleanup curl // Cleanup curl
status = api.curl_global_cleanup(); SAPI_RETURN_IF_ERROR(api.curl_global_cleanup());
if (!status.ok()) {
LOG(FATAL) << "curl_global_cleanup failed: " << status; return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
if (absl::Status status = Example4(); !status.ok()) {
LOG(ERROR) << "Example4 failed: " << status.ToString();
return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -15,87 +15,90 @@
// Sandboxed version of multithread.c // Sandboxed version of multithread.c
// Multithreaded HTTP GET requests // Multithreaded HTTP GET requests
#include <pthread.h>
#include <cstdlib> #include <cstdlib>
#include <future> // NOLINT(build/c++11)
#include <thread> // NOLINT(build/c++11)
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
void pull_one_url(const std::string& url, CurlApi& api) { namespace {
absl::Status pull_one_url(const std::string& url, curl::CurlApi& api) {
// Initialize the curl session // Initialize the curl session
absl::StatusOr<CURL*> curl_handle = api.curl_easy_init(); curl::CURL* curl_handle;
if (!curl_handle.ok()) { SAPI_ASSIGN_OR_RETURN(curl_handle, api.curl_easy_init());
LOG(FATAL) << "curl_easy_init failed: " << curl_handle.status(); sapi::v::RemotePtr curl(curl_handle);
} if (!curl_handle) {
sapi::v::RemotePtr curl(curl_handle.value()); return absl::UnavailableError("curl_easy_init failed: curl is NULL");
if (!curl.GetValue()) {
LOG(FATAL) << "curl_easy_init failed: curl is NULL";
} }
absl::StatusOr<int> curl_code; int curl_code;
// Specify URL to get // Specify URL to get
sapi::v::ConstCStr sapi_url(url.c_str()); sapi::v::ConstCStr sapi_url(url.c_str());
curl_code = SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL,
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, sapi_url.PtrBefore()); sapi_url.PtrBefore()));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_easy_setopt_ptr failed: " << curl_code.status(); return absl::UnavailableError("curl_easy_setopt_ptr failed: " + curl_code);
} }
// Perform the request // Perform the request
curl_code = api.curl_easy_perform(&curl); SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_easy_perform(&curl));
if (!curl_code.ok() || curl_code.value() != CURLE_OK) { if (curl_code != 0) {
LOG(FATAL) << "curl_easy_perform failed: " << curl_code.status(); return absl::UnavailableError("curl_easy_perform failed: " + curl_code);
} }
// Cleanup curl // Cleanup curl easy handle
absl::Status status = api.curl_easy_cleanup(&curl); SAPI_RETURN_IF_ERROR(api.curl_easy_cleanup(&curl));
if (!status.ok()) {
LOG(FATAL) << "curl_easy_cleanup failed: " << status; return absl::OkStatus();
}
} }
const std::vector<std::string> urls = { const std::vector<std::string> urls = {
"http://example.com", "http://example.edu", "http://example.net", "http://example.com", "http://example.edu", "http://example.net",
"http://example.org"}; "http://example.org"};
absl::Status Example5() {
// Initialize sandbox2 and sapi
curl::CurlSapiSandbox sandbox;
SAPI_RETURN_IF_ERROR(sandbox.Init());
curl::CurlApi api(&sandbox);
int curl_code;
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
SAPI_ASSIGN_OR_RETURN(curl_code, api.curl_global_init(3l));
if (curl_code != 0) {
return absl::UnavailableError("curl_global_init failed: " + curl_code);
}
// Create the threads (by using futures)
std::vector<std::future<absl::Status>> futures;
for (auto& url : urls) {
futures.emplace_back(
std::async(pull_one_url, std::ref(url), std::ref(api)));
}
// Join the threads and check for errors
for (auto& future : futures) {
SAPI_RETURN_IF_ERROR(future.get());
}
// Cleanup curl
SAPI_RETURN_IF_ERROR(api.curl_global_cleanup());
return absl::OkStatus();
}
} // namespace
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true); gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
absl::Status status; if (absl::Status status = Example5(); !status.ok()) {
LOG(ERROR) << "Example5 failed: " << status.ToString();
// Initialize sandbox2 and sapi return EXIT_FAILURE;
CurlSapiSandbox sandbox;
status = sandbox.Init();
if (!status.ok()) {
LOG(FATAL) << "Couldn't initialize Sandboxed API: " << status;
}
CurlApi api(&sandbox);
absl::StatusOr<int> curl_code;
// Initialize curl (CURL_GLOBAL_DEFAULT = 3)
curl_code = api.curl_global_init(3l);
if (!curl_code.ok() || curl_code.value() != CURLE_OK) {
LOG(FATAL) << "curl_global_init failed: " << curl_code.status();
}
// Create the threads
std::vector<std::thread> threads;
for (auto& url : urls) {
threads.emplace_back(pull_one_url, std::ref(url), std::ref(api));
}
// Join the threads
for (auto& thread : threads) {
thread.join();
}
// Cleanup curl
status = api.curl_global_cleanup();
if (!status.ok()) {
LOG(FATAL) << "curl_global_cleanup failed: " << status;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -20,6 +20,8 @@
#include "../sandbox.h" // NOLINT(build/include) #include "../sandbox.h" // NOLINT(build/include)
#include "sandboxed_api/transaction.h" #include "sandboxed_api/transaction.h"
namespace {
class CurlTransaction : public sapi::Transaction { class CurlTransaction : public sapi::Transaction {
public: public:
explicit CurlTransaction(std::unique_ptr<sapi::Sandbox> sandbox) explicit CurlTransaction(std::unique_ptr<sapi::Sandbox> sandbox)
@ -36,7 +38,7 @@ class CurlTransaction : public sapi::Transaction {
}; };
absl::Status CurlTransaction::Main() { absl::Status CurlTransaction::Main() {
CurlApi api(sandbox()); curl::CurlApi api(sandbox());
// Initialize the curl session // Initialize the curl session
SAPI_ASSIGN_OR_RETURN(void* curl_remote, api.curl_easy_init()); SAPI_ASSIGN_OR_RETURN(void* curl_remote, api.curl_easy_init());
@ -47,13 +49,13 @@ absl::Status CurlTransaction::Main() {
sapi::v::ConstCStr url("http://example.com"); sapi::v::ConstCStr url("http://example.com");
SAPI_ASSIGN_OR_RETURN( SAPI_ASSIGN_OR_RETURN(
int setopt_url_code, int setopt_url_code,
api.curl_easy_setopt_ptr(&curl, CURLOPT_URL, url.PtrBefore())); api.curl_easy_setopt_ptr(&curl, curl::CURLOPT_URL, url.PtrBefore()));
TRANSACTION_FAIL_IF_NOT(setopt_url_code == CURLE_OK, TRANSACTION_FAIL_IF_NOT(setopt_url_code == curl::CURLE_OK,
"curl_easy_setopt_ptr failed"); "curl_easy_setopt_ptr failed");
// Perform the request // Perform the request
SAPI_ASSIGN_OR_RETURN(int perform_code, api.curl_easy_perform(&curl)); SAPI_ASSIGN_OR_RETURN(int perform_code, api.curl_easy_perform(&curl));
TRANSACTION_FAIL_IF_NOT(setopt_url_code == CURLE_OK, TRANSACTION_FAIL_IF_NOT(setopt_url_code == curl::CURLE_OK,
"curl_easy_perform failed"); "curl_easy_perform failed");
// Cleanup curl // Cleanup curl
@ -63,8 +65,10 @@ absl::Status CurlTransaction::Main() {
return absl::OkStatus(); return absl::OkStatus();
} }
} // namespace
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
CurlTransaction curl{std::make_unique<CurlSapiSandbox>()}; CurlTransaction curl{std::make_unique<curl::CurlSapiSandbox>()};
absl::Status status = curl.Run(); absl::Status status = curl.Run();
CHECK(status.ok()) << "CurlTransaction failed"; CHECK(status.ok()) << "CurlTransaction failed";

View File

@ -24,7 +24,9 @@
#include "curl_sapi.sapi.h" // NOLINT(build/include) #include "curl_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/sandbox2/util/bpf_helper.h" #include "sandboxed_api/sandbox2/util/bpf_helper.h"
class CurlSapiSandbox : public CurlSandbox { namespace curl {
class CurlSapiSandbox : public curl::CurlSandbox {
protected: protected:
std::unique_ptr<sandbox2::Policy> ModifyPolicy( std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder* policy_builder) override { sandbox2::PolicyBuilder* policy_builder) override {
@ -64,4 +66,6 @@ class CurlSapiSandbox : public CurlSandbox {
} }
}; };
} // namespace curl
#endif // SANDBOX_H_ #endif // SANDBOX_H_

View File

@ -28,17 +28,17 @@
int CurlTestUtils::port_; int CurlTestUtils::port_;
std::thread CurlTestUtils::server_thread_; std::thread CurlTestUtils::server_thread_;
absl::Status CurlTestUtils::CurlTestSetUp() { absl::Status curl::tests::CurlTestUtils::CurlTestSetUp() {
// Initialize sandbox2 and sapi // Initialize sandbox2 and sapi
sandbox_ = std::make_unique<CurlSapiSandbox>(); sandbox_ = std::make_unique<curl::CurlSapiSandbox>();
absl::Status init = sandbox_->Init(); absl::Status init = sandbox_->Init();
if (!init.ok()) { if (!init.ok()) {
return init; return init;
} }
api_ = std::make_unique<CurlApi>(sandbox_.get()); api_ = std::make_unique<curl::CurlApi>(sandbox_.get());
// Initialize curl // Initialize curl
absl::StatusOr<CURL*> curl_handle = api_->curl_easy_init(); absl::StatusOr<curl::CURL*> curl_handle = api_->curl_easy_init();
if (!curl_handle.ok()) { if (!curl_handle.ok()) {
return curl_handle.status(); return curl_handle.status();
} }
@ -51,23 +51,24 @@ absl::Status CurlTestUtils::CurlTestSetUp() {
// Specify request URL // Specify request URL
sapi::v::ConstCStr sapi_url(kUrl.data()); sapi::v::ConstCStr sapi_url(kUrl.data());
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_URL, curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_URL,
sapi_url.PtrBefore()); sapi_url.PtrBefore());
if (!curl_code.ok()) { if (!curl_code.ok()) {
return curl_code.status(); return curl_code.status();
} }
if (curl_code.value() != CURLE_OK) { if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " + "curl_easy_setopt_ptr returned with the error code " +
curl_code.value()); curl_code.value());
} }
// Set port // Set port
curl_code = api_->curl_easy_setopt_long(curl_.get(), CURLOPT_PORT, port_); curl_code =
api_->curl_easy_setopt_long(curl_.get(), curl::CURLOPT_PORT, port_);
if (!curl_code.ok()) { if (!curl_code.ok()) {
return curl_code.status(); return curl_code.status();
} }
if (curl_code.value() != CURLE_OK) { if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_easy_setopt_long returned with the error code " + "curl_easy_setopt_long returned with the error code " +
curl_code.value()); curl_code.value());
@ -83,12 +84,12 @@ absl::Status CurlTestUtils::CurlTestSetUp() {
sapi::v::RemotePtr remote_function_ptr(function_ptr); sapi::v::RemotePtr remote_function_ptr(function_ptr);
// Set WriteToMemory as the write function // Set WriteToMemory as the write function
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEFUNCTION, curl_code = api_->curl_easy_setopt_ptr(
&remote_function_ptr); curl_.get(), curl::CURLOPT_WRITEFUNCTION, &remote_function_ptr);
if (!curl_code.ok()) { if (!curl_code.ok()) {
return curl_code.status(); return curl_code.status();
} }
if (curl_code.value() != CURLE_OK) { if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " + "curl_easy_setopt_ptr returned with the error code " +
curl_code.value()); curl_code.value());
@ -96,12 +97,12 @@ absl::Status CurlTestUtils::CurlTestSetUp() {
// Pass memory chunk object to the callback // Pass memory chunk object to the callback
chunk_ = std::make_unique<sapi::v::LenVal>(0); chunk_ = std::make_unique<sapi::v::LenVal>(0);
curl_code = api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_WRITEDATA, curl_code = api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_WRITEDATA,
chunk_->PtrBoth()); chunk_->PtrBoth());
if (!curl_code.ok()) { if (!curl_code.ok()) {
return curl_code.status(); return curl_code.status();
} }
if (curl_code.value() != CURLE_OK) { if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_easy_setopt_ptr returned with the error code " + "curl_easy_setopt_ptr returned with the error code " +
curl_code.value()); curl_code.value());
@ -110,18 +111,18 @@ absl::Status CurlTestUtils::CurlTestSetUp() {
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status CurlTestUtils::CurlTestTearDown() { absl::Status curl::tests::CurlTestUtils::CurlTestTearDown() {
// Cleanup curl // Cleanup curl
return api_->curl_easy_cleanup(curl_.get()); return api_->curl_easy_cleanup(curl_.get());
} }
absl::StatusOr<std::string> CurlTestUtils::PerformRequest() { absl::StatusOr<std::string> curl::tests::CurlTestUtils::PerformRequest() {
// Perform the request // Perform the request
absl::StatusOr<int> curl_code = api_->curl_easy_perform(curl_.get()); absl::StatusOr<int> curl_code = api_->curl_easy_perform(curl_.get());
if (!curl_code.ok()) { if (!curl_code.ok()) {
return curl_code.status(); return curl_code.status();
} }
if (curl_code.value() != CURLE_OK) { if (curl_code.value() != curl::CURLE_OK) {
return absl::UnavailableError( return absl::UnavailableError(
"curl_easy_perform returned with the error code " + curl_code.value()); "curl_easy_perform returned with the error code " + curl_code.value());
} }
@ -267,7 +268,7 @@ void ServerLoop(int listening_socket, sockaddr_in socket_address) {
} // namespace } // namespace
void CurlTestUtils::StartMockServer() { void curl::tests::CurlTestUtils::StartMockServer() {
// Get the socket file descriptor // Get the socket file descriptor
int listening_socket = socket(AF_INET, SOCK_STREAM, 0); int listening_socket = socket(AF_INET, SOCK_STREAM, 0);

View File

@ -21,6 +21,8 @@
#include "sandboxed_api/util/flag.h" #include "sandboxed_api/util/flag.h"
#include "sandboxed_api/util/status_matchers.h" #include "sandboxed_api/util/status_matchers.h"
namespace curl::tests {
// Helper class that can be used to test Curl Sandboxed // Helper class that can be used to test Curl Sandboxed
class CurlTestUtils { class CurlTestUtils {
protected: protected:
@ -39,8 +41,8 @@ class CurlTestUtils {
// Responds with the POST request fields to a POST request // Responds with the POST request fields to a POST request
static void StartMockServer(); static void StartMockServer();
std::unique_ptr<CurlSapiSandbox> sandbox_; std::unique_ptr<curl::CurlSapiSandbox> sandbox_;
std::unique_ptr<CurlApi> api_; std::unique_ptr<curl::CurlApi> api_;
std::unique_ptr<sapi::v::RemotePtr> curl_; std::unique_ptr<sapi::v::RemotePtr> curl_;
static std::thread server_thread_; static std::thread server_thread_;
@ -52,4 +54,6 @@ class CurlTestUtils {
std::unique_ptr<sapi::v::LenVal> chunk_; std::unique_ptr<sapi::v::LenVal> chunk_;
}; };
} // namespace curl::tests
#endif // TESTS_H_ #endif // TESTS_H_

View File

@ -14,7 +14,9 @@
#include "test_utils.h" // NOLINT(build/include) #include "test_utils.h" // NOLINT(build/include)
class CurlTest : public CurlTestUtils, public ::testing::Test { namespace {
class CurlTest : public curl::tests::CurlTestUtils, public ::testing::Test {
protected: protected:
void SetUp() override { void SetUp() override {
// Start mock server, get port number and check for any error // Start mock server, get port number and check for any error
@ -38,9 +40,9 @@ TEST_F(CurlTest, EffectiveUrl) {
// Get effective URL // Get effective URL
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int getinfo_code, int getinfo_code,
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_EFFECTIVE_URL, api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_EFFECTIVE_URL,
effective_url_ptr.PtrBoth())); effective_url_ptr.PtrBoth()));
ASSERT_EQ(getinfo_code, CURLE_OK); ASSERT_EQ(getinfo_code, curl::CURLE_OK);
// Store effective URL in a string // Store effective URL in a string
SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url, SAPI_ASSERT_OK_AND_ASSIGN(std::string effective_url,
@ -74,9 +76,9 @@ TEST_F(CurlTest, ResponseCode) {
// Get response code // Get response code
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int getinfo_code, int getinfo_code,
api_->curl_easy_getinfo_ptr(curl_.get(), CURLINFO_RESPONSE_CODE, api_->curl_easy_getinfo_ptr(curl_.get(), curl::CURLINFO_RESPONSE_CODE,
response_code.PtrBoth())); response_code.PtrBoth()));
ASSERT_EQ(getinfo_code, CURLE_OK); ASSERT_EQ(getinfo_code, curl::CURLE_OK);
// Check response code // Check response code
ASSERT_EQ(response_code.GetValue(), 200); ASSERT_EQ(response_code.GetValue(), 200);
@ -120,19 +122,21 @@ TEST_F(CurlTest, POSTResponse) {
// Set the size of the POST fields // Set the size of the POST fields
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int setopt_post_fields_size, int setopt_post_fields_size,
api_->curl_easy_setopt_long(curl_.get(), CURLOPT_POSTFIELDSIZE, api_->curl_easy_setopt_long(curl_.get(), curl::CURLOPT_POSTFIELDSIZE,
post_fields.GetSize())); post_fields.GetSize()));
ASSERT_EQ(setopt_post_fields_size, CURLE_OK); ASSERT_EQ(setopt_post_fields_size, curl::CURLE_OK);
// Set the POST fields // Set the POST fields
SAPI_ASSERT_OK_AND_ASSIGN( SAPI_ASSERT_OK_AND_ASSIGN(
int setopt_post_fields, int setopt_post_fields,
api_->curl_easy_setopt_ptr(curl_.get(), CURLOPT_POSTFIELDS, api_->curl_easy_setopt_ptr(curl_.get(), curl::CURLOPT_POSTFIELDS,
post_fields.PtrBefore())); post_fields.PtrBefore()));
ASSERT_EQ(setopt_post_fields, CURLE_OK); ASSERT_EQ(setopt_post_fields, curl::CURLE_OK);
SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest()); SAPI_ASSERT_OK_AND_ASSIGN(std::string response, PerformRequest());
// Compare response with expected response // Compare response with expected response
ASSERT_EQ(std::string(post_fields.GetData()), response); ASSERT_EQ(std::string(post_fields.GetData()), response);
} }
} // namespace