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
|
#endif
|
||||||
struct clientparam *param = (struct clientparam *)p;
|
struct clientparam *param = (struct clientparam *)p;
|
||||||
|
|
||||||
do serveparam(param);
|
do {
|
||||||
while(poolpark(param));
|
/* 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);
|
freeworker(param);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -909,9 +909,10 @@ static void cbmapfinish(void *arg){
|
|||||||
int res = m->res, timeo = m->timeosec, usesplice = m->usesplice0;
|
int res = m->res, timeo = m->timeosec, usesplice = m->usesplice0;
|
||||||
|
|
||||||
free(m);
|
free(m);
|
||||||
/* the buffers given back while relayed are the child's again: without
|
/* the buffers given back while relayed are made again only to map on
|
||||||
them only the end is logged */
|
after a reload: the end has no use for them. Without them only the
|
||||||
if(bufalloc(param)){
|
end is logged */
|
||||||
|
if(res == -2 && bufalloc(param)){
|
||||||
param->res = (res == -2)? 21 : res;
|
param->res = (res == -2)? 21 : res;
|
||||||
param->maptail = NULL;
|
param->maptail = NULL;
|
||||||
dolog(param, 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;
|
unsigned lo, start, pos, hend = 0, tail = 0, rest, linelen;
|
||||||
int mark = -1, len;
|
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;
|
/* 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
|
a request marked earlier (handed over by httpsrv) is kept from the
|
||||||
mark, which moves with it */
|
mark, which moves with it */
|
||||||
@ -556,6 +557,29 @@ static void proxytail(struct clientparam *param, void *data){
|
|||||||
logurl(param, (char *)data, 0);
|
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) {
|
void * proxychild(struct clientparam* param) {
|
||||||
int res=0, i=0;
|
int res=0, i=0;
|
||||||
unsigned char* buf = NULL, *newbuf;
|
unsigned char* buf = NULL, *newbuf;
|
||||||
@ -1321,23 +1345,7 @@ for(;;){
|
|||||||
return (void *)param->redirectfunc;
|
return (void *)param->redirectfunc;
|
||||||
}
|
}
|
||||||
hdrfree(&buf, &bufown);
|
hdrfree(&buf, &bufown);
|
||||||
/* mapping its last thing, but in a request httpsrv hands over, whose
|
param->res = maplast(param, &req, &ftpbase, param->srv->timeouts[CONNECTION_L]);
|
||||||
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;
|
|
||||||
}
|
|
||||||
RETURN(param->res);
|
RETURN(param->res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1692,13 +1700,15 @@ for(;;){
|
|||||||
BODYSENT:
|
BODYSENT:
|
||||||
if(isconnect && res == 200 && param->operation){
|
if(isconnect && res == 200 && param->operation){
|
||||||
hdrfree(&buf, &bufown);
|
hdrfree(&buf, &bufown);
|
||||||
RETURN (mapsocket(param, param->srv->timeouts[CONNECTION_S]));
|
RETURN (maplast(param, &req, &ftpbase, param->srv->timeouts[CONNECTION_S]));
|
||||||
}
|
}
|
||||||
else if(isconnect){
|
else if(isconnect){
|
||||||
ckeepalive = keepalive = 1;
|
ckeepalive = keepalive = 1;
|
||||||
}
|
}
|
||||||
else if(!hascontent && !param->chunked) {
|
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;
|
contentlength64 = 0;
|
||||||
REQUESTEND:
|
REQUESTEND:
|
||||||
|
|||||||
@ -173,6 +173,8 @@ int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
|
|||||||
return (int)param->clibuf[param->clioffset++];
|
return (int)param->clibuf[param->clioffset++];
|
||||||
}
|
}
|
||||||
if(param->climark == -2) return EOF; /* nothing more until it is cleared */
|
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){
|
if(param->climark >= 0){
|
||||||
/* what was read since the mark stays, moved to the start */
|
/* what was read since the mark stays, moved to the start */
|
||||||
keep = param->cliinbuf - (unsigned)param->climark;
|
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
|
buffer, at the end of the stream, or when nothing comes in time; returns
|
||||||
how much is there, at most size. */
|
how much is there, at most size. */
|
||||||
unsigned long sockfillbuf(struct clientparam * param, DIRECTION which, unsigned long size, int timeosec){
|
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 *inbuf = which? ¶m->srvinbuf : ¶m->cliinbuf;
|
||||||
unsigned *offset = which? ¶m->srvoffset : ¶m->clioffset;
|
unsigned *offset = which? ¶m->srvoffset : ¶m->clioffset;
|
||||||
unsigned bufsize = which? param->srvbufsize : param->clibufsize;
|
unsigned bufsize = which? param->srvbufsize : param->clibufsize;
|
||||||
unsigned want;
|
unsigned want;
|
||||||
int len;
|
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){
|
if(*offset){
|
||||||
memmove(buf, buf + *offset, *inbuf - *offset);
|
memmove(buf, buf + *offset, *inbuf - *offset);
|
||||||
*inbuf -= *offset;
|
*inbuf -= *offset;
|
||||||
@ -232,6 +237,7 @@ int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
|
|||||||
return (int)param->srvbuf[param->srvoffset++];
|
return (int)param->srvbuf[param->srvoffset++];
|
||||||
}
|
}
|
||||||
bufrelease(param, SERVER);
|
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;
|
if ((len = sockrecvfrom(param, param->remsock, (struct sockaddr *)¶m->sinsr, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
|
||||||
param->srvinbuf = len;
|
param->srvinbuf = len;
|
||||||
param->srvoffset = 1;
|
param->srvoffset = 1;
|
||||||
|
|||||||
@ -1018,8 +1018,10 @@ log("timeout");
|
|||||||
|
|
||||||
CLEANRET:
|
CLEANRET:
|
||||||
|
|
||||||
/* what comes after a mapping finds the buffers there */
|
/* what comes after a mapping finds the buffers there; after the last
|
||||||
if(((!param->clibuf && bufget(param, CLIENT)) || (!param->srvbuf && bufget(param, SERVER))) && !res) res = 21;
|
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
|
#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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user