mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-05 09:25:49 +08:00
Event loops: CONNECT of the HTTP proxy and SOCKS, pop3p, imapp, smtpp
give up their fiber while relayed The children for which mapping is their last thing set their tail too: - socks, for CONNECT: its log line; the request's buffer is freed before mapping, nothing needing it after; - proxy, for CONNECT: the status page its end sends for the result where one is, now proxystatus() for both, and the log line of its request, a copy of which is the tail's. Not in a request httpsrv hands over, whose end is httpsrv's; - pop3p, imapp (with a copy of its tag), smtpp (its command freed before mapping): the log line and the error reply their ends send. A tail may wait now, sending to the client: once mapping is over the end of a client whose fiber gave up its stack runs on a fiber taken again for it, which, after a reload, has sockmap() go on with the mapping first. Only with no stack to be had is it ended there, logged with no tail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
973fc89d58
commit
90d798eaaf
19
src/imapp.c
19
src/imapp.c
@ -25,6 +25,24 @@
|
||||
#define NOSTARTTLS param->srv->nostarttls
|
||||
#endif
|
||||
|
||||
/* as the end below, once mapping is over: data is the tag */
|
||||
static void imapptail(struct clientparam *param, void *data){
|
||||
unsigned char buf[320];
|
||||
char *tag = (char *)data;
|
||||
|
||||
if(*param->hostname&&*param->extusername) {
|
||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==143)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
||||
dolog(param, buf);
|
||||
}
|
||||
else dolog(param, NULL);
|
||||
if(param->clisock != INVALID_SOCKET) {
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 691 && param->res <700)) {
|
||||
sprintf((char *)buf, "%.60s NO proxy error\r\n", (tag && *tag)? tag : "*");
|
||||
socksend(param, param->clisock, buf, (int)strlen((char *)buf),param->srv->timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void * imappchild(struct clientparam* param) {
|
||||
int i=0, res, method=CL_LOGINCMD, caps=0;
|
||||
unsigned char buf[2048];
|
||||
@ -224,6 +242,7 @@ void * imappchild(struct clientparam* param) {
|
||||
}
|
||||
param->statscli64 += (uint64_t)(strlen((char *)tag) + strlen((char *)param->extusername) + strlen((char *)pb) + 11);
|
||||
param->nwrites++;
|
||||
if((param->maptaildata = strdup((char *)tag))) param->maptail = imapptail;
|
||||
RETURN (mapsocket(param, 180));
|
||||
CLEANRET:
|
||||
|
||||
|
||||
@ -848,51 +848,51 @@ static void cbmapidle(struct loop *l, struct looptimer *t){
|
||||
cbmapdone(m);
|
||||
}
|
||||
|
||||
/* What the child of the client does once mapping is over, as its end and
|
||||
that of its fiber would: the result, its tail, the connection released
|
||||
and freed. */
|
||||
static void cbmapfinish(struct clientparam *param, int res){
|
||||
/* The end of a client whose fiber gave up its stack while it was relayed,
|
||||
on a fiber again, which the child's end (maptail) may wait on: after a
|
||||
reload sockmap() goes on with the mapping first. Then what the child and
|
||||
its fiber would do: the result, the tail, the connection released and
|
||||
freed. */
|
||||
static void cbmapfinish(void *arg){
|
||||
struct cbmap *m = (struct cbmap *)arg;
|
||||
struct clientparam *param = m->param;
|
||||
int res = m->res, timeo = m->timeosec, usesplice = m->usesplice0;
|
||||
|
||||
free(m);
|
||||
if(res == -2) res = sockmap(param, timeo, usesplice);
|
||||
param->res = res;
|
||||
if(param->maptail) param->maptail(param, param->maptaildata);
|
||||
releaseparam(param);
|
||||
freeparam(param);
|
||||
}
|
||||
|
||||
/* a fiber for the client again: sockmap() goes on with the mapping after
|
||||
a reload, then the child's end */
|
||||
static void cbmapresume(void *arg){
|
||||
struct cbmap *m = (struct cbmap *)arg;
|
||||
struct clientparam *param = m->param;
|
||||
int timeo = m->timeosec, usesplice = m->usesplice0;
|
||||
|
||||
free(m);
|
||||
cbmapfinish(param, sockmap(param, timeo, usesplice));
|
||||
}
|
||||
|
||||
/* The mapping is over: its fiber goes on, or, with none, the loop ends it
|
||||
as the child would, or gives it a fiber again for sockmap() to take it
|
||||
over after a reload. m is freed. */
|
||||
/* The mapping is over: its fiber goes on, which frees m, or, with none, a
|
||||
fiber is taken to end the client as the child would. */
|
||||
static void cbmapdone(struct cbmap *m){
|
||||
struct clientparam *param = m->param;
|
||||
struct fiberslot *fs;
|
||||
int res;
|
||||
|
||||
if(!m->abandoned){
|
||||
/* the fiber frees m */
|
||||
fiberrun(m->lp, m->f);
|
||||
return;
|
||||
}
|
||||
if(m->res == -2){
|
||||
if((fs = fibertake(m->lp, param->stacksize))){
|
||||
fiberstart(&fs->f, cbmapresume, m);
|
||||
fiberrun(m->lp, &fs->f);
|
||||
return;
|
||||
}
|
||||
m->res = 21;
|
||||
if((fs = fibertake(m->lp, m->param->stacksize))){
|
||||
fiberstart(&fs->f, cbmapfinish, m);
|
||||
fiberrun(m->lp, &fs->f);
|
||||
return;
|
||||
}
|
||||
/* no stack for it: as it can be, here, with no waits left to its
|
||||
tail, a reload taken for its end */
|
||||
if(m->res == -2) m->res = 21;
|
||||
{
|
||||
struct clientparam *param = m->param;
|
||||
|
||||
param->res = m->res;
|
||||
free(m);
|
||||
param->maptail = NULL;
|
||||
dolog(param, NULL);
|
||||
releaseparam(param);
|
||||
freeparam(param);
|
||||
}
|
||||
res = m->res;
|
||||
free(m);
|
||||
cbmapfinish(param, res);
|
||||
}
|
||||
|
||||
/* sockmapcbfunc: sockmap() of a fiber, as callbacks, its result; -2 for
|
||||
|
||||
15
src/pop3p.c
15
src/pop3p.c
@ -18,6 +18,20 @@
|
||||
#define NOSTARTTLS param->srv->nostarttls
|
||||
#endif
|
||||
|
||||
/* as the end below, once mapping is over */
|
||||
static void pop3ptail(struct clientparam *param, void *data){
|
||||
unsigned char buf[320];
|
||||
|
||||
if(*param->hostname&&*param->extusername) {
|
||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr)));
|
||||
dolog(param, buf);
|
||||
}
|
||||
else dolog(param, NULL);
|
||||
if(param->clisock != INVALID_SOCKET) {
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"-ERR\r\n", 6,param->srv->timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
|
||||
void * pop3pchild(struct clientparam* param) {
|
||||
int i=0, res;
|
||||
unsigned char buf[320];
|
||||
@ -65,6 +79,7 @@ void * pop3pchild(struct clientparam* param) {
|
||||
{RETURN(623);}
|
||||
param->statscli64 += (uint64_t)(strlen((char *)param->extusername) + 7);
|
||||
param->nwrites++;
|
||||
param->maptail = pop3ptail;
|
||||
RETURN (mapsocket(param, 180));
|
||||
CLEANRET:
|
||||
|
||||
|
||||
81
src/proxy.c
81
src/proxy.c
@ -493,6 +493,50 @@ void file2url(unsigned char *sb, unsigned char *buf, unsigned bufsize, int * inb
|
||||
}
|
||||
|
||||
|
||||
/* The status page the client is sent for the result in param->res, where
|
||||
one is: the rest of a request whose headers were not all read is read
|
||||
first. */
|
||||
static void proxystatus(struct clientparam *param, int hdrsdone, char *ftpbuf, int inftpbuf){
|
||||
int stidx = -1, i;
|
||||
int r = param->res;
|
||||
|
||||
if(r == 555 || !r || param->clisock == INVALID_SOCKET || !(r < 90 || r >=800 || r == 100 ||(r > 500 && r< 800)))
|
||||
return;
|
||||
if(!hdrsdone && ((r >= 509 && r < 517) || r > 900)) {
|
||||
unsigned char rest[256];
|
||||
int atstart = 1;
|
||||
|
||||
while((i = sockgetlinebuf(param, CLIENT, rest, sizeof(rest) - 1, '\n', param->srv->timeouts[STRING_S])) > 0){
|
||||
if(atstart && i <= 2 && rest[i-1] == '\n') break;
|
||||
atstart = (rest[i-1] == '\n');
|
||||
}
|
||||
}
|
||||
if(r == 10) stidx = 2;
|
||||
else if(r == 700 || r == 701) stidx = 16;
|
||||
else if(r == 100 || (r > 10 && r < 20) || (r > 701 && r <= 705)) stidx = 1;
|
||||
else if(r >= 20 && r < 30) stidx = 6;
|
||||
else if(r >= 30 && r < 80) stidx = 5;
|
||||
else if(r == 1 || (!param->srv->needuser && r < 10)) stidx = 11;
|
||||
else if(r < 10) stidx = 7;
|
||||
else if(r == 999) stidx = 4;
|
||||
else if(r == 519) stidx = 3;
|
||||
else if(r == 517) stidx = 15;
|
||||
else if(r == 780) stidx = 10;
|
||||
else if(r >= 511 && r <= 516) stidx = 0;
|
||||
|
||||
if(stidx >= 0) {
|
||||
send_st(param, stidx);
|
||||
if((r == 700 || r == 701) && ftpbuf) socksend(param, param->clisock, (unsigned char *)ftpbuf, inftpbuf, param->srv->timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
|
||||
/* the end of a CONNECT, as proxychild()'s, once mapping is over: data is
|
||||
its request line */
|
||||
static void proxytail(struct clientparam *param, void *data){
|
||||
proxystatus(param, 1, NULL, 0);
|
||||
logurl(param, (char *)data, 0);
|
||||
}
|
||||
|
||||
void * proxychild(struct clientparam* param) {
|
||||
int res=0, i=0;
|
||||
unsigned char* buf = NULL, *newbuf;
|
||||
@ -1250,6 +1294,10 @@ 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 */
|
||||
if(!param->onerequest && (param->maptaildata = req? (void *)strdup((char *)req) : NULL))
|
||||
param->maptail = proxytail;
|
||||
param->res = mapsocket(param, param->srv->timeouts[CONNECTION_L]);
|
||||
RETURN(param->res);
|
||||
}
|
||||
@ -1617,38 +1665,7 @@ REQUESTEND:
|
||||
|
||||
CLEANRET:
|
||||
|
||||
if(param->res != 555 && param->res && param->clisock != INVALID_SOCKET && (param->res < 90 || param->res >=800 || param->res == 100 ||(param->res > 500 && param->res< 800))) {
|
||||
int stidx = -1;
|
||||
int r = param->res;
|
||||
|
||||
/* the rest of a request whose headers were not all read */
|
||||
if(!hdrsdone && ((r >= 509 && r < 517) || r > 900)) {
|
||||
unsigned char rest[256];
|
||||
int atstart = 1;
|
||||
|
||||
while((i = sockgetlinebuf(param, CLIENT, rest, sizeof(rest) - 1, '\n', param->srv->timeouts[STRING_S])) > 0){
|
||||
if(atstart && i <= 2 && rest[i-1] == '\n') break;
|
||||
atstart = (rest[i-1] == '\n');
|
||||
}
|
||||
}
|
||||
if(r == 10) stidx = 2;
|
||||
else if(r == 700 || r == 701) stidx = 16;
|
||||
else if(r == 100 || (r > 10 && r < 20) || (r > 701 && r <= 705)) stidx = 1;
|
||||
else if(r >= 20 && r < 30) stidx = 6;
|
||||
else if(r >= 30 && r < 80) stidx = 5;
|
||||
else if(r == 1 || (!param->srv->needuser && r < 10)) stidx = 11;
|
||||
else if(r < 10) stidx = 7;
|
||||
else if(r == 999) stidx = 4;
|
||||
else if(r == 519) stidx = 3;
|
||||
else if(r == 517) stidx = 15;
|
||||
else if(r == 780) stidx = 10;
|
||||
else if(r >= 511 && r <= 516) stidx = 0;
|
||||
|
||||
if(stidx >= 0) {
|
||||
send_st(param, stidx);
|
||||
if(r == 700 || r == 701) socksend(param, param->clisock, (unsigned char *)ftpbuf, inftpbuf, param->srv->timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
proxystatus(param, hdrsdone, ftpbuf, inftpbuf);
|
||||
logurl(param, (char *)req, ftp);
|
||||
freeptr(&req); hdrfree(&buf, &bufown); freeptr(&ftpbase);
|
||||
return (NULL);
|
||||
|
||||
23
src/smtpp.c
23
src/smtpp.c
@ -114,6 +114,25 @@ int readdata (struct clientparam* param) {
|
||||
}
|
||||
|
||||
|
||||
/* as the end below, once mapping is over */
|
||||
static void smtpptail(struct clientparam *param, void *data){
|
||||
unsigned char buf[320];
|
||||
|
||||
if(*param->hostname&&*param->extusername) {
|
||||
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==587?0:':',ntohs(*SAPORT(¶m->sinsr)));
|
||||
dolog(param, buf);
|
||||
}
|
||||
else dolog(param, NULL);
|
||||
if(param->clisock != INVALID_SOCKET) {
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"571 \r\n", 6,param->srv->timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
|
||||
/* mapping the last thing: what is not needed any more freed, the end left
|
||||
to the tail */
|
||||
#define SMTPLASTMAP { if(command){ free(command); command = NULL; } param->maptail = smtpptail; \
|
||||
RETURN (mapsocket(param, 180)); }
|
||||
|
||||
void * smtppchild(struct clientparam* param) {
|
||||
int i=0, res;
|
||||
unsigned char buf[320];
|
||||
@ -309,7 +328,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
|
||||
if(param->nhdrfilterscli || param->nhdrfilterssrv || param->ndatfilterscli || param->ndatfilterssrv){
|
||||
do {
|
||||
if(res == 22) RETURN (mapsocket(param, 180));
|
||||
if(res == 22) SMTPLASTMAP
|
||||
if(res != 2 && (res = readreply(param)) <= 0) break;
|
||||
if(res == 221) RETURN(0);
|
||||
if(res == 354) res = readdata(param);
|
||||
@ -323,7 +342,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
|
||||
#endif
|
||||
|
||||
RETURN (mapsocket(param, 180));
|
||||
SMTPLASTMAP
|
||||
|
||||
CLEANRET:
|
||||
|
||||
|
||||
15
src/socks.c
15
src/socks.c
@ -30,6 +30,14 @@ static void printcommand(unsigned char * buf, int command, struct clientparam *p
|
||||
|
||||
}
|
||||
|
||||
/* the end of a CONNECT, as below, once mapping is over */
|
||||
static void sockstail(struct clientparam *param, void *data){
|
||||
unsigned char logline[340];
|
||||
|
||||
printcommand(logline, 1, param);
|
||||
dolog(param, logline);
|
||||
}
|
||||
|
||||
void * sockschild(struct clientparam* param) {
|
||||
int res;
|
||||
unsigned i=0;
|
||||
@ -347,6 +355,13 @@ fflush(stderr);
|
||||
if(buf != param->tmpbuf) free(buf);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
/* the request is not needed any more: its end is
|
||||
the log line, which mapping may leave to a loop */
|
||||
if(buf != param->tmpbuf){
|
||||
free(buf);
|
||||
buf = param->tmpbuf;
|
||||
}
|
||||
param->maptail = sockstail;
|
||||
param->res = mapsocket(param, param->srv->timeouts[CONNECTION_L]);
|
||||
break;
|
||||
case 2:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user