mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 09:25:49 +08:00
Relays: no buffers made again after a connection's last mapping
sockmap() made both buffers again as it returned, for whatever came after it, and the callbacks before the end: after the last mapping there is only the end, the log line and a refusal sent from a buffer of its own, with no use for them. They are made again only for a mapping that is not the last, and for a fiber mapping on after a reload; the functions reading a side's buffer make it if it is not there, and a worker taken from the pool for its next connection gets its own again. proxy.c's other last mappings, a CONNECT through a parent and an answer ending as the server closes, are marked so too (maplast(), proxytail), as the CONNECT of its own was: their end, and with callbacks the fiber, is the loop's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
f991edbb3a
commit
f2cc447f73
@ -240,8 +240,15 @@ void * threadfunc (void *p) {
|
||||
#endif
|
||||
struct clientparam *param = (struct clientparam *)p;
|
||||
|
||||
do serveparam(param);
|
||||
while(poolpark(param));
|
||||
do {
|
||||
/* a worker taken from the pool: its buffers may have been let go on
|
||||
its last connection's last mapping */
|
||||
if(bufalloc(param)){
|
||||
param->res = 21;
|
||||
releaseparam(param);
|
||||
}
|
||||
else serveparam(param);
|
||||
} while(poolpark(param));
|
||||
freeworker(param);
|
||||
#ifdef _WIN32
|
||||
return 0;
|
||||
|
||||
@ -909,9 +909,10 @@ static void cbmapfinish(void *arg){
|
||||
int res = m->res, timeo = m->timeosec, usesplice = m->usesplice0;
|
||||
|
||||
free(m);
|
||||
/* the buffers given back while relayed are the child's again: without
|
||||
them only the end is logged */
|
||||
if(bufalloc(param)){
|
||||
/* the buffers given back while relayed are made again only to map on
|
||||
after a reload: the end has no use for them. Without them only the
|
||||
end is logged */
|
||||
if(res == -2 && bufalloc(param)){
|
||||
param->res = (res == -2)? 21 : res;
|
||||
param->maptail = NULL;
|
||||
dolog(param, NULL);
|
||||
|
||||
48
src/proxy.c
48
src/proxy.c
@ -252,6 +252,7 @@ static int hdrread(struct clientparam *param, DIRECTION which, unsigned front, u
|
||||
unsigned lo, start, pos, hend = 0, tail = 0, rest, linelen;
|
||||
int mark = -1, len;
|
||||
|
||||
if(!*bufp && bufget(param, which)) return -2;
|
||||
/* what was read and not taken yet moves to one byte into the buffer;
|
||||
a request marked earlier (handed over by httpsrv) is kept from the
|
||||
mark, which moves with it */
|
||||
@ -556,6 +557,29 @@ static void proxytail(struct clientparam *param, void *data){
|
||||
logurl(param, (char *)data, 0);
|
||||
}
|
||||
|
||||
/* The connection's last mapping. Its end, the status and the log line, can
|
||||
be a loop's (proxytail), the request line handed over for them, but for
|
||||
a request httpsrv hands over, whose end is httpsrv's: the rest of the end
|
||||
may then never come back here. What it would free is freed now, and the
|
||||
request line is back if mapping returns. */
|
||||
static int maplast(struct clientparam *param, unsigned char **req, unsigned char **ftpbase, int timeo){
|
||||
int res;
|
||||
|
||||
if(!param->onerequest && *req){
|
||||
freeptr(ftpbase);
|
||||
param->maptaildata = *req;
|
||||
*req = NULL;
|
||||
param->maptail = proxytail;
|
||||
}
|
||||
res = mapsocket(param, timeo);
|
||||
if(param->maptail == proxytail){
|
||||
*req = param->maptaildata;
|
||||
param->maptaildata = NULL;
|
||||
param->maptail = NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void * proxychild(struct clientparam* param) {
|
||||
int res=0, i=0;
|
||||
unsigned char* buf = NULL, *newbuf;
|
||||
@ -1321,23 +1345,7 @@ for(;;){
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
hdrfree(&buf, &bufown);
|
||||
/* mapping its last thing, but in a request httpsrv hands over, whose
|
||||
end is httpsrv's: the rest of the end can be a loop's, which this
|
||||
function's own may then never reach. What it would free is freed
|
||||
now, and the request line is the tail's, back here if mapping
|
||||
returns. */
|
||||
if(!param->onerequest && req){
|
||||
freeptr(&ftpbase);
|
||||
param->maptaildata = req;
|
||||
req = NULL;
|
||||
param->maptail = proxytail;
|
||||
}
|
||||
param->res = mapsocket(param, param->srv->timeouts[CONNECTION_L]);
|
||||
if(param->maptail == proxytail){
|
||||
req = param->maptaildata;
|
||||
param->maptaildata = NULL;
|
||||
param->maptail = NULL;
|
||||
}
|
||||
param->res = maplast(param, &req, &ftpbase, param->srv->timeouts[CONNECTION_L]);
|
||||
RETURN(param->res);
|
||||
}
|
||||
|
||||
@ -1692,13 +1700,15 @@ for(;;){
|
||||
BODYSENT:
|
||||
if(isconnect && res == 200 && param->operation){
|
||||
hdrfree(&buf, &bufown);
|
||||
RETURN (mapsocket(param, param->srv->timeouts[CONNECTION_S]));
|
||||
RETURN (maplast(param, &req, &ftpbase, param->srv->timeouts[CONNECTION_S]));
|
||||
}
|
||||
else if(isconnect){
|
||||
ckeepalive = keepalive = 1;
|
||||
}
|
||||
else if(!hascontent && !param->chunked) {
|
||||
RETURN(mapsocket(param, param->srv->timeouts[CONNECTION_S]));
|
||||
/* the answer ends as the server's side does: the connection with it */
|
||||
hdrfree(&buf, &bufown);
|
||||
RETURN(maplast(param, &req, &ftpbase, param->srv->timeouts[CONNECTION_S]));
|
||||
}
|
||||
contentlength64 = 0;
|
||||
REQUESTEND:
|
||||
|
||||
@ -173,6 +173,8 @@ int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
||||
return (int)param->clibuf[param->clioffset++];
|
||||
}
|
||||
if(param->climark == -2) return EOF; /* nothing more until it is cleared */
|
||||
/* let go on a connection's last mapping */
|
||||
if(!param->clibuf && bufget(param, CLIENT)) return EOF;
|
||||
if(param->climark >= 0){
|
||||
/* what was read since the mark stays, moved to the start */
|
||||
keep = param->cliinbuf - (unsigned)param->climark;
|
||||
@ -197,13 +199,16 @@ int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
||||
buffer, at the end of the stream, or when nothing comes in time; returns
|
||||
how much is there, at most size. */
|
||||
unsigned long sockfillbuf(struct clientparam * param, DIRECTION which, unsigned long size, int timeosec){
|
||||
unsigned char *buf = which? param->srvbuf : param->clibuf;
|
||||
unsigned char *buf;
|
||||
unsigned *inbuf = which? ¶m->srvinbuf : ¶m->cliinbuf;
|
||||
unsigned *offset = which? ¶m->srvoffset : ¶m->clioffset;
|
||||
unsigned bufsize = which? param->srvbufsize : param->clibufsize;
|
||||
unsigned want;
|
||||
int len;
|
||||
|
||||
/* let go on a connection's last mapping */
|
||||
if(!(which? param->srvbuf : param->clibuf) && bufget(param, which)) return 0;
|
||||
buf = which? param->srvbuf : param->clibuf;
|
||||
if(*offset){
|
||||
memmove(buf, buf + *offset, *inbuf - *offset);
|
||||
*inbuf -= *offset;
|
||||
@ -232,6 +237,7 @@ int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
|
||||
return (int)param->srvbuf[param->srvoffset++];
|
||||
}
|
||||
bufrelease(param, SERVER);
|
||||
if(!param->srvbuf && bufget(param, SERVER)) return EOF;
|
||||
if ((len = sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
|
||||
param->srvinbuf = len;
|
||||
param->srvoffset = 1;
|
||||
|
||||
@ -1018,8 +1018,10 @@ 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;
|
||||
/* what comes after a mapping finds the buffers there; after the last
|
||||
one only its end, which has no use for them */
|
||||
if(!param->maptail &&
|
||||
((!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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user