-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathWorker.cpp
More file actions
184 lines (149 loc) · 6.01 KB
/
Worker.cpp
File metadata and controls
184 lines (149 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//
// Created by Kosho Owa on 2016/08/19.
// Worker thread to perform HTTP requests
//
#include "Worker.h"
//Worker::Worker(Stats *stats, Options *options) : stats_(stats), options_(options) {}
Worker::Worker(Stats *stats_, Options *options_, mutex *mtx_for_cout_) : stats_(stats_), options_(options_),
mtx_for_cout_(mtx_for_cout_) {}
void Worker::Run() {
// Verbose output
if(options_->verbose_){
stringstream msg_start;
msg_start << this_thread::get_id() << " Started." << endl;
safe_cout(msg_start.str());
}
// init easy curl
CURL *curl = curl_easy_init();
if (curl) {
CURLcode cr;
FILE *f;
// Do not show the response unless verbose logging
if (!options_->verbose_) {
f = fopen("/dev/null", "wb");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
}
// Set the method explicitly
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, options_->http_method_.c_str());
// Capture HTTP errors
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
// Enable basic auth
if (!options_->http_user_.empty()) {
curl_easy_setopt(curl, CURLOPT_USERPWD, options_->http_user_.c_str());
}
// Set headers
struct curl_slist *slist;
slist = curl_slist_append(slist, "Content-Type: application/json");
slist = curl_slist_append(slist, options_->http_header_.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
while(stats_->CountRequest() < options_->num_recurrence_) {
// Supply random numbers and strings
string url = ReplaceRNUMEx(options_->request_url_);
url = ReplaceRNUM(url);
string body = ReplaceRNUMEx(options_->request_body_);
body = ReplaceRNUM(body);
if (options_->dict_.size() > 0) {
url = ReplaceRDICT(url);
body = ReplaceRDICT(body);
}
if(options_->verbose_){
stringstream msg_url;
msg_url << this_thread::get_id() << " URL: " << url << endl;
safe_cout(msg_url.str());
stringstream msg_body;
msg_body << this_thread::get_id() << " Body: " << body << endl;
safe_cout(msg_body.str());
}
// Set the URL and the body
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.size());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body.c_str());
// Set timeout
curl_easy_setopt(curl, CURLOPT_TIMEOUT, options_->timeout_sec_);
// Perform a request
cr = curl_easy_perform(curl);
stringstream msg_response;
// curl and HTTP errors
switch (cr) {
case CURLE_OK:
long sizeUpload;
double sizeDownload;
long sizeReceivedHeader;
double transferTime;
curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &sizeUpload);
curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &sizeDownload);
curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &sizeReceivedHeader);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &transferTime);
stats_->CountResult(1, 0, 0, sizeUpload, (u_int) (sizeDownload + sizeReceivedHeader),
transferTime);
break;
case CURLE_HTTP_RETURNED_ERROR:
long http_response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_response_code);
msg_response << "Error: HTTP response (" << http_response_code << ")" << endl;
safe_cerr(msg_response.str());
stats_->CountResult(0, 0, 1, 0, 0, 0);
break;
default:
msg_response << "Error: curl_easy_perform() returned (" << cr << ") " << curl_easy_strerror(cr) << endl;
safe_cerr(msg_response.str());
stats_->CountResult(0, 1, 0, 0, 0, 0);
}
}
if (!options_->verbose_) fclose(f);
curl_easy_cleanup(curl);
}
}
// Replace $RNUM with random numbers
string Worker::ReplaceRNUM(const string in) {
random_device rd;
string from = "$RNUM";
string subject = in;
string::size_type pos = subject.find(from);
while (pos != string::npos) {
string to = to_string(rd() % 256);
subject.replace(pos, from.size(), to);
pos = subject.find(from, pos + to.size());
}
return subject;
}
// Replace $RDICT with randomly selected strings
string Worker::ReplaceRDICT(const string in) {
random_device rd;
string from = "$RDICT";
string subject = in;
string::size_type pos = subject.find(from);
while (pos != string::npos) {
string to = options_->dict_.at(rd() % options_->dict_.size());
subject.replace(pos, from.size(), to);
pos = subject.find(from, pos + to.size());
}
return subject;
}
string Worker::ReplaceRNUMEx(const string in) {
random_device rd;
string from = "$RNUM(";
string subject = in;
string::size_type s_pos = subject.find(from);
while (s_pos != string::npos) {
string::size_type e_pos = subject.find(")", s_pos);
int m = atoi(subject.substr(s_pos + from.size(), e_pos).c_str());
string to;
if (m > 0) {
to = to_string(rd() % m);
}else{
to = "";
}
subject.replace(s_pos, e_pos - s_pos +1, to);
s_pos = subject.find(from, s_pos + to.size());
}
return subject;
}
void Worker::safe_cout(const string msg) {
lock_guard<mutex> lock(*mtx_for_cout_);
cout << msg;
}
void Worker::safe_cerr(const string msg) {
lock_guard<std::mutex> lock(*mtx_for_cout_);
cerr << msg;
}