Skip to content

Commit d3c3c4f

Browse files
committed
Use a connection pool for apache to avoid errors
1 parent 63a1988 commit d3c3c4f

File tree

4 files changed

+152
-35
lines changed

4 files changed

+152
-35
lines changed

src/mod_redirectionio.c

Lines changed: 135 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ static int redirectionio_redirect_handler(request_rec *r);
1717
static int redirectionio_log_handler(request_rec *r);
1818

1919
static apr_status_t redirectionio_create_connection(redirectionio_connection *conn, redirectionio_config *config, apr_pool_t *pool);
20+
static redirectionio_connection* redirectionio_acquire_connection(redirectionio_config *config, apr_pool_t *pool);
21+
static apr_status_t redirectionio_release_connection(redirectionio_connection *conn, redirectionio_config *config, apr_pool_t *pool);
2022

2123
static void *create_redirectionio_dir_conf(apr_pool_t *pool, char *context);
2224
static void *merge_redirectionio_dir_conf(apr_pool_t *pool, void *BASE, void *ADD);
2325

26+
static apr_status_t redirectionio_pool_construct(void** rs, void* params, apr_pool_t* pool);
27+
static apr_status_t redirectionio_pool_destruct(void* resource, void* params, apr_pool_t* pool);
28+
static apr_status_t redirectionio_child_exit(void *resource);
29+
2430
static const char *redirectionio_set_enable(cmd_parms *cmd, void *cfg, const char *arg);
2531
static const char *redirectionio_set_project_key(cmd_parms *cmd, void *cfg, const char *arg);
2632
static const char *redirectionio_set_logs_enable(cmd_parms *cmd, void *cfg, const char *arg);
@@ -66,27 +72,23 @@ static int redirectionio_redirect_handler(request_rec *r) {
6672
}
6773

6874
ap_set_module_config(r->request_config, &redirectionio_module, context);
75+
redirectionio_connection* conn = redirectionio_acquire_connection(config, r->pool);
6976

70-
// Create connection
71-
context->conn = apr_palloc(r->pool, sizeof(redirectionio_connection));
72-
73-
if (context->conn == NULL) {
74-
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Cannot create redirectionio context");
75-
76-
return DECLINED;
77-
}
78-
79-
if (redirectionio_create_connection(context->conn, config, r->pool) != APR_SUCCESS) {
77+
if (conn == NULL) {
8078
return DECLINED;
8179
}
8280

8381
// Ask for redirection
84-
if (redirectionio_protocol_match(context, r, config->project_key) != APR_SUCCESS) {
82+
if (redirectionio_protocol_match(conn, context, r, config->project_key) != APR_SUCCESS) {
83+
redirectionio_release_connection(conn, config, r->pool);
84+
8585
return DECLINED;
8686
}
8787

8888
// No match
8989
if (context->status == 0) {
90+
redirectionio_release_connection(conn, config, r->pool);
91+
9092
return DECLINED;
9193
}
9294

@@ -96,6 +98,8 @@ static int redirectionio_redirect_handler(request_rec *r) {
9698

9799
r->status = context->status;
98100

101+
redirectionio_release_connection(conn, config, r->pool);
102+
99103
return context->status;
100104
}
101105

@@ -112,14 +116,24 @@ static int redirectionio_log_handler(request_rec *r) {
112116

113117
redirectionio_context* context = ap_get_module_config(r->request_config, &redirectionio_module);
114118

115-
if (context == NULL || context->conn == NULL) {
119+
if (context == NULL) {
116120
return DECLINED;
117121
}
118122

119-
if (redirectionio_protocol_log(context, r, config->project_key) != APR_SUCCESS) {
123+
redirectionio_connection* conn = redirectionio_acquire_connection(config, r->pool);
124+
125+
if (conn == NULL) {
120126
return DECLINED;
121127
}
122128

129+
if (redirectionio_protocol_log(conn, context, r, config->project_key) != APR_SUCCESS) {
130+
redirectionio_release_connection(conn, config, r->pool);
131+
132+
return DECLINED;
133+
}
134+
135+
redirectionio_release_connection(conn, config, r->pool);
136+
123137
return OK;
124138
}
125139

@@ -173,20 +187,46 @@ static apr_status_t redirectionio_create_connection(redirectionio_connection *co
173187
return rv;
174188
}
175189

176-
// rv = apr_socket_timeout_set(conn->rio_sock, 0);
177-
//
178-
// if (rv != APR_SUCCESS) {
179-
// ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "mod_redirectionio: Error setting socket timeout: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
180-
//
181-
// return rv;
182-
// }
190+
rv = apr_socket_timeout_set(conn->rio_sock, RIO_TIMEOUT);
191+
192+
if (rv != APR_SUCCESS) {
193+
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "mod_redirectionio: Error setting socket timeout: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
194+
195+
return rv;
196+
}
183197

184198
return APR_SUCCESS;
185199
}
186200

201+
static redirectionio_connection* redirectionio_acquire_connection(redirectionio_config *config, apr_pool_t *pool) {
202+
apr_status_t rv;
203+
redirectionio_connection *conn;
204+
205+
rv = apr_reslist_acquire(config->connection_pool, (void**)&conn);
206+
207+
if (rv != APR_SUCCESS || !conn) {
208+
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "mod_redirectionio: Failed to acquire RIO connection from pool: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
209+
210+
return NULL;
211+
}
212+
213+
return conn;
214+
}
215+
216+
static apr_status_t redirectionio_release_connection(redirectionio_connection *conn, redirectionio_config *config, apr_pool_t *pool) {
217+
apr_status_t rv = apr_reslist_release(config->connection_pool, conn);
218+
219+
if (rv != APR_SUCCESS) {
220+
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "mod_redirectionio: Can not release RIO socket.");
221+
}
222+
223+
return rv;
224+
}
225+
187226
static void *create_redirectionio_dir_conf(apr_pool_t *pool, char *context) {
227+
redirectionio_config *config = apr_pcalloc(pool, sizeof(redirectionio_config));
228+
188229
context = context ? context : "(undefined context)";
189-
redirectionio_config *config = apr_pcalloc(pool, sizeof(redirectionio_config));
190230

191231
if (config) {
192232
config->enable = -1;
@@ -201,9 +241,9 @@ static void *create_redirectionio_dir_conf(apr_pool_t *pool, char *context) {
201241
}
202242

203243
static void *merge_redirectionio_dir_conf(apr_pool_t *pool, void *parent, void *current) {
204-
redirectionio_config *conf_parent = (redirectionio_config *) parent;
205-
redirectionio_config *conf_current = (redirectionio_config *) current;
206-
redirectionio_config *conf = (redirectionio_config *) create_redirectionio_dir_conf(pool, "Merged configuration");
244+
redirectionio_config *conf_parent = (redirectionio_config *) parent;
245+
redirectionio_config *conf_current = (redirectionio_config *) current;
246+
redirectionio_config *conf = (redirectionio_config *) create_redirectionio_dir_conf(pool, "Merged configuration");
207247

208248
/* Merge configurations */
209249
if (conf_current->enable == -1) {
@@ -234,9 +274,80 @@ static void *merge_redirectionio_dir_conf(apr_pool_t *pool, void *parent, void *
234274
conf->server = conf_current->server;
235275
}
236276

277+
if (apr_reslist_create(
278+
&conf->connection_pool,
279+
RIO_MIN_CONNECTIONS,
280+
RIO_KEEP_CONNECTIONS,
281+
RIO_MAX_CONNECTIONS,
282+
0,
283+
redirectionio_pool_construct,
284+
redirectionio_pool_destruct,
285+
conf,
286+
pool
287+
) != APR_SUCCESS) {
288+
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "mod_redirectionio: Failed to initialize resource pool, disabling redirectionio.");
289+
290+
conf->enable = 0;
291+
292+
return conf;
293+
}
294+
295+
apr_pool_cleanup_register(pool, conf->connection_pool, redirectionio_child_exit, redirectionio_child_exit);
296+
237297
return conf;
238298
}
239299

300+
static apr_status_t redirectionio_pool_construct(void** rs, void* params, apr_pool_t* pool) {
301+
redirectionio_config *conf = (redirectionio_config *) params;
302+
redirectionio_connection *conn;
303+
apr_status_t rv;
304+
305+
if (conf->enable != 1) {
306+
return APR_SUCCESS;
307+
}
308+
309+
conn = apr_palloc(pool, sizeof(redirectionio_connection));
310+
rv = redirectionio_create_connection(conn, conf, pool);
311+
312+
if (rv != APR_SUCCESS) {
313+
return APR_EGENERAL;
314+
}
315+
316+
*rs = conn;
317+
318+
if (!*rs) {
319+
ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, pool, "mod_redirectionio: Failed to store socket in resource list");
320+
321+
return APR_EGENERAL;
322+
}
323+
324+
return APR_SUCCESS;
325+
}
326+
327+
static apr_status_t redirectionio_pool_destruct(void* resource, void* params, apr_pool_t* pool) {
328+
if (resource) {
329+
redirectionio_connection *conn = (redirectionio_connection*)resource;
330+
apr_socket_close(conn->rio_sock);
331+
}
332+
333+
return APR_SUCCESS;
334+
}
335+
336+
static apr_status_t redirectionio_child_exit(void *resource) {
337+
apr_reslist_t *connection_pool = (apr_reslist_t *)resource;
338+
apr_pool_t *pool;
339+
340+
apr_pool_create(&pool, NULL);
341+
342+
while (apr_reslist_acquired_count(connection_pool) != 0) {
343+
ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "mod_redirectionio: Socket pool not empty: %i", apr_reslist_acquired_count(connection_pool));
344+
}
345+
346+
apr_reslist_destroy(connection_pool);
347+
348+
return APR_SUCCESS;
349+
}
350+
240351
static const char *redirectionio_set_enable(cmd_parms *cmd, void *cfg, const char *arg) {
241352
redirectionio_config *conf = (redirectionio_config*)cfg;
242353

src/mod_redirectionio.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define mod_redirectionio_h
33

44
#include "apr_network_io.h"
5+
#include "apr_reslist.h"
56

67
#ifndef APR_UNIX
78
#if defined (AF_UNIX)
@@ -16,7 +17,12 @@
1617
#define UNIX 0
1718
#define TCP 1
1819

19-
#define SEND_BUFFER 1048576
20+
#define RIO_TIMEOUT 10000 // Timeout in microseconds
21+
#define RIO_RECONNECT_INTERVAL 0
22+
#define RIO_MIN_CONNECTIONS 1
23+
#define RIO_KEEP_CONNECTIONS 10
24+
#define RIO_MAX_CONNECTIONS 100
25+
#define RIO_SEND_BUFFER 1048576
2026

2127
typedef struct {
2228
const char* project_key;
@@ -25,6 +31,7 @@ typedef struct {
2531
int protocol;
2632
int enable;
2733
int enable_logs;
34+
apr_reslist_t *connection_pool;
2835
} redirectionio_config;
2936

3037
typedef struct {
@@ -33,7 +40,6 @@ typedef struct {
3340
} redirectionio_connection;
3441

3542
typedef struct {
36-
redirectionio_connection *conn;
3743
char *matched_rule_id;
3844
char *target;
3945
int status;

src/redirectionio_protocol.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const char COMMAND_LOG_QUERY[] = "{ \"project_id\": \"%s\", \"request_uri\": \"%
1212

1313
static apr_status_t redirectionio_read_json_handler(redirectionio_connection *conn, apr_pool_t *pool, cJSON **json);
1414

15-
apr_status_t redirectionio_protocol_match(redirectionio_context *ctx, request_rec *r, const char *project_key) {
15+
apr_status_t redirectionio_protocol_match(redirectionio_connection *conn, redirectionio_context *ctx, request_rec *r, const char *project_key) {
1616
apr_size_t wlen, clen;
1717
char *dst;
1818
apr_status_t rv;
@@ -23,23 +23,23 @@ apr_status_t redirectionio_protocol_match(redirectionio_context *ctx, request_re
2323
sprintf(dst, COMMAND_MATCH_QUERY, project_key, r->unparsed_uri, r->hostname);
2424

2525
clen = sizeof(COMMAND_MATCH_NAME);
26-
rv = apr_socket_send(ctx->conn->rio_sock, COMMAND_MATCH_NAME, &clen);
26+
rv = apr_socket_send(conn->rio_sock, COMMAND_MATCH_NAME, &clen);
2727

2828
if (rv != APR_SUCCESS) {
2929
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_redirectionio: Error sending match command: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
3030

3131
return rv;
3232
}
3333

34-
rv = apr_socket_send(ctx->conn->rio_sock, dst, &wlen);
34+
rv = apr_socket_send(conn->rio_sock, dst, &wlen);
3535

3636
if (rv != APR_SUCCESS) {
3737
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_redirectionio: Error sending match command data: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
3838

3939
return rv;
4040
}
4141

42-
rv = redirectionio_read_json_handler(ctx->conn, r->pool, &result);
42+
rv = redirectionio_read_json_handler(conn, r->pool, &result);
4343

4444
if (rv != APR_SUCCESS) {
4545
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_redirectionio: Error receiving match command result: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
@@ -70,7 +70,7 @@ apr_status_t redirectionio_protocol_match(redirectionio_context *ctx, request_re
7070
return APR_SUCCESS;
7171
}
7272

73-
apr_status_t redirectionio_protocol_log(redirectionio_context *ctx, request_rec *r, const char *project_key) {
73+
apr_status_t redirectionio_protocol_log(redirectionio_connection *conn, redirectionio_context *ctx, request_rec *r, const char *project_key) {
7474
apr_size_t wlen, clen;
7575
const char *location = apr_table_get(r->headers_out, "Location");
7676
const char *user_agent = apr_table_get(r->headers_in, "User-Agent");
@@ -119,15 +119,15 @@ apr_status_t redirectionio_protocol_log(redirectionio_context *ctx, request_rec
119119
);
120120

121121
clen = sizeof(COMMAND_LOG_NAME);
122-
rv = apr_socket_send(ctx->conn->rio_sock, COMMAND_LOG_NAME, &clen);
122+
rv = apr_socket_send(conn->rio_sock, COMMAND_LOG_NAME, &clen);
123123

124124
if (rv != APR_SUCCESS) {
125125
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_redirectionio: Error sending log command: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));
126126

127127
return rv;
128128
}
129129

130-
rv = apr_socket_send(ctx->conn->rio_sock, dst, &wlen);
130+
rv = apr_socket_send(conn->rio_sock, dst, &wlen);
131131

132132
if (rv != APR_SUCCESS) {
133133
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mod_redirectionio: Error sending log command data: %s", apr_strerror(rv, errbuf, sizeof(errbuf)));

src/redirectionio_protocol.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "mod_redirectionio.h"
55
#include "httpd.h"
66

7-
apr_status_t redirectionio_protocol_match(redirectionio_context *ctx, request_rec *r, const char *project_key);
8-
apr_status_t redirectionio_protocol_log(redirectionio_context *ctx, request_rec *r, const char *project_key);
7+
apr_status_t redirectionio_protocol_match(redirectionio_connection *conn, redirectionio_context *ctx, request_rec *r, const char *project_key);
8+
apr_status_t redirectionio_protocol_log(redirectionio_connection *conn, redirectionio_context *ctx, request_rec *r, const char *project_key);
99

1010
#endif

0 commit comments

Comments
 (0)