]>
sourceware.org Git - systemtap.git/blob - client-http.cxx
530bdac1775f73819ed04892b183912f1dd27d25
2 // Copyright (C) 2017 Red Hat Inc.
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
11 #ifdef HAVE_HTTP_SUPPORT
13 #include "client-http.h"
22 #include <curl/curl.h>
23 #include <curl/easy.h>
24 #include <curl/curlbuild.h>
31 http_client_backend::get_data (void *ptr
, size_t size
, size_t nitems
,
32 http_client_backend
* client
)
34 string
data ((const char *) ptr
, (size_t) size
* nitems
);
36 if (data
.front () == '{')
39 bool parsedSuccess
= reader
.parse (data
,
42 if (not parsedSuccess
)
43 clog
<< "Failed to parse JSON" << reader
.getFormattedErrorMessages() << endl
;
49 http_client_backend::get_header (void *ptr
, size_t size
, size_t nitems
,
50 http_client_backend
* client
)
52 string
data ((const char *) ptr
, (size_t) size
* nitems
);
54 unsigned long colon
= data
.find(':');
55 if (colon
!= string::npos
)
57 string key
= data
.substr (0, colon
);
58 string value
= data
.substr (colon
+ 2, data
.length() - colon
- 4);
59 client
->header_values
[key
] = value
;
66 http_client_backend::get_file (void *ptr
, size_t size
, size_t nitems
,
70 written
= fwrite(ptr
, size
, nitems
, stream
);
76 http_client_backend::download (const std::string
& url
, http_client_backend::download_type type
)
78 struct curl_slist
*headers
= NULL
;
80 curl_easy_setopt (curl
, CURLOPT_URL
, url
.c_str ());
81 /* example.com is redirected, so we tell libcurl to follow redirection */
82 curl_easy_setopt (curl
, CURLOPT_FOLLOWLOCATION
, 1L);
83 curl_easy_setopt (curl
, CURLOPT_NOSIGNAL
, 1); //Prevent "longjmp causes uninitialized stack frame" bug
84 curl_easy_setopt (curl
, CURLOPT_ACCEPT_ENCODING
, "deflate");
85 headers
= curl_slist_append (headers
, "Accept: */*");
86 headers
= curl_slist_append (headers
, "Content-Type: text/html");
87 curl_easy_setopt (curl
, CURLOPT_HTTPHEADER
, headers
);
88 curl_easy_setopt (curl
, CURLOPT_HTTPGET
, 1);
92 if (type
== json_type
)
94 curl_easy_setopt (curl
, CURLOPT_WRITEDATA
, lthis
);
95 curl_easy_setopt (curl
, CURLOPT_WRITEFUNCTION
, http_client_backend::get_data
);
97 else if (type
== file_type
)
99 std::string filename
= url
;
100 std::string ko_suffix
= ".ko";
101 std::string filepath
;
102 if (filename
.back() == '/')
103 filename
.erase(filename
.length()-1);
105 if (std::equal(ko_suffix
.rbegin(), ko_suffix
.rend(), filename
.rbegin()))
106 filepath
= s
.tmpdir
+ "/" + s
.module_name
+ ".ko";
108 filepath
= s
.tmpdir
+ "/" + filename
.substr (filename
.rfind ('/')+1);
111 clog
<< "Downloaded " + filepath
<< endl
;
112 std::FILE *File
= std::fopen(filepath
.c_str(), "wb");
113 curl_easy_setopt (curl
, CURLOPT_WRITEDATA
, File
);
114 curl_easy_setopt (curl
, CURLOPT_WRITEFUNCTION
, http_client_backend::get_file
);
116 curl_easy_setopt (curl
, CURLOPT_HEADERDATA
, lthis
);
117 curl_easy_setopt (curl
, CURLOPT_HEADERFUNCTION
, http_client_backend::get_header
);
120 res
= curl_easy_perform (curl
);
124 fprintf (stderr
, "curl_easy_perform() failed in %s: %s\n",
125 __FUNCTION__
, curl_easy_strerror (res
));
134 http_client_backend::post (const std::string
& url
, const std::string
& data
)
136 struct curl_slist
*headers
= NULL
;
138 curl_easy_setopt (curl
, CURLOPT_URL
, url
.c_str());
139 curl_easy_setopt (curl
, CURLOPT_POST
, 1);
140 curl_easy_setopt (curl
, CURLOPT_POSTFIELDS
, data
.c_str ());
141 headers
= curl_slist_append (headers
, "Accept: */*");
143 curl_slist_append (headers
,
144 "Content-Type: application/x-www-form-urlencoded");
145 curl_easy_setopt (curl
, CURLOPT_HTTPHEADER
, headers
);
147 CURLcode res
= curl_easy_perform (curl
);
148 /* Check for errors */
151 fprintf (stderr
, "curl_easy_perform() failed in %s: %s\n",
152 __FUNCTION__
, curl_easy_strerror (res
));
158 http_client_backend::initialize ()
160 request_parameters
.clear();
161 request_files
.clear();
162 curl
= curl_easy_init ();
169 http_client_backend::package_request ()
171 const std::string query_parts
[] =
177 query
= query_parts
[0] + s
.release
+ query_parts
[1] + s
.release
.substr (s
.release
.rfind ('.')+1);
179 for (vector
<std::tuple
<std::string
, std::string
>>::const_iterator it
= request_parameters
.begin ();
180 it
!= request_parameters
.end ();
183 string parm_type
= get
<0>(*it
);
184 if (parm_type
== "cmd_args" && stat (get
<1>(*it
).c_str(), &buffer
) != 0)
185 query
= query
+ "&cmd_args=" + get
<1>(*it
);
189 clog
<< "Query: " + query
<< endl
;
195 http_client_backend::find_and_connect_to_server ()
197 for (vector
<std::string
>::const_iterator i
= s
.http_servers
.begin ();
198 i
!= s
.http_servers
.end ();
200 if (download (*i
+ "/builds", json_type
))
203 post (host
+ "/builds", query
);
206 std::string::size_type found
= host
.find ("/builds");
208 if (found
!= std::string::npos
)
209 uri
= host
.substr (0, found
) + header_values
["Location"];
211 uri
= host
+ header_values
["Location"];
215 int retry
= std::stoi (header_values
["Retry-After"], nullptr, 10);
217 clog
<< "Waiting " << retry
<< " seconds...";
219 if (download (host
+ header_values
["Location"], json_type
))
221 const Json::Value uuid
= root
["uuid"];
223 for(Json::Value::iterator it
= root
["files"].begin();
224 it
!= root
["files"].end(); ++it
)
226 for(unsigned int index
=0; index
< (*it
).size()-1;
228 download (host
+ (*it
)["location"].asString(), file_type
);
231 for(Json::Value::iterator it
= root
.begin();
232 it
!= root
.end(); ++it
)
234 Json::Value val
= (*it
);
235 std::cout
<< it
.key().asString() << ':' << (*it
) << '\n';
241 download (host
+ root
["stderr_location"].asString(), file_type
);
242 std::ifstream
ferr(s
.tmpdir
+ "/stderr");
244 std::cout
<< ferr
.rdbuf() << endl
;
246 download (host
+ root
["stdout_location"].asString(), file_type
);
247 std::ifstream
fout(s
.tmpdir
+ "/stdout");
249 std::cout
<< fout
.rdbuf() << endl
;
256 http_client_backend::unpack_response ()
262 http_client_backend::process_response ()
268 http_client_backend::add_protocol_version (const std::string
&version
)
270 // Add the protocol version (so the server can ensure we're
272 request_parameters
.push_back(make_tuple("version", version
));
277 http_client_backend::add_sysinfo ()
280 request_parameters
.push_back(make_tuple("kver", s
.kernel_release
));
281 request_parameters
.push_back(make_tuple("arch", s
.architecture
));
286 http_client_backend::include_file_or_directory (const std::string
&,
289 // FIXME: this is going to be interesting. We can't add a whole
290 // directory at one shot, we'll have to traverse the directory and
291 // add each file, preserving the directory structure somehow.
296 http_client_backend::add_tmpdir_file (const std::string
&file
)
298 request_files
.push_back(make_tuple("files", file
));
303 http_client_backend::add_cmd_arg (const std::string
&arg
)
305 request_parameters
.push_back(make_tuple("cmd_args", arg
));
310 http_client_backend::add_localization_variable(const std::string
&,
313 // FIXME: We'll probably just add to the request_parameters here.
318 http_client_backend::add_mok_fingerprint(const std::string
&)
320 // FIXME: We'll probably just add to the request_parameters here.
324 #endif /* HAVE_HTTP_SUPPORT */
This page took 0.048393 seconds and 5 git commands to generate.