Clean up UDP code

This commit is contained in:
Vladimir Dubrovin 2026-04-30 11:32:12 +03:00
parent b1ac46da79
commit a3fb7aff07
5 changed files with 102 additions and 64 deletions

View File

@ -514,7 +514,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
_3proxy_mutex_init(&rad_mutex); _3proxy_mutex_init(&rad_mutex);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
conf.threadinit = CreateSemaphore(NULL, 0, 1, NULL); conf.threadinit = CreateSemaphore(NULL, 1, 1, NULL);
if(!conf.threadinit){ if(!conf.threadinit){
fprintf(stderr, "semaphore init failed\n"); fprintf(stderr, "semaphore init failed\n");
return 1; return 1;

View File

@ -153,6 +153,7 @@ int start_proxy_thread(struct child * chp){
HANDLE h; HANDLE h;
#endif #endif
_3proxy_sem_lock(conf.threadinit);
#ifdef _WIN32 #ifdef _WIN32
#ifndef _WINCE #ifndef _WINCE
h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread); h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
@ -164,16 +165,11 @@ int start_proxy_thread(struct child * chp){
pthread_attr_init(&pa); pthread_attr_init(&pa);
pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768+conf.stacksize)); pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768+conf.stacksize));
pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
_3proxy_mutex_lock(&conf.threadinit);
pthread_create(&thread, &pa, startsrv, (void *)chp); pthread_create(&thread, &pa, startsrv, (void *)chp);
pthread_attr_destroy(&pa); pthread_attr_destroy(&pa);
#endif #endif
#ifdef _WIN32 _3proxy_sem_lock(conf.threadinit);
WaitForSingleObject(conf.threadinit, INFINITE); _3proxy_sem_unlock(conf.threadinit);
#else
_3proxy_mutex_lock(&conf.threadinit);
_3proxy_mutex_unlock(&conf.threadinit);
#endif
if(haveerror) { if(haveerror) {
fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":""); fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":"");
return(40); return(40);

View File

@ -238,6 +238,15 @@ unsigned char* en64 (const unsigned char *in, unsigned char *out, int inlen);
void tohex(unsigned char *in, unsigned char *out, int len); void tohex(unsigned char *in, unsigned char *out, int len);
void fromhex(unsigned char *in, unsigned char *out, int len); void fromhex(unsigned char *in, unsigned char *out, int len);
#ifdef _WIN32
extern HANDLE udpinit;
#define _3proxy_sem_lock(x) WaitForSingleObject(x, INFINITE)
#define _3proxy_sem_unlock(x) ReleaseSemaphore(x, 1, NULL)
#else
extern _3proxy_mutex_t udpinit;
#define _3proxy_sem_lock(x) pthread_mutex_lock(&x)
#define _3proxy_sem_unlock(x) pthread_mutex_unlock(&x)
#endif
int ftplogin(struct clientparam *param, char *buf, int *inbuf); int ftplogin(struct clientparam *param, char *buf, int *inbuf);

View File

@ -115,16 +115,6 @@ void * threadfunc (void *p) {
} }
#undef param #undef param
int pushthreadinit(){
#ifdef _WIN32
return ReleaseSemaphore(conf.threadinit, 1, NULL) ? 1 : 0;
#else
_3proxy_mutex_unlock(&conf.threadinit);
return 1;
#endif
}
struct socketoptions sockopts[] = { struct socketoptions sockopts[] = {
#ifdef TCP_NODELAY #ifdef TCP_NODELAY
{TCP_NODELAY, "TCP_NODELAY"}, {TCP_NODELAY, "TCP_NODELAY"},
@ -262,7 +252,7 @@ int MODULEMAINFUNC (int argc, char** argv){
char *hostname=NULL; char *hostname=NULL;
int opt = 1, isudp = 0, iscbl = 0, iscbc = 0; int opt = 1, isudp = 0, iscbl = 0, iscbc = 0;
#ifndef NOUDPMAIN #ifndef NOUDPMAIN
unsigned char udpbuf[UDPBUFSIZE]; unsigned char *udpbuf = NULL;
int udplen = 0; int udplen = 0;
#endif #endif
unsigned char *cbc_string = NULL, *cbl_string = NULL; unsigned char *cbc_string = NULL, *cbl_string = NULL;
@ -353,6 +343,7 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef NOUDPMAIN #ifndef NOUDPMAIN
if(isudp) { if(isudp) {
if(!udp_table.ihashtable)inithashtable(&udp_table, 64, 256, 65536); if(!udp_table.ihashtable)inithashtable(&udp_table, 64, 256, 65536);
if(!(udpbuf = myalloc(UDPBUFSIZE))) return 21;
} }
#endif #endif
srv.service = defparam.service = childdef.service; srv.service = defparam.service = childdef.service;
@ -567,7 +558,7 @@ int MODULEMAINFUNC (int argc, char** argv){
if (error || i!=argc) { if (error || i!=argc) {
#ifndef STDMAIN #ifndef STDMAIN
haveerror = 1; haveerror = 1;
pushthreadinit(); _3proxy_sem_unlock(conf.threadinit);
#endif #endif
fprintf(stderr, "%s of %s\n" fprintf(stderr, "%s of %s\n"
"Usage: %s options\n" "Usage: %s options\n"
@ -599,7 +590,7 @@ int MODULEMAINFUNC (int argc, char** argv){
if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((uint16_t)atoi(argv[i])))==0 || (srv.targetport = htons((uint16_t)atoi(argv[i+2])))==0) { if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((uint16_t)atoi(argv[i])))==0 || (srv.targetport = htons((uint16_t)atoi(argv[i+2])))==0) {
#ifndef STDMAIN #ifndef STDMAIN
haveerror = 1; haveerror = 1;
pushthreadinit(); _3proxy_sem_unlock(conf.threadinit);
#endif #endif
fprintf(stderr, "%s of %s\n" fprintf(stderr, "%s of %s\n"
"Usage: %s options" "Usage: %s options"
@ -665,7 +656,7 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef STDMAIN #ifndef STDMAIN
copyfilter(conf.filters, &srv); copyfilter(conf.filters, &srv);
pushthreadinit(); _3proxy_sem_unlock(conf.threadinit);
#endif #endif
@ -937,19 +928,23 @@ int MODULEMAINFUNC (int argc, char** argv){
struct clientparam *toparam; struct clientparam *toparam;
udplen = sockrecvfrom(NULL, srv.srvsock, (struct sockaddr *)&defparam.sincr, udpbuf, UDPBUFSIZE, 0); udplen = sockrecvfrom(NULL, srv.srvsock, (struct sockaddr *)&defparam.sincr, udpbuf, UDPBUFSIZE, 0);
if(udplen <= 0) continue; if(udplen <= 0) continue;
_3proxy_mutex_lock(&srv.counter_mutex); _3proxy_sem_lock(udpinit);
if(hashresolv(&udp_table, &defparam, &toparam, NULL)) { if(hashresolv(&udp_table, &defparam, &toparam, NULL)) {
socksendto(toparam, toparam->remsock, (struct sockaddr *)&toparam->sinsr, udpbuf, udplen, 0); socksendto(toparam, toparam->remsock, (struct sockaddr *)&toparam->sinsr, udpbuf, udplen, 0);
_3proxy_sem_unlock(udpinit);
toparam->statscli64 += udplen; toparam->statscli64 += udplen;
toparam->nwrites++; toparam->nwrites++;
_3proxy_mutex_unlock(&srv.counter_mutex);
continue; continue;
} }
_3proxy_mutex_unlock(&srv.counter_mutex);
} }
#endif #endif
if(! (newparam = myalloc (sizeof(defparam)))){ if(! (newparam = myalloc (sizeof(defparam)))){
if(!isudp) srv.so._closesocket(srv.so.state, new_sock); if(!isudp) srv.so._closesocket(srv.so.state, new_sock);
#ifndef NOUDPMAIN
else {
_3proxy_sem_unlock(udpinit);
}
#endif
defparam.res = 21; defparam.res = 21;
if(!srv.silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed"); if(!srv.silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed");
usleep(SLEEPTIME); usleep(SLEEPTIME);
@ -962,36 +957,24 @@ int MODULEMAINFUNC (int argc, char** argv){
#ifndef STDMAIN #ifndef STDMAIN
if(makefilters(&srv, newparam) > CONTINUE){ if(makefilters(&srv, newparam) > CONTINUE){
freeparam(newparam); freeparam(newparam);
#ifndef NOUDPMAIN
if(isudp) {
_3proxy_sem_unlock(udpinit);
}
#endif
continue; continue;
} }
#endif #endif
#ifndef NOUDPMAIN #ifndef NOUDPMAIN
if(isudp) { if(isudp) {
int authres; if(!(newparam->srvbuf = myalloc(UDPBUFSIZE))){
freeparam(newparam);
if(parsehostname((char *)srv.target, newparam, ntohs(srv.targetport))) { freeparam(newparam); continue; } _3proxy_sem_unlock(udpinit);
#ifndef NOIPV6 continue;
memcpy(&newparam->sinsl, *SAFAMILY(&newparam->req) == AF_INET6 ? (struct sockaddr *)&srv.extsa6 : (struct sockaddr *)&srv.extsa, SASIZE(&newparam->req)); }
#else newparam->srvbufsize = UDPBUFSIZE;
memcpy(&newparam->sinsl, (struct sockaddr *)&srv.extsa, SASIZE(&newparam->req)); newparam->srvinbuf = udplen;
#endif memcpy(newparam->srvbuf, udpbuf, udplen);
*SAPORT(&newparam->sinsl) = 0;
newparam->remsock = srv.so._socket(srv.so.state, SASOCK(&newparam->sinsl), SOCK_DGRAM, IPPROTO_UDP);
if(newparam->remsock == INVALID_SOCKET) { freeparam(newparam); continue; }
if(srv.so._bind(srv.so.state, newparam->remsock, (struct sockaddr *)&newparam->sinsl, SASIZE(&newparam->sinsl))) { freeparam(newparam); continue; }
#ifdef _WIN32
{ unsigned long ul2 = 1; ioctlsocket(newparam->remsock, FIONBIO, &ul2); }
#else
fcntl(newparam->remsock, F_SETFL, O_NONBLOCK | fcntl(newparam->remsock, F_GETFL));
#endif
memcpy(&newparam->sinsr, &newparam->req, sizeof(newparam->req));
newparam->operation = UDPASSOC;
authres = (*srv.authfunc)(newparam);
if(authres) { freeparam(newparam); continue; }
if(!srv.singlepacket)hashadd(&udp_table, newparam, &newparam, MAX_COUNTER_TIME);
socksendto(newparam, newparam->remsock, (struct sockaddr *)&newparam->sinsr, udpbuf, udplen, 0);
newparam->statscli64 += udplen;
newparam->nwrites++;
} }
#endif #endif
newparam->prev = newparam->next = NULL; newparam->prev = newparam->next = NULL;
@ -1010,38 +993,37 @@ int MODULEMAINFUNC (int argc, char** argv){
#else #else
h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv.stacksize), (void *)threadfunc, (void *) newparam, 0, &thread); h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv.stacksize), (void *)threadfunc, (void *) newparam, 0, &thread);
#endif #endif
srv.childcount++;
if (h) { if (h) {
newparam->threadid = (uint64_t)thread;
CloseHandle(h); CloseHandle(h);
} }
else { else {
sprintf((char *)buf, "_beginthreadex(): %s", _strerror(NULL)); sprintf((char *)buf, "_beginthreadex(): %s", _strerror(NULL));
if(!srv.silent)dolog(&defparam, buf);
error = 1; error = 1;
} }
_3proxy_mutex_unlock(&srv.counter_mutex);
if(error) freeparam(newparam);
#else #else
error = pthread_create(&thread, &pa, threadfunc, (void *)newparam); if ((error = pthread_create(&thread, &pa, threadfunc, (void *)newparam))){
if(error){
sprintf((char *)buf, "pthread_create(): %s", strerror(error)); sprintf((char *)buf, "pthread_create(): %s", strerror(error));
}
#endif
if(error){
if(!srv.silent)dolog(&defparam, buf); if(!srv.silent)dolog(&defparam, buf);
if(newparam->prev) newparam->prev->next = newparam->next; if(newparam->prev) newparam->prev->next = newparam->next;
else srv.child = newparam->next; else srv.child = newparam->next;
if(newparam->next) newparam->next->prev = newparam->prev; if(newparam->next) newparam->next->prev = newparam->prev;
_3proxy_mutex_unlock(&srv.counter_mutex);
newparam->srv = NULL; newparam->srv = NULL;
#ifndef NOUDPMAIN
if(isudp){
_3proxy_sem_unlock(udpinit);
}
#endif
freeparam(newparam); freeparam(newparam);
} }
else { else {
srv.childcount++; srv.childcount++;
newparam->threadid = (uint64_t)thread; newparam->threadid = (uint64_t)thread;
_3proxy_mutex_unlock(&srv.counter_mutex);
} }
#endif _3proxy_mutex_unlock(&srv.counter_mutex);
memset(&defparam.sincl, 0, sizeof(defparam.sincl)); memset(&defparam.sincl, 0, sizeof(defparam.sincl));
memset(&defparam.sincr, 0, sizeof(defparam.sincr)); memset(&defparam.sincr, 0, sizeof(defparam.sincr));
} }
@ -1065,10 +1047,22 @@ int MODULEMAINFUNC (int argc, char** argv){
if(cbc_string)myfree(cbc_string); if(cbc_string)myfree(cbc_string);
if(cbl_string)myfree(cbl_string); if(cbl_string)myfree(cbl_string);
if(fp) fclose(fp); if(fp) fclose(fp);
#ifndef NOUDPMAIN
myfree(udpbuf);
#endif
return 0; return 0;
} }
#ifndef NOUDPMAIN
int udpinited = 0;
#ifdef _WIN32
HANDLE udpinit;
#else
_3proxy_mutex_t udpinit;
#endif
#endif
void srvinit(struct srvparam * srv, struct clientparam *param){ void srvinit(struct srvparam * srv, struct clientparam *param){
@ -1102,6 +1096,16 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET; param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
*SAFAMILY(&param->req) = *SAFAMILY(&param->sinsl) = *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->sincr) = *SAFAMILY(&param->sincl) = AF_INET; *SAFAMILY(&param->req) = *SAFAMILY(&param->sinsl) = *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->sincr) = *SAFAMILY(&param->sincl) = AF_INET;
_3proxy_mutex_init(&srv->counter_mutex); _3proxy_mutex_init(&srv->counter_mutex);
#ifndef NOUDPMAIN
if(!udpinited){
#ifdef _WIN32
udpinit = CreateSemaphore(NULL, 1, 1, NULL);
#else
_3proxy_mutex_init(&udpinit);
#endif
}
udpinited = 1;
#endif
srv->intsa = conf.intsa; srv->intsa = conf.intsa;
srv->extsa = conf.extsa; srv->extsa = conf.extsa;
#ifndef NOIPV6 #ifndef NOIPV6

View File

@ -31,13 +31,42 @@ static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash
struct hashtable udp_table = {udpparam2hash, udpparam2hash, sizeof(struct clientparam *), 8}; struct hashtable udp_table = {udpparam2hash, udpparam2hash, sizeof(struct clientparam *), 8};
void * udppmchild(struct clientparam* param) { void * udppmchild(struct clientparam* param) {
int authres;
param->clisock = param->srv->srvsock; if(parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) { RETURN(201) }
param->waitserver64 = 0x7fffffffffffffff; #ifndef NOIPV6
param->res = mapsocket(param, conf.timeouts[STRING_L]); memcpy(&param->sinsl, *SAFAMILY(&param->req) == AF_INET6 ? (struct sockaddr *)&param->srv->extsa6 : (struct sockaddr *)&param->srv->extsa, SASIZE(&param->req));
#else
memcpy(&param->sinsl, (struct sockaddr *)&param->srv->extsa, SASIZE(&param->req));
#endif
*SAPORT(&param->sinsl) = 0;
param->remsock = param->srv->so._socket(param->srv->so.state, SASOCK(&param->sinsl), SOCK_DGRAM, IPPROTO_UDP);
if(param->remsock == INVALID_SOCKET) { RETURN(202); }
if(param->srv->so._bind(param->srv->so.state, param->remsock, (struct sockaddr *)&param->sinsl, SASIZE(&param->sinsl))) { RETURN(203); }
#ifdef _WIN32
{ unsigned long ul2 = 1; ioctlsocket(param->remsock, FIONBIO, &ul2); }
#else
fcntl(param->remsock, F_SETFL, O_NONBLOCK | fcntl(param->remsock, F_GETFL));
#endif
memcpy(&param->sinsr, &param->req, sizeof(param->req));
param->operation = UDPASSOC;
authres = (*param->srv->authfunc)(param);
if(authres) { RETURN(authres); }
if(!param->srv->singlepacket)hashadd(&udp_table, param, &param, MAX_COUNTER_TIME);
socksendto(param, param->remsock, (struct sockaddr *)&param->sinsr, param->srvbuf, param->srvinbuf, 0);
_3proxy_sem_unlock(udpinit);
param->statscli64 += param->srvinbuf;
param->srvinbuf = 0;
param->nwrites++;
param->clisock = param->srv->srvsock;
param->waitserver64 = 0x7fffffffffffffff;
param->res = mapsocket(param, conf.timeouts[STRING_L]);
_3proxy_sem_lock(udpinit);
if(!param->srv->singlepacket)hashdelete(&udp_table, param);
CLEANRET: CLEANRET:
_3proxy_sem_unlock(udpinit);
dolog(param, NULL); dolog(param, NULL);
param->clisock = INVALID_SOCKET; param->clisock = INVALID_SOCKET;
freeparam(param); freeparam(param);