mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 09:25:49 +08:00
Relays: buffers let go while spliced on a connection's last mapping
sockmap() of fibers and threads kept both buffers for as long as it mapped, even with a direction spliced. On a connection's last mapping (maptail set), as the callbacks already do, a direction spliced lets its empty buffer go: bufdrop(), shared with the callbacks now. It is made again before a read into it, back to copying or draining what TLS held, and both are there again once sockmap() returns, for whatever comes after it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1201031404
commit
cbc7245925
@ -497,13 +497,7 @@ static void cbbuf(struct clientparam *param, int side, unsigned char **buf, unsi
|
||||
relay can use it: the client's fiber gave up its stack. The next read
|
||||
makes it again. */
|
||||
static void cbbufdrop(struct cbmap *m, int side){
|
||||
struct clientparam *param = m->param;
|
||||
unsigned char **own = side? ¶m->srvbufdata : ¶m->clibufdata;
|
||||
unsigned char **buf = side? ¶m->srvbuf : ¶m->clibuf;
|
||||
|
||||
if(!m->abandoned || !*own || *buf != *own || (side? param->srvinbuf : param->cliinbuf)) return;
|
||||
free(*own);
|
||||
*own = *buf = NULL;
|
||||
if(m->abandoned) bufdrop(m->param, side? SERVER : CLIENT);
|
||||
}
|
||||
|
||||
/* what a way has buffered and in its pipe: none once it is not moving */
|
||||
|
||||
@ -361,6 +361,7 @@ int paramstr(unsigned char *field, size_t size, const unsigned char *s);
|
||||
#define PARAMSTR(p, f, s) paramstr((p)->f, sizeof((p)->f), (const unsigned char *)(s))
|
||||
void bufrelease(struct clientparam * param, DIRECTION which);
|
||||
int bufget(struct clientparam * param, DIRECTION which);
|
||||
void bufdrop(struct clientparam * param, DIRECTION which);
|
||||
int bufalloc(struct clientparam * param);
|
||||
void buffree(struct clientparam * param);
|
||||
|
||||
|
||||
@ -102,6 +102,20 @@ void buffree(struct clientparam * param){
|
||||
param->clibufdata = param->srvbufdata = NULL;
|
||||
}
|
||||
|
||||
/* An empty own buffer let go, while the connection's last mapping has
|
||||
no use for it, its direction spliced; bufget() makes it again. */
|
||||
void bufdrop(struct clientparam * param, DIRECTION which){
|
||||
unsigned char **own = which? ¶m->srvbufdata : ¶m->clibufdata;
|
||||
unsigned char **buf = which? ¶m->srvbuf : ¶m->clibuf;
|
||||
unsigned *in = which? ¶m->srvinbuf : ¶m->cliinbuf;
|
||||
unsigned *off = which? ¶m->srvoffset : ¶m->clioffset;
|
||||
|
||||
if(!*own || *buf != *own || *in != *off) return;
|
||||
free(*own);
|
||||
*own = *buf = NULL;
|
||||
*in = *off = 0;
|
||||
}
|
||||
|
||||
/* Starts an empty buffer over from its beginning, and goes back to the
|
||||
connection's own buffer if a filter needed a bigger one. Does nothing
|
||||
while anything is left unread. */
|
||||
|
||||
@ -378,6 +378,12 @@ log("done send to client from buf");
|
||||
splicesrv = wantbufsrv = streaksrv = 0;
|
||||
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
||||
}
|
||||
/* the connection's last mapping: a direction spliced has no use for
|
||||
its buffer while it is empty */
|
||||
if(param->maptail){
|
||||
if(splicecli && !wantbufcli && !draincli && !inclientbuf) bufdrop(param, CLIENT);
|
||||
if(splicesrv && !wantbufsrv && !drainsrv && !inserverbuf) bufdrop(param, SERVER);
|
||||
}
|
||||
{
|
||||
/* each direction goes through its pipe if spliced, through its
|
||||
buffer otherwise; what was in the buffer before is sent first */
|
||||
@ -597,6 +603,8 @@ log("done read from server to pipe\n");
|
||||
#ifdef WITHLOG
|
||||
log("read from client to buf");
|
||||
#endif
|
||||
/* let go while spliced: made again */
|
||||
if(!param->clibuf && bufget(param, CLIENT)) RETURN(21);
|
||||
/* no address: it would overwrite the client's with what a
|
||||
stream socket gives, an empty one for a Unix socket */
|
||||
res = param->srv->so._recvfrom(param->sostate, param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)CLIROOM - param->cliinbuf, fromclient-inclientbuf), 0, NULL, NULL);
|
||||
@ -654,6 +662,7 @@ log("done read from client to buf");
|
||||
#ifdef WITHLOG
|
||||
log("read from server to buf");
|
||||
#endif
|
||||
if(!param->srvbuf && bufget(param, SERVER)) RETURN(21);
|
||||
res = param->srv->so._recvfrom(param->sostate, param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)SRVROOM - param->srvinbuf, fromserver-inserverbuf), 0, NULL, NULL);
|
||||
if(res <= 0) {
|
||||
FROMSERVER = 0;
|
||||
@ -1009,6 +1018,9 @@ log("timeout");
|
||||
|
||||
CLEANRET:
|
||||
|
||||
/* what comes after a mapping finds the buffers there */
|
||||
if(((!param->clibuf && bufget(param, CLIENT)) || (!param->srvbuf && bufget(param, SERVER))) && !res) res = 21;
|
||||
|
||||
#ifdef WITHSPLICE
|
||||
/* empty pipes stay with the connection for its next mapping; one still
|
||||
holding data, left by an error or a timeout, cannot be used again */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user