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 *);

Reply via email to