Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/external/curl/lib/cf-haproxy.c
2065 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
25
#include "curl_setup.h"
26
27
#if !defined(CURL_DISABLE_PROXY)
28
29
#include <curl/curl.h>
30
#include "urldata.h"
31
#include "cfilters.h"
32
#include "cf-haproxy.h"
33
#include "curl_trc.h"
34
#include "multiif.h"
35
36
/* The last 3 #include files should be in this order */
37
#include "curl_printf.h"
38
#include "curl_memory.h"
39
#include "memdebug.h"
40
41
42
typedef enum {
43
HAPROXY_INIT, /* init/default/no tunnel state */
44
HAPROXY_SEND, /* data_out being sent */
45
HAPROXY_DONE /* all work done */
46
} haproxy_state;
47
48
struct cf_haproxy_ctx {
49
int state;
50
struct dynbuf data_out;
51
};
52
53
static void cf_haproxy_ctx_reset(struct cf_haproxy_ctx *ctx)
54
{
55
DEBUGASSERT(ctx);
56
ctx->state = HAPROXY_INIT;
57
curlx_dyn_reset(&ctx->data_out);
58
}
59
60
static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx)
61
{
62
if(ctx) {
63
curlx_dyn_free(&ctx->data_out);
64
free(ctx);
65
}
66
}
67
68
static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
69
struct Curl_easy *data)
70
{
71
struct cf_haproxy_ctx *ctx = cf->ctx;
72
CURLcode result;
73
const char *client_ip;
74
struct ip_quadruple ipquad;
75
int is_ipv6;
76
77
DEBUGASSERT(ctx);
78
DEBUGASSERT(ctx->state == HAPROXY_INIT);
79
#ifdef USE_UNIX_SOCKETS
80
if(cf->conn->unix_domain_socket)
81
/* the buffer is large enough to hold this! */
82
result = curlx_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
83
else {
84
#endif /* USE_UNIX_SOCKETS */
85
result = Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad);
86
if(result)
87
return result;
88
89
/* Emit the correct prefix for IPv6 */
90
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
91
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
92
else
93
client_ip = ipquad.local_ip;
94
95
result = curlx_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
96
is_ipv6 ? "TCP6" : "TCP4",
97
client_ip, ipquad.remote_ip,
98
ipquad.local_port, ipquad.remote_port);
99
100
#ifdef USE_UNIX_SOCKETS
101
}
102
#endif /* USE_UNIX_SOCKETS */
103
return result;
104
}
105
106
static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
107
struct Curl_easy *data,
108
bool *done)
109
{
110
struct cf_haproxy_ctx *ctx = cf->ctx;
111
CURLcode result;
112
size_t len;
113
114
DEBUGASSERT(ctx);
115
if(cf->connected) {
116
*done = TRUE;
117
return CURLE_OK;
118
}
119
120
result = cf->next->cft->do_connect(cf->next, data, done);
121
if(result || !*done)
122
return result;
123
124
switch(ctx->state) {
125
case HAPROXY_INIT:
126
result = cf_haproxy_date_out_set(cf, data);
127
if(result)
128
goto out;
129
ctx->state = HAPROXY_SEND;
130
FALLTHROUGH();
131
case HAPROXY_SEND:
132
len = curlx_dyn_len(&ctx->data_out);
133
if(len > 0) {
134
ssize_t nwritten;
135
nwritten = Curl_conn_cf_send(cf->next, data,
136
curlx_dyn_ptr(&ctx->data_out), len, FALSE,
137
&result);
138
if(nwritten < 0) {
139
if(result != CURLE_AGAIN)
140
goto out;
141
result = CURLE_OK;
142
nwritten = 0;
143
}
144
curlx_dyn_tail(&ctx->data_out, len - (size_t)nwritten);
145
if(curlx_dyn_len(&ctx->data_out) > 0) {
146
result = CURLE_OK;
147
goto out;
148
}
149
}
150
ctx->state = HAPROXY_DONE;
151
FALLTHROUGH();
152
default:
153
curlx_dyn_free(&ctx->data_out);
154
break;
155
}
156
157
out:
158
*done = (!result) && (ctx->state == HAPROXY_DONE);
159
cf->connected = *done;
160
return result;
161
}
162
163
static void cf_haproxy_destroy(struct Curl_cfilter *cf,
164
struct Curl_easy *data)
165
{
166
(void)data;
167
CURL_TRC_CF(data, cf, "destroy");
168
cf_haproxy_ctx_free(cf->ctx);
169
}
170
171
static void cf_haproxy_close(struct Curl_cfilter *cf,
172
struct Curl_easy *data)
173
{
174
CURL_TRC_CF(data, cf, "close");
175
cf->connected = FALSE;
176
cf_haproxy_ctx_reset(cf->ctx);
177
if(cf->next)
178
cf->next->cft->do_close(cf->next, data);
179
}
180
181
static void cf_haproxy_adjust_pollset(struct Curl_cfilter *cf,
182
struct Curl_easy *data,
183
struct easy_pollset *ps)
184
{
185
if(cf->next->connected && !cf->connected) {
186
/* If we are not connected, but the filter "below" is
187
* and not waiting on something, we are sending. */
188
Curl_pollset_set_out_only(data, ps, Curl_conn_cf_get_socket(cf, data));
189
}
190
}
191
192
struct Curl_cftype Curl_cft_haproxy = {
193
"HAPROXY",
194
CF_TYPE_PROXY,
195
0,
196
cf_haproxy_destroy,
197
cf_haproxy_connect,
198
cf_haproxy_close,
199
Curl_cf_def_shutdown,
200
Curl_cf_def_get_host,
201
cf_haproxy_adjust_pollset,
202
Curl_cf_def_data_pending,
203
Curl_cf_def_send,
204
Curl_cf_def_recv,
205
Curl_cf_def_cntrl,
206
Curl_cf_def_conn_is_alive,
207
Curl_cf_def_conn_keep_alive,
208
Curl_cf_def_query,
209
};
210
211
static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
212
struct Curl_easy *data)
213
{
214
struct Curl_cfilter *cf = NULL;
215
struct cf_haproxy_ctx *ctx;
216
CURLcode result;
217
218
(void)data;
219
ctx = calloc(1, sizeof(*ctx));
220
if(!ctx) {
221
result = CURLE_OUT_OF_MEMORY;
222
goto out;
223
}
224
ctx->state = HAPROXY_INIT;
225
curlx_dyn_init(&ctx->data_out, DYN_HAXPROXY);
226
227
result = Curl_cf_create(&cf, &Curl_cft_haproxy, ctx);
228
if(result)
229
goto out;
230
ctx = NULL;
231
232
out:
233
cf_haproxy_ctx_free(ctx);
234
*pcf = result ? NULL : cf;
235
return result;
236
}
237
238
CURLcode Curl_cf_haproxy_insert_after(struct Curl_cfilter *cf_at,
239
struct Curl_easy *data)
240
{
241
struct Curl_cfilter *cf;
242
CURLcode result;
243
244
result = cf_haproxy_create(&cf, data);
245
if(result)
246
goto out;
247
Curl_conn_cf_insert_after(cf_at, cf);
248
249
out:
250
return result;
251
}
252
253
#endif /* !CURL_DISABLE_PROXY */
254
255