Hi,
Here is a patch trying to fix the persistent connection issue.
The patch adds a relay_disconnect function.
This function allows to only disconnect se_out connection and reallocate
output buffer for future use.
The patch also uses this function in relay_match_action for http if it
appears destination changed.
Feel free to comment.
Regards,
--
Paul Fariello
PGP: 0x672CDD2031AAF49B
? .gitignore
? 0001-Remove-superfluous-http-method-handling-for-request-.patch
? README.md
Index: relay.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.206
diff -u -p -r1.206 relay.c
--- relay.c 30 Dec 2015 16:00:57 -0000 1.206
+++ relay.c 4 Aug 2016 19:32:58 -0000
@@ -1646,6 +1646,67 @@ relay_connect(struct rsession *con)
}
void
+relay_disconnect(struct rsession *con, const char *msg)
+{
+ char ibuf[128], obuf[128], *ptr = NULL;
+ struct relay *rlay = con->se_relay;
+
+ if ((env->sc_opts & RELAYD_OPT_LOGUPDATE) && msg != NULL) {
+ bzero(&ibuf, sizeof(ibuf));
+ bzero(&obuf, sizeof(obuf));
+ (void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf));
+ (void)print_host(&con->se_out.ss, obuf, sizeof(obuf));
+ if (EVBUFFER_LENGTH(con->se_log) &&
+ evbuffer_add_printf(con->se_log, "\r\n") != -1)
+ ptr = evbuffer_readline(con->se_log);
+ log_info("relay %s, "
+ "session %d (%d active), %s, %s -> %s:%d, "
+ "%s%s%s", rlay->rl_conf.name, con->se_id, relay_sessions,
+ con->se_tag != 0 ? tag_id2name(con->se_tag) : "0", ibuf,
+ obuf, ntohs(con->se_out.port), msg, ptr == NULL ? "" : ",",
+ ptr == NULL ? "" : ptr);
+ free(ptr);
+ }
+
+ if (con->se_out.bev != NULL) {
+ bufferevent_free(con->se_out.bev);
+ con->se_out.bev = NULL;
+ }
+ if (con->se_out.ssl != NULL) {
+ /* XXX handle non-blocking shutdown */
+ if (SSL_shutdown(con->se_out.ssl) == 0)
+ SSL_shutdown(con->se_out.ssl);
+ SSL_free(con->se_out.ssl);
+ con->se_out.ssl = NULL;
+ }
+ if (con->se_out.tlscert != NULL) {
+ X509_free(con->se_out.tlscert);
+ con->se_out.tlscert = NULL;
+ }
+ if (con->se_out.s != -1) {
+ close(con->se_out.s);
+
+ /* Some file descriptors are available again. */
+ if (evtimer_pending(&rlay->rl_evt, NULL)) {
+ evtimer_del(&rlay->rl_evt);
+ event_add(&rlay->rl_ev, NULL);
+ }
+ con->se_out.s = -1;
+ }
+
+ /* Pre-allocate output buffer */
+ con->se_out.output = evbuffer_new();
+ if (con->se_out.output == NULL) {
+ relay_close(con, "failed to allocate output buffer");
+ return;
+ }
+
+ con->se_out.state = STATE_INIT;
+
+ free(con->se_out.buf);
+}
+
+void
relay_close(struct rsession *con, const char *msg)
{
char ibuf[128], obuf[128], *ptr = NULL;
Index: relay_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v
retrieving revision 1.57
diff -u -p -r1.57 relay_http.c
--- relay_http.c 27 Jul 2016 06:55:44 -0000 1.57
+++ relay_http.c 4 Aug 2016 19:32:58 -0000
@@ -1414,8 +1414,13 @@ relay_match_actions(struct ctl_relay_eve
/*
* Apply the following options instantly (action per match).
*/
- if (rule->rule_table != NULL)
+ if (rule->rule_table != NULL) {
+ if (con->se_table != rule->rule_table &&
+ cre->dst->state == STATE_CONNECTED) {
+ relay_disconnect(con, "change destination");
+ }
con->se_table = rule->rule_table;
+ }
if (rule->rule_tag != 0)
con->se_tag = rule->rule_tag == -1 ? 0 : rule->rule_tag;
Index: relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.224
diff -u -p -r1.224 relayd.h
--- relayd.h 27 Jul 2016 06:55:44 -0000 1.224
+++ relayd.h 4 Aug 2016 19:32:58 -0000
@@ -1166,6 +1166,7 @@ int relay_spliceadjust(struct ctl_relay
void relay_error(struct bufferevent *, short, void *);
int relay_preconnect(struct rsession *);
int relay_connect(struct rsession *);
+void relay_disconnect(struct rsession *, const char *);
void relay_connected(int, short, void *);
void relay_bindanyreq(struct rsession *, in_port_t, int);
void relay_bindany(int, short, void *);