Skip to content

Commit ddc5f8d

Browse files
committed
BUG/MEDIUM: mux-spop: Properly handle CLOSING state
The CLOSING state was not handled at all by the SPOP multiplexer while it is mandatory when a DISCONNECT frame was sent and the mux should wait for the DISCONNECT frame in reply from the agent. Thanks to this patch, it should be fixed. In addition, if an error occurres during the AGENT HELLO frame parsing, the SPOP connection is no longer switched to CLOSED state and remains in ERROR state instead. It is important to be able to send the DISCONNECT frame to the agent instead of closing the TCP connection immediately. This patch depends on following commits: * BUG/MEDIUM: mux-spop: Remove frame parsing states from the SPOP connection state * MINOR: mux-spop: Don't set SPOP connection state to FRAME_H after ACK parsing * BUG/MINOR: mux-spop: Don't open new streams for SPOP connection on error * BUG/MINOR: mux-spop: Make the demux stream ID a signed integer All the series must be backported to 3.1.
1 parent a394061 commit ddc5f8d

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

src/mux_spop.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,7 @@ static int spop_conn_send_disconnect(struct spop_conn *spop_conn)
15551555
spop_set_frame_size(outbuf.area, outbuf.data - 4);
15561556
b_add(mbuf, outbuf.data);
15571557
spop_conn->flags |= SPOP_CF_DISCO_SENT;
1558+
spop_conn->state = SPOP_CS_CLOSING;
15581559
ret = 1;
15591560

15601561
switch (spop_conn->errcode) {
@@ -1787,8 +1788,6 @@ static int spop_conn_handle_hello(struct spop_conn *spop_conn)
17871788
TRACE_LEAVE(SPOP_EV_RX_FRAME|SPOP_EV_RX_HELLO, spop_conn->conn);
17881789
return 1;
17891790
fail:
1790-
spop_conn->state = SPOP_CS_CLOSED;
1791-
TRACE_STATE("switching to CLOSED", SPOP_EV_RX_FRAME|SPOP_EV_RX_HELLO, spop_conn->conn);
17921791
TRACE_DEVEL("leaving on error", SPOP_EV_RX_FRAME|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
17931792
return 0;
17941793
}
@@ -1974,7 +1973,6 @@ static int spop_conn_handle_ack(struct spop_conn *spop_conn, struct spop_strm *s
19741973

19751974
sent = b_xfer(rxbuf, dbuf, flen);
19761975
BUG_ON(sent != flen);
1977-
/* b_del(&spop_conn->dbuf, sent); */
19781976
spop_conn->dfl -= sent;
19791977

19801978
end:
@@ -2062,27 +2060,34 @@ static void spop_process_demux(struct spop_conn *spop_conn)
20622060

20632061
TRACE_ENTER(SPOP_EV_SPOP_CONN_WAKE, spop_conn->conn);
20642062

2065-
if (spop_conn->state >= SPOP_CS_ERROR)
2063+
if (spop_conn->state == SPOP_CS_CLOSED)
20662064
goto out;
20672065

2068-
if (unlikely(spop_conn->state < SPOP_CS_RUNNING)) {
2066+
if (unlikely(spop_conn->state < SPOP_CS_RUNNING || spop_conn->state == SPOP_CS_CLOSING)) {
20692067
if (spop_conn->state == SPOP_CS_HA_HELLO) {
20702068
TRACE_STATE("waiting AGENT HELLO frame to be sent", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO, spop_conn->conn);
20712069
goto out;
20722070
}
2073-
if (spop_conn->state == SPOP_CS_AGENT_HELLO) {
2074-
/* ensure that what is pending is a valid AGENT HELLO frame. */
2075-
TRACE_STATE("receiving AGENT HELLO frame header", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR, spop_conn->conn);
2071+
else { /* AGENT_HELLO OR CLOSING */
2072+
/* ensure that what is pending is a valid AGENT HELLO/DISCONNECT frame. */
2073+
TRACE_STATE("receiving AGENT HELLO/DISCONNECT frame header", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR, spop_conn->conn);
20762074
if (!spop_get_frame_hdr(&spop_conn->dbuf, &hdr)) {
20772075
spop_conn->flags |= SPOP_CF_DEM_SHORT_READ;
20782076
TRACE_ERROR("header frame not available yet", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR, spop_conn->conn);
20792077
goto done;
20802078
}
20812079

2082-
if (hdr.sid || hdr.fid || hdr.type != SPOP_FRM_T_AGENT_HELLO || !(hdr.flags & SPOP_FRM_FL_FIN)) {
2080+
if (spop_conn->state == SPOP_CS_AGENT_HELLO && hdr.type != SPOP_FRM_T_AGENT_HELLO) {
2081+
spop_conn_error(spop_conn, SPOP_ERR_INVALID);
2082+
spop_conn->state = SPOP_CS_CLOSED;
2083+
TRACE_ERROR("unexpected frame type (AGENT HELLO expected)", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
2084+
TRACE_STATE("switching to CLOSED", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
2085+
goto done;
2086+
}
2087+
if ((hdr.type == SPOP_FRM_T_AGENT_HELLO || hdr.type == SPOP_FRM_T_AGENT_DISCON) && (hdr.sid || hdr.fid || !(hdr.flags & SPOP_FRM_FL_FIN))) {
20832088
spop_conn_error(spop_conn, SPOP_ERR_INVALID);
20842089
spop_conn->state = SPOP_CS_CLOSED;
2085-
TRACE_ERROR("unexpected frame type or flags", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
2090+
TRACE_ERROR("unexpected frame meta-data", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
20862091
TRACE_STATE("switching to CLOSED", SPOP_EV_RX_FRAME|SPOP_EV_RX_FHDR|SPOP_EV_RX_HELLO|SPOP_EV_SPOP_CONN_ERR, spop_conn->conn);
20872092
goto done;
20882093
}
@@ -2109,7 +2114,7 @@ static void spop_process_demux(struct spop_conn *spop_conn)
21092114
break;
21102115
}
21112116

2112-
if (spop_conn->state >= SPOP_CS_ERROR) {
2117+
if (spop_conn->state == SPOP_CS_CLOSED) {
21132118
TRACE_STATE("end of connection reported", SPOP_EV_RX_FRAME|SPOP_EV_RX_EOI, spop_conn->conn);
21142119
break;
21152120
}

0 commit comments

Comments
 (0)