http://blog.macrowen.com/Technology/64.html
// Author: LZX
// E-mail: [email protected]
// Version: V1.0 (Multithreads Mode)
// Purpose: A Proxy works on one port and supports SOCKS v4 && v5 && Http protocol.
// The socks proxy request has not supported BIND method yet.
// The Http proxy supports three methods:GET(HEAD) POST CONNECT.
// Test PlatForm: WinXP SP2
// Compiled On: VC++ 6.0
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define MAX_HOSTNAME 256
#define DEFAULTPORT 80
#define LISTENPORT 1080
#define DEFLISNUM 50
#define MAXBUFSIZE 20480
#define TIMEOUT 10000
#define HEADLEN 7
char ErrorMsg[]="Http/1.1 403 Forbidden\r\n\r\n403 Forbidden
";
char ConnectionEstablished[]="HTTP/1.0 200 OK\r\n\r\n";
int LisPort;
char Username[256]="\0";
char Password[256]="\0";
struct Socks4Req
{
BYTE Ver;
BYTE REP;
WORD wPort;
DWORD dwIP;
BYTE other[1];
};
struct Socks5Req
{
BYTE Ver;
BYTE nMethods;
BYTE Methods[255];
};
struct AuthReq
{
BYTE Ver;
BYTE Ulen;
BYTE UserPass[1024];
};
typedef struct
{
BYTE Ver; // Version Number
BYTE CMD; // 0x01==TCP CONNECT,0x02==TCP BIND,0x03==UDP ASSOCIATE
BYTE RSV;
BYTE ATYP;
BYTE IP_LEN;
BYTE szIP;
}Socks5Info;
typedef struct
{
DWORD dwIP;
WORD wPort;
}IPandPort;
typedef struct
{
BYTE Ver;
BYTE REP;
BYTE RSV;
BYTE ATYP;
IPandPort IPandPort;
}Socks5AnsConn;
typedef struct
{
BYTE RSV[2];
BYTE FRAG;
BYTE ATYP;
IPandPort IPandPort;
// BYTE DATA;
}Socks5UDPHead;
struct SocketInfo
{
SOCKET socks;
IPandPort IPandPort;
};
typedef struct
{
SocketInfo Local;
SocketInfo Client;
SocketInfo Server;
}Socks5Para;
// End Of Structure
static CRITICAL_SECTION cs;
void TCPTransfer(SOCKET* CSsocket);
void UDPTransfer(Socks5Para *sPara);
BOOL ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const WORD RemotePort);
/////////////////////////////////////////////////////
//---------------------------------------------------------------------------
void GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,UINT *RemotePort)
{
char *fp = ReceiveBuf;
for(int i = 0;i < datalen && *fp != ':' && *fp != '\0' && *fp != '\r' && *fp != '/';i++)
{
HostName[i]=*fp++;
if(*fp == ':')
*RemotePort=atoi(fp+1);
else *RemotePort=DEFAULTPORT;
}
}
//---------------------------------------------------------------------------
char * GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen)
{
for(int i = 0;i < DataLen; i++)
{
if(ReceiveBuf[i] == '/')
{
*HostNaneLen = i;
return &ReceiveBuf[i];
}
}
return NULL;
}
//---------------------------------------------------------------------------
int CheckRequest(char *ReceiveBuf,int *MethodLength)
{
if(!strnicmp(ReceiveBuf,"GET ",4))
{
*MethodLength = 4;
return 1;
}
else if(!strnicmp(ReceiveBuf,"HEAD ",5)) //Looks like the same with GET
{
*MethodLength = 5;
return 2;
}
else if(!strnicmp(ReceiveBuf,"POST ",5))
{
*MethodLength = 5;
return 3;
}
else if(!strnicmp(ReceiveBuf,"CONNECT ",8))
{
*MethodLength = 8;
return 4;
}
else
{
return 0;
}
}
int ModifyRequest(char *SenderBuf,char *ReceiveBuf,int DataLen,int MethodLength)
{
strncpy(SenderBuf,ReceiveBuf,MethodLength);
int HedLen = 0;
if(strncmp(ReceiveBuf+MethodLength,"http://",HEADLEN))
return 0;
char * Getrootfp = GetURLRootPoint(ReceiveBuf+MethodLength+HEADLEN,DataLen-MethodLength-HEADLEN,&HedLen);
if(Getrootfp == NULL)
return 0;
memcpy(SenderBuf+MethodLength,Getrootfp,DataLen-MethodLength-HEADLEN-HedLen);
return DataLen-HEADLEN-HedLen;
}
BOOL SendRequest(SOCKET* CSsocket, char *SenderBuf, char *ReceiveBuf, int DataLen)
{
//CSsocket[0] ClientSocket
//CSsocket[1] ServerSocket
DWORD dwThreadID;
char HostName[MAX_HOSTNAME] = {0};
char ReqInfo1[8],ReqInfo2[248];
UINT RemotePort = 0;
static t=0;
EnterCriticalSection(&cs);
int n=++t;
LeaveCriticalSection(&cs);
int Flag=0, MethodLength=0, SendLength=0;
Flag = CheckRequest(ReceiveBuf,&MethodLength);
if(Flag==0) return 0;
if(Flag==1 || Flag==2 || Flag==3)
{
SendLength=ModifyRequest(SenderBuf,ReceiveBuf,DataLen,MethodLength);
if(!SendLength)
return 0;
GetHostNameAndPort(ReceiveBuf+MethodLength+HEADLEN,DataLen-MethodLength-HEADLEN,HostName,&RemotePort);
if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
return 0;
if(send(CSsocket[1],SenderBuf,SendLength,0) == SOCKET_ERROR)
return 0;
}else if(Flag==4)
{
GetHostNameAndPort(ReceiveBuf+MethodLength,DataLen-MethodLength,HostName,&RemotePort);
if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
return 0;
send(CSsocket[0], ConnectionEstablished, strlen(ConnectionEstablished)+1,0);
}
if(CSsocket[0] && CSsocket[1])
{
//printf("HTTP Proxy request %d OK.\n",n);
//sscanf(ReceiveBuf,"%s %s",ReqInfo1,ReqInfo2);
//printf("%s %s\n",ReqInfo1,ReqInfo2);
HANDLE ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TCPTransfer,(LPVOID)CSsocket,0,&dwThreadID);
if (ThreadHandle != NULL)
{
WaitForSingleObject(ThreadHandle, INFINITE);
//printf("HTTP Proxy request %d Exit.\n",n);
}
}else
return 0;
return 1;
}
/////////////////////////////////////////////////////
int Authentication(SOCKET* CSsocket, char *ReceiveBuf,int DataLen)
{
Socks5Req *sq;
char Method[2]={0x05,0};
sq=(Socks5Req *)ReceiveBuf;
////printf("%d,%d,%d,%d,%d\n",sq->Ver,sq->nMethods,sq->Methods[0],sq->Methods[1],sq->Methods[2]);
if(sq->Ver!=5)
return sq->Ver;
if((sq->Methods[0]==0)||(sq->Methods[0]==2))//00,无需认证;01,GSSAPI;02,需要用户名和PASSWORD
{
if(strlen(Username)==0)
Method[1]=0x00;
else
Method[1]=0x02;
if(send(CSsocket[0],Method,2,0) == SOCKET_ERROR)
return 0;
}else
return 0;
if(Method[1]==0x02)//00,无需认证;01,GSSAPI;02,需要用户名和PASSWORD
{
char USER[256];
char PASS[256];
memset(USER,0,sizeof(USER));
memset(PASS,0,sizeof(PASS));
DataLen = recv(CSsocket[0],ReceiveBuf,MAXBUFSIZE,0);
if(DataLen == SOCKET_ERROR || DataLen == 0)
return 0;
AuthReq *aq=(AuthReq *)ReceiveBuf;
if(aq->Ver!=1)
return 0;
if((aq->Ulen!=0)&&(aq->Ulen<=256))
memcpy(USER,ReceiveBuf+2,aq->Ulen);
int PLen=ReceiveBuf[2+aq->Ulen];
if((PLen!=0)&&(PLen<=256))
memcpy(PASS,ReceiveBuf+3+aq->Ulen,PLen);
//printf("USER %s\nPASS %s\n",USER,PASS);
//0=login successfully,0xFF=failure;
if(!strcmp(Username,USER) && !strcmp(Password,PASS))
{
ReceiveBuf[1]=0x00;
//printf("Socks5 Authentication Passed\n");
}
else
{
ReceiveBuf[1]=0xFF;
//printf("Invalid Password\n");
}
if(send(CSsocket[0],ReceiveBuf,2,0) == SOCKET_ERROR)
return 0;
}
return 1;
}
char *GetInetIP(char *OutIP)
{
// Get host adresses
char addr[16];
struct hostent * pHost;
pHost = gethostbyname("");
for( int i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
{
OutIP[0]=0;
for( int j = 0; j < pHost->h_length; j++ )
{
if( j > 0 ) strcat(OutIP,".");
sprintf(addr,"%u", (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);
strcat(OutIP,addr);
}
}
return OutIP;
}
char *DNS(char *HostName)
{
HOSTENT *hostent = NULL;
IN_ADDR iaddr;
hostent = gethostbyname(HostName);
if (hostent == NULL)
{
return NULL;
}
iaddr = *((LPIN_ADDR)*hostent->h_addr_list);
return inet_ntoa(iaddr);
}
int GetAddressAndPort(char *ReceiveBuf, int DataLen, int ATYP, char *HostName, WORD *RemotePort)
{
DWORD Socks5InfoSize = sizeof(Socks5Info);
DWORD dwIndex = 0;
Socks4Req *Socks4Request=(Socks4Req *)ReceiveBuf;
Socks5Info *Socks5Request=(Socks5Info *)ReceiveBuf;
struct sockaddr_in in;
if(ATYP==2) //Socks v4 !!!
{
*RemotePort=ntohs(Socks4Request->wPort);
if(ReceiveBuf[4]!=0x00) //USERID !!
in.sin_addr.s_addr = Socks4Request->dwIP;
else
in.sin_addr.s_addr = inet_addr(DNS((char*)&Socks4Request->other+1));
memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
return 1;
}
//ATYP=0x01代表IP V4地址 0x03代表域名;
if((Socks5Request->Ver==5)&&(ATYP==1))
{
IPandPort *IPP=(IPandPort *)&Socks5Request->IP_LEN;
in.sin_addr.S_un.S_addr = IPP->dwIP;
memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
*RemotePort = ntohs(IPP->wPort);
}
else if((Socks5Request->Ver==5)&&(ATYP==3))
{
memcpy(HostName, &Socks5Request->szIP, Socks5Request->IP_LEN);
memcpy(RemotePort, &Socks5Request->szIP+Socks5Request->IP_LEN, 2);
*RemotePort=ntohs(*RemotePort);
}else if((Socks5Request->Ver==0)&&(Socks5Request->CMD==0)&&(ATYP==1))
{
IPandPort *IPP=(IPandPort *)&Socks5Request->IP_LEN;
in.sin_addr.S_un.S_addr = IPP->dwIP;
memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
*RemotePort = ntohs(IPP->wPort);
return 10; //return Data Enter point
}else if((Socks5Request->Ver==0)&&(Socks5Request->CMD==0)&&(ATYP==3))
{
memcpy(HostName, &Socks5Request->szIP, Socks5Request->IP_LEN);
memcpy(RemotePort, &Socks5Request->szIP+Socks5Request->IP_LEN, 2);
*RemotePort=ntohs(*RemotePort);
return 7+Socks5Request->IP_LEN; //return Data Enter point
}else
return 0;
return 1;
}
BOOL ConnectToRemoteHost(SOCKET *ServerSocket,char *HostName,const WORD RemotePort)
{
struct sockaddr_in Server;
memset(&Server, 0, sizeof(Server));
Server.sin_family = AF_INET;
Server.sin_port = htons(RemotePort);
if (inet_addr(HostName) != INADDR_NONE)
Server.sin_addr.s_addr = inet_addr(HostName);
else
{
if (DNS(HostName) != NULL)
Server.sin_addr.s_addr = inet_addr(DNS(HostName));
else
return FALSE;
}
// Create Socket
*ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (*ServerSocket == INVALID_SOCKET)
return FALSE;
UINT TimeOut = TIMEOUT;
setsockopt(*ServerSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut));
if (connect(*ServerSocket, (const SOCKADDR *)&Server,sizeof(Server)) == SOCKET_ERROR)
{
printf("Fail To Connect To Remote Host\n");
closesocket(*ServerSocket);
return FALSE;
}
return TRUE;
}
int TalkWithClient(SOCKET *CSsocket, char *ReceiveBuf, int DataLen, char *HostName, WORD *RemotePort)
{
//CSsocket[0] ClientSocket
//CSsocket[1] ServerSocket
int Flag=0;
//Username Password Authentication
Flag = Authentication(CSsocket, ReceiveBuf, DataLen);
if(Flag==0) return 0;
if(Flag==4) //Processing Socks v4 requests......
{//The third parameter ATYP==2 is not used for Socks5 protocol,I use it to flag the socks4 request.
if(!GetAddressAndPort(ReceiveBuf, DataLen, 2, HostName, RemotePort))
return 0;
return 4;
}
//Processing Socks v5 requests......
DataLen = recv(CSsocket[0],ReceiveBuf,MAXBUFSIZE,0);
if(DataLen == SOCKET_ERROR || DataLen == 0)
return 0;
Socks5Info *Socks5Request=(Socks5Info *)ReceiveBuf;
if (Socks5Request->Ver != 5) //Invalid Socks 5 Request
{
//printf("Invalid Socks 5 Request\n");
return 0;
}
//Get IP Type //0x01==IP V4地址 0x03代表域名;0x04代表IP V6地址;not Support
if((Socks5Request->ATYP==1)||(Socks5Request->ATYP==3))
{
if(!GetAddressAndPort(ReceiveBuf, DataLen, Socks5Request->ATYP, HostName, RemotePort))
return 0;
}else return 0;
//Get and return the work mode. 1:TCP CONNECT 3:UDP ASSOCIATE
if((Socks5Request->CMD == 1)||(Socks5Request->CMD == 3))
return Socks5Request->CMD;
return 0;
}
BOOL CreateUDPSocket(Socks5AnsConn *SAC, SOCKET *socks)
{
char szIP[256];
struct sockaddr_in UDPServer;
struct sockaddr_in in;
memset(&in,0,sizeof(sockaddr_in));
int structsize=sizeof(sockaddr_in);
UDPServer.sin_family=AF_INET;
UDPServer.sin_addr.s_addr= INADDR_ANY;
UDPServer.sin_port=INADDR_ANY;
SOCKET Locals = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(Locals == SOCKET_ERROR)
{
//printf("UDP socket create failed.\n");
return 0;
}
if(bind(Locals,(SOCKADDR*)&UDPServer, sizeof(UDPServer)) == SOCKET_ERROR)
{
//printf("UDP socket bind failed.\n");
return 0;
}
UINT TimeOut = TIMEOUT;
//setsockopt(Locals,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut));
*socks = Locals;
getsockname(Locals,(struct sockaddr *)&in,&structsize);
SAC->IPandPort.dwIP = inet_addr(GetInetIP(szIP));
SAC->IPandPort.wPort = in.sin_port;
//printf("UDP Bound to %s:%d\r\n", szIP, ntohs(in.sin_port));
return 1;
}
DWORD WINAPI ZXProxyThread(SOCKET* CSsocket)
{
DWORD dwThreadID;
static t=0;
EnterCriticalSection(&cs);
int n=++t;
LeaveCriticalSection(&cs);
WORD RemotePort = 0;
char *HostName = (char*)malloc(sizeof(char)*MAX_HOSTNAME);
char *ReceiveBuf = (char*)malloc(sizeof(char)*MAXBUFSIZE);
char *SenderBuf = (char*)malloc(sizeof(char)*MAXBUFSIZE);
Socks4Req Socks4Request;
Socks5AnsConn SAC;
memset(HostName,0,MAX_HOSTNAME);
memset(ReceiveBuf,0,MAXBUFSIZE);
memset( SenderBuf,0,MAXBUFSIZE);
memset(&SAC,0,sizeof(SAC));
/////////////////////////UDP variable
Socks5Para sPara;
struct sockaddr_in in;
memset(&sPara,0,sizeof(Socks5Para));
memset(&in,0,sizeof(sockaddr_in));
int structsize=sizeof(sockaddr_in);
////////////////////////
int DataLen = 0,Flag = 0,ProtocolVer=0;
DataLen = recv(CSsocket[0],ReceiveBuf,MAXBUFSIZE,0);
if(DataLen == SOCKET_ERROR || DataLen == 0)
goto exit;
if(SendRequest(CSsocket, SenderBuf, ReceiveBuf, DataLen)) //http proxy
goto exit;
Flag=TalkWithClient(CSsocket, ReceiveBuf, DataLen, HostName, &RemotePort);
if(!Flag)
{
/*SAC.Ver=0x05;
SAC.REP=0x01;
SAC.ATYP=0x01;
send(CSsocket[0], (char *)&SAC, 10, 0);*/
goto exit;
}
else if(Flag==1) //TCP CONNECT
{
ProtocolVer=5;
if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
SAC.REP=0x01;
SAC.Ver=0x05;
SAC.ATYP=0x01;
if(send(CSsocket[0], (char *)&SAC, 10, 0) == SOCKET_ERROR)
goto exit;
if(SAC.REP==0x01) // general SOCKS server failure
goto exit;
}
else if(Flag==3) //UDP ASSOCIATE
{ //ProcessingUDPsession;
ProtocolVer=5;
//Save the client connection information(client IP and source port)
getpeername(CSsocket[0],(struct sockaddr *)&in,&structsize);
if(inet_addr(HostName)==0)
sPara.Client.IPandPort.dwIP = in.sin_addr.s_addr;
else
sPara.Client.IPandPort.dwIP = inet_addr(DNS(HostName));
////printf("Accept ip:%s\n",inet_ntoa(in.sin_addr));
sPara.Client.IPandPort.wPort= htons(RemotePort);/////////////////
sPara.Client.socks=CSsocket[0];
if(!CreateUDPSocket(&SAC,&sPara.Local.socks)) //Create a local UDP socket
SAC.REP=0x01;
SAC.Ver=5;
SAC.ATYP=1;
if(send(CSsocket[0], (char *)&SAC, 10, 0) == SOCKET_ERROR)
goto exit;
if(SAC.REP==0x01) // general SOCKS server failure
goto exit;
sPara.Local.IPandPort=SAC.IPandPort; //Copy local UDPsocket data structure to sPara.Local
////// Create UDP Transfer thread
HANDLE ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)UDPTransfer,(LPVOID)&sPara,0,&dwThreadID);
if (ThreadHandle != NULL)
{
//printf("Socks%d UDP Session-> %s:%d\n",ProtocolVer,inet_ntoa(in.sin_addr),ntohs(sPara.Client.IPandPort.wPort));
WaitForSingleObject(ThreadHandle, INFINITE);
//printf("UDPTransfer Thread %d Exit.\n",n);
}else
goto exit;
return 1;
////////////////////
}
else if(Flag==4) // Socks v4! I use the return value==4 to flag the Socks v4 request.
{
ProtocolVer=4;
memset(&Socks4Request, 0, 9);
if(!ConnectToRemoteHost(&CSsocket[1],HostName,RemotePort))
Socks4Request.REP = 0x5B; //REJECT
else
Socks4Request.REP = 0x5A; //GRANT
if(send(CSsocket[0], (char *)&Socks4Request, 8, 0) == SOCKET_ERROR)
goto exit;
if(Socks4Request.REP==0x5B) //ConnectToRemoteHost failed,closesocket and free some point.
goto exit;
}else
goto exit;
if(CSsocket[0] && CSsocket[1])
{
//printf("Socks%d TCP Session-> %s:%d\n",ProtocolVer,HostName,RemotePort);
HANDLE ThreadHandle = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)TCPTransfer,(LPVOID)CSsocket,0,&dwThreadID);
if (ThreadHandle != NULL)
{
WaitForSingleObject(ThreadHandle, INFINITE);
}
}else
goto exit;
goto exit;
exit:
closesocket(CSsocket[0]);
closesocket(CSsocket[1]);
free(CSsocket);
free(HostName);
free(SenderBuf);
free(ReceiveBuf);
return 0;
}
BOOL StartProxy()
{
WSADATA WSAData;
if(WSAStartup(MAKEWORD(2,2), &WSAData))
return false;
SOCKET ProxyServer= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ProxyServer == SOCKET_ERROR)
return false;
struct sockaddr_in Server={0};
Server.sin_family = AF_INET;
Server.sin_port = htons(LisPort);
Server.sin_addr.S_un.S_addr = INADDR_ANY;
if(bind(ProxyServer, (LPSOCKADDR)&Server, sizeof(Server)) == SOCKET_ERROR)
return false;
if(listen(ProxyServer, DEFLISNUM) == SOCKET_ERROR)
return false;
SOCKET AcceptSocket = INVALID_SOCKET;
SOCKET *CSsocket;
DWORD dwThreadID;
printf("Now listening on port: %d\r\n",LisPort);
while(1)
{
AcceptSocket = accept(ProxyServer, NULL, NULL);
//printf("Accepting New Requests\n");
CSsocket = (SOCKET*)malloc(sizeof(SOCKET)*2);
if (CSsocket == NULL)
{
//printf("Fail To Allocate Ram\n");
continue;
}
CSsocket[0] = AcceptSocket;
HANDLE hThread = CreateThread (NULL,0, (LPTHREAD_START_ROUTINE)ZXProxyThread,CSsocket,0, &dwThreadID); // Create Thread To Handle Request
if (hThread == NULL) // Fail To Create Socket
{
//printf("Fail To Create Thread.Probably Too Many Threads Have Been Created\n");
Sleep(1000);
}
else
{
CloseHandle(hThread);
}
}
}
void main(int argc, char* argv[])
{
LisPort=LISTENPORT;
if(argc>1)
LisPort=atoi(argv[1]);
if(argc==4)
{
strcpy(Username,argv[2]);
strcpy(Password,argv[3]);
}
printf("SOCKS v4 && v5 && Http Proxy V1.0 By LZX.\r\nUsage:\n%s ProxyPort (Default port 1080)\n%s ProxyPort Username Password\n",argv[0],argv[0]);
InitializeCriticalSection(&cs);
StartProxy();
WSACleanup();
DeleteCriticalSection(&cs);
}
////////////////////////////////
int UDPSend(SOCKET s, char *buff, int nBufSize, struct sockaddr_in *to,int tolen)
{
int nBytesLeft = nBufSize;
int idx = 0, nBytes = 0;
while(nBytesLeft > 0)
{
nBytes = sendto(s, &buff[idx], nBytesLeft, 0, (SOCKADDR *)to, tolen);
if(nBytes == SOCKET_ERROR)
{
//printf("Failed to send buffer to socket %d.\r\n", WSAGetLastError());
return SOCKET_ERROR;
}
nBytesLeft -= nBytes;
idx += nBytes;
}
return idx;
}
void UDPTransfer(Socks5Para *sPara)////////////////!!!!!!!!!!!!!!!!
{
struct sockaddr_in SenderAddr;
int SenderAddrSize=sizeof(SenderAddr),DataLength=0,result;
char RecvBuf[MAXBUFSIZE];
struct sockaddr_in UDPClient,UDPServer;
memset(&UDPClient,0,sizeof(sockaddr_in));
memset(&UDPServer,0,sizeof(sockaddr_in));
UDPClient.sin_family = AF_INET;
UDPClient.sin_addr.s_addr = sPara->Client.IPandPort.dwIP;
UDPClient.sin_port = sPara->Client.IPandPort.wPort;
/*/test
Socks5UDPHead test;
memset(&test,0,sizeof(Socks5UDPHead));
test.RSV[0]=0x05;
test.ATYP=0x01;
test.IPandPort=sPara->Local.IPandPort;
if(sendto(sPara->Local.socks,(char*)&test, 10,0,(struct sockaddr FAR *)&UDPClient,sizeof(UDPClient)) == SOCKET_ERROR)
{
//printf("test sendto server error.\n");
return;
}*/
//printf("UDPTransfer thread start......\n");
fd_set readfd;
while(1)
{
FD_ZERO(&readfd);
FD_SET((UINT)sPara->Local.socks, &readfd);
FD_SET((UINT)sPara->Client.socks, &readfd);
result=select(sPara->Local.socks+1,&readfd,NULL,NULL,NULL);
if((result<0) && (errno!=EINTR))
{
//printf("Select error.\r\n");
break;
}
if(FD_ISSET(sPara->Client.socks, &readfd))
break;
if(FD_ISSET(sPara->Local.socks, &readfd))
{
memset(RecvBuf,0,MAXBUFSIZE);
DataLength=recvfrom(sPara->Local.socks,
RecvBuf+10, MAXBUFSIZE-10, 0, (struct sockaddr FAR *)&SenderAddr, &SenderAddrSize);
if(DataLength==SOCKET_ERROR)
{
//printf("UDPTransfer recvfrom error.\n");
break;
}//SenderAddr.sin_addr.s_addr==sPara->Client.IPandPort.dwIP&&
if(SenderAddr.sin_port==sPara->Client.IPandPort.wPort)//Data come from client
{
//////这里要先修改udp数据报头
WORD RemotePort = 0;
char HostName[MAX_HOSTNAME];
memset(HostName,0,MAX_HOSTNAME);
int DataPoint=GetAddressAndPort(RecvBuf+10, DataLength, RecvBuf[13], HostName, &RemotePort);
if(DataPoint)
{
////printf("Data come from client IP: %s:%d | %d Bytes.\n",
// inet_ntoa(SenderAddr.sin_addr),ntohs(SenderAddr.sin_port),DataLength);
//send data to server
////printf("IP: %s:%d || DataPoint: %d\n",HostName,RemotePort,DataPoint);
UDPServer.sin_family=AF_INET;
UDPServer.sin_addr.s_addr= inet_addr(DNS(HostName));
UDPServer.sin_port=htons(RemotePort);
result=UDPSend(sPara->Local.socks,RecvBuf+10+DataPoint, DataLength-DataPoint,&UDPServer,sizeof(UDPServer));
if(result == SOCKET_ERROR)
{
//printf("sendto server error\n");
break;
}
printf("Data(%d) sent to server succeed.|| Bytes: %d\n",DataLength-DataPoint,result);
}else break;
}else if(SenderAddr.sin_port==UDPServer.sin_port)//Data come from server
{//SenderAddr.sin_addr.s_addr==UDPServer.sin_addr.s_addr&&
//send data to client
////printf("Data come from server IP: %s:%d | %d Bytes.\n",
// inet_ntoa(SenderAddr.sin_addr),ntohs(SenderAddr.sin_port),DataLength);
Socks5UDPHead *UDPHead = (Socks5UDPHead*)RecvBuf;
memset(UDPHead,0,10);
UDPHead->ATYP=0x01;
UDPHead->IPandPort=sPara->Client.IPandPort;
//UDPHead->IPandPort.dwIP =SenderAddr.sin_addr.s_addr;
//UDPHead->IPandPort.wPort=SenderAddr.sin_port;
//memcpy(&UDPHead->DATA-2,RecvBuf,DataLength);//UDPHead->DATA-2!!!!!!!!!!!!
result=UDPSend(sPara->Local.socks,RecvBuf,DataLength+10,&UDPClient,sizeof(UDPClient));
if(result == SOCKET_ERROR)
{
////printf("sendto client error\n");
break;
}
//printf("Data(%d) sent to client succeed.|| Bytes: %d\n",DataLength+10,result);
}else
{
//printf("!!!!!The data are not from client or server.drop it.%s\n",inet_ntoa(SenderAddr.sin_addr));
}
}
Sleep(5);
}
closesocket(sPara->Local.socks);
closesocket(sPara->Client.socks);
}
void TCPTransfer(SOCKET* CSsocket)
{
SOCKET ClientSocket = CSsocket[0];
SOCKET ServerSocket = CSsocket[1];
struct timeval timeset;
fd_set readfd,writefd;
int result,i=0;
char read_in1[MAXBUFSIZE],send_out1[MAXBUFSIZE],SenderBuf[MAXBUFSIZE];
char read_in2[MAXBUFSIZE],send_out2[MAXBUFSIZE];
int read1=0,totalread1=0,send1=0;
int read2=0,totalread2=0,send2=0;
int sendcount1,sendcount2;
int maxfd;
maxfd=max(ClientSocket,ServerSocket)+1;
memset(read_in1,0,MAXBUFSIZE);
memset(read_in2,0,MAXBUFSIZE);
memset(send_out1,0,MAXBUFSIZE);
memset(send_out2,0,MAXBUFSIZE);
timeset.tv_sec=TIMEOUT;
timeset.tv_usec=0;
while(1)
{
FD_ZERO(&readfd);
FD_ZERO(&writefd);
FD_SET((UINT)ClientSocket, &readfd);
FD_SET((UINT)ClientSocket, &writefd);
FD_SET((UINT)ServerSocket, &writefd);
FD_SET((UINT)ServerSocket, &readfd);
result=select(maxfd,&readfd,&writefd,NULL,×et);
if((result<0) && (errno!=EINTR))
{
printf("Select error.\r\n");
break;
}
else if(result==0)
{
printf("Socket time out.\r\n");
break;
}
if(FD_ISSET(ServerSocket, &readfd))
{
if(totalread20)
{
send2=send(ClientSocket, send_out2+sendcount2, totalread2, 0);
if(send2==0)break;
if((send2<0) && (errno!=EINTR))
{
printf("Send to ClientSocket unknow error.\r\n");
err2=1;
break;
}
if((send2<0) && (errno==ENOSPC)) break;
sendcount2+=send2;
totalread2-=send2;
}
if(err2==1) break;
if((totalread2>0) && (sendcount2 > 0))
{
/* move not sended data to start addr */
memcpy(send_out2, send_out2+sendcount2, totalread2);
memset(send_out2+totalread2, 0, MAXBUFSIZE-totalread2);
}
else
memset(send_out2,0,MAXBUFSIZE);
}
if(FD_ISSET(ClientSocket, &readfd))
{
if(totalread10)
{
send1=send(ServerSocket, send_out1+sendcount1, totalread1, 0);
if(send1==0)break;
if((send1<0) && (errno!=EINTR))
{
err=1;
break;
}
if((send1<0) && (errno==ENOSPC)) break;
sendcount1+=send1;
totalread1-=send1;
}
if(err==1) break;
if((totalread1>0) && (sendcount1>0))
{
memcpy(send_out1,send_out1+sendcount1,totalread1);
memset(send_out1+totalread1,0,MAXBUFSIZE-totalread1);
}
else
memset(send_out1,0,MAXBUFSIZE);
}
Sleep(5);
}
closesocket(ClientSocket);
closesocket(ServerSocket);
}