Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmcurl/lib/cf-haproxy.c
5012 views
1
/***************************************************************************
2
* _ _ ____ _
3
* Project ___| | | | _ \| |
4
* / __| | | | |_) | |
5
* | (__| |_| | _ <| |___
6
* \___|\___/|_| \_\_____|
7
*
8
* Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9
*
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at https://curl.se/docs/copyright.html.
13
*
14
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
* copies of the Software, and permit persons to whom the Software is
16
* furnished to do so, under the terms of the COPYING file.
17
*
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
* KIND, either express or implied.
20
*
21
* SPDX-License-Identifier: curl
22
*
23
***************************************************************************/
24
#include "curl_setup.h"
25
26
#ifndef CURL_DISABLE_PROXY
27
28
#include "urldata.h"
29
#include "cfilters.h"
30
#include "cf-haproxy.h"
31
#include "curl_trc.h"
32
#include "select.h"
33
34
35
typedef enum {
36
HAPROXY_INIT, /* init/default/no tunnel state */
37
HAPROXY_SEND, /* data_out being sent */
38
HAPROXY_DONE /* all work done */
39
} haproxy_state;
40
41
struct cf_haproxy_ctx {
42
int state;
43
struct dynbuf data_out;
44
};
45
46
static void cf_haproxy_ctx_reset(struct cf_haproxy_ctx *ctx)
47
{
48
DEBUGASSERT(ctx);
49
ctx->state = HAPROXY_INIT;
50
curlx_dyn_reset(&ctx->data_out);
51
}
52
53
static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
54
{
55
if(ctx) {
56
curlx_dyn_free(&ctx->data_out);
57
curlx_free(ctx);
58
}
59
}
60
61
static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf,
62
struct Curl_easy *data)
63
{
64
struct cf_haproxy_ctx *ctx = cf->ctx;
65
CURLcode result;
66
const char *client_ip;
67
struct ip_quadruple ipquad;
68
bool is_ipv6;
69
70
DEBUGASSERT(ctx);
71
DEBUGASSERT(ctx->state == HAPROXY_INIT);
72
#ifdef USE_UNIX_SOCKETS
73
if(cf->conn->unix_domain_socket)
74
/* the buffer is large enough to hold this! */
75
result = curlx_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
76
else {
77
#endif /* USE_UNIX_SOCKETS */
78
result = Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad);
79
if(result)
80
return result;
81
82
/* Emit the correct prefix for IPv6 */
83
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
84
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
85
else
86
client_ip = ipquad.local_ip;
87
88
result = curlx_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
89
is_ipv6 ? "TCP6" : "TCP4",
90
client_ip, ipquad.remote_ip,
91
ipquad.local_port, ipquad.remote_port);
92
93
#ifdef USE_UNIX_SOCKETS
94
}
95
#endif /* USE_UNIX_SOCKETS */
96
return result;
97
}
98
99
static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
100
struct Curl_easy *data,
101
bool *done)
102
{
103
struct cf_haproxy_ctx *ctx = cf->ctx;
104
CURLcode result;
105
size_t len;
106
107
DEBUGASSERT(ctx);
108
if(cf->connected) {
109
*done = TRUE;
110
return CURLE_OK;
111
}
112
113
result = cf->next->cft->do_connect(cf->next, data, done);
114
if(result || !*done)
115
return result;
116
117
switch(ctx->state) {
118
case HAPROXY_INIT:
119
result = cf_haproxy_date_out_set(cf, data);
120
if(result)
121
goto out;
122
ctx->state = HAPROXY_SEND;
123
FALLTHROUGH();
124
case HAPROXY_SEND:
125
len = curlx_dyn_len(&ctx->data_out);
126
if(len > 0) {
127
size_t nwritten;
128
result = Curl_conn_cf_send(cf->next, data,
129
curlx_dyn_uptr(&ctx->data_out), len, FALSE,
130
&nwritten);
131
if(result) {
132
if(result != CURLE_AGAIN)
133
goto out;
134
result = CURLE_OK;
135
nwritten = 0;
136
}
137
curlx_dyn_tail(&ctx->data_out, len - nwritten);
138
if(curlx_dyn_len(&ctx->data_out) > 0) {
139
result = CURLE_OK;
140
goto out;
141
}
142
}
143
ctx->state = HAPROXY_DONE;
144
FALLTHROUGH();
145
default:
146
curlx_dyn_free(&ctx->data_out);
147
break;
148
}
149
150
out:
151
*done = (!result) && (ctx->state == HAPROXY_DONE);
152
cf->connected = *done;
153
return result;
154
}
155
156
static void cf_haproxy_destroy(struct Curl_cfilter *cf,
157
struct Curl_easy *data)
158
{
159
(void)data;
160
CURL_TRC_CF(data, cf, "destroy");
161
cf_haproxy_ctx_free(cf->ctx);
162
}
163
164
static void cf_haproxy_close(struct Curl_cfilter *cf,
165
struct Curl_easy *data)
166
{
167
CURL_TRC_CF(data, cf, "close");
168
cf->connected = FALSE;
169
cf_haproxy_ctx_reset(cf->ctx);
170
if(cf->next)
171
cf->next->cft->do_close(cf->next, data);
172
}
173
174
static CURLcode cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
175
struct Curl_easy *data,
176
struct easy_pollset *ps)
177
{
178
if(cf->next->connected && !cf->connected) {
179
/* If we are not connected, but the filter "below" is
180
* and not waiting on something, we are sending. */
181
return Curl_pollset_set_out_only(
182
data, ps, Curl_conn_cf_get_socket(cf, data));
183
}
184
return CURLE_OK;
185
}
186
187
struct Curl_cftype Curl_cft_haproxy = {
188
"HAPROXY",
189
CF_TYPE_PROXY,
190
0,
191
cf_haproxy_destroy,
192
cf_haproxy_connect,
193
cf_haproxy_close,
194
Curl_cf_def_shutdown,
195
cf_haproxy_adjust_pollset,
196
Curl_cf_def_data_pending,
197
Curl_cf_def_send,
198
Curl_cf_def_recv,
199
Curl_cf_def_cntrl,
200
Curl_cf_def_conn_is_alive,
201
Curl_cf_def_conn_keep_alive,
202
Curl_cf_def_query,
203
};
204
205
static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
206
struct Curl_easy *data)
207
{
208
struct Curl_cfilter *cf = NULL;
209
struct cf_haproxy_ctx *ctx;
210
CURLcode result;
211
212
(void)data;
213
ctx = curlx_calloc(1, sizeof(*ctx));
214
if(!ctx) {
215
result = CURLE_OUT_OF_MEMORY;
216
goto out;
217
}
218
ctx->state = HAPROXY_INIT;
219
curlx_dyn_init(&ctx->data_out, DYN_HAXPROXY);
220
221
result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
222
if(result)
223
goto out;
224
ctx = NULL;
225
226
out:
227
cf_haproxy_ctx_free(ctx);
228
*pcf = result ? NULL : cf;
229
return result;
230
}
231
232
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
233
struct Curl_easy *data)
234
{
235
struct Curl_cfilter *cf;
236
CURLcode result;
237
238
result = cf_haproxy_create(&cf, data);
239
if(result)
240
goto out;
241
Curl_conn_cf_insert_after(cf_at, cf);
242
243
out:
244
return result;
245
}
246
247
#endif /* !CURL_DISABLE_PROXY */
248
249