mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 17:35: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
|
relay can use it: the client's fiber gave up its stack. The next read
|
||||||
makes it again. */
|
makes it again. */
|
||||||
static void cbbufdrop(struct cbmap *m, int side){
|
static void cbbufdrop(struct cbmap *m, int side){
|
||||||
struct clientparam *param = m->param;
|
if(m->abandoned) bufdrop(m->param, side? SERVER : CLIENT);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* what a way has buffered and in its pipe: none once it is not moving */
|
/* 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))
|
#define PARAMSTR(p, f, s) paramstr((p)->f, sizeof((p)->f), (const unsigned char *)(s))
|
||||||
void bufrelease(struct clientparam * param, DIRECTION which);
|
void bufrelease(struct clientparam * param, DIRECTION which);
|
||||||
int bufget(struct clientparam * param, DIRECTION which);
|
int bufget(struct clientparam * param, DIRECTION which);
|
||||||
|
void bufdrop(struct clientparam * param, DIRECTION which);
|
||||||
int bufalloc(struct clientparam * param);
|
int bufalloc(struct clientparam * param);
|
||||||
void buffree(struct clientparam * param);
|
void buffree(struct clientparam * param);
|
||||||
|
|
||||||
|
|||||||
@ -102,6 +102,20 @@ void buffree(struct clientparam * param){
|
|||||||
param->clibufdata = param->srvbufdata = NULL;
|
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
|
/* 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
|
connection's own buffer if a filter needed a bigger one. Does nothing
|
||||||
while anything is left unread. */
|
while anything is left unread. */
|
||||||
|
|||||||
@ -378,6 +378,12 @@ log("done send to client from buf");
|
|||||||
splicesrv = wantbufsrv = streaksrv = 0;
|
splicesrv = wantbufsrv = streaksrv = 0;
|
||||||
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
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
|
/* each direction goes through its pipe if spliced, through its
|
||||||
buffer otherwise; what was in the buffer before is sent first */
|
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
|
#ifdef WITHLOG
|
||||||
log("read from client to buf");
|
log("read from client to buf");
|
||||||
#endif
|
#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
|
/* no address: it would overwrite the client's with what a
|
||||||
stream socket gives, an empty one for a Unix socket */
|
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);
|
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
|
#ifdef WITHLOG
|
||||||
log("read from server to buf");
|
log("read from server to buf");
|
||||||
#endif
|
#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);
|
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) {
|
if(res <= 0) {
|
||||||
FROMSERVER = 0;
|
FROMSERVER = 0;
|
||||||
@ -1009,6 +1018,9 @@ log("timeout");
|
|||||||
|
|
||||||
CLEANRET:
|
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
|
#ifdef WITHSPLICE
|
||||||
/* empty pipes stay with the connection for its next mapping; one still
|
/* 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 */
|
holding data, left by an error or a timeout, cannot be used again */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user