ProxySocket.pas
上传用户:hbtcygglw
上传日期:2007-01-07
资源大小:281k
文件大小:12k
- unit ProxySocket;
- {$define SYNC}
- {
- UDP Proxy core unit
- copyright (C) 2000-2002 NetGale
- }
- interface
- uses SysUtils,WIndows,WinSock,Classes,Dialogs;
- type
- TProxySock=class;
- TProxyReadThread=class(TThread)
- private
- FProxySock:TProxySock;
- FBuffer:array [0..2048] of char;
- FBuflen:Integer;
- FFromAddr:TSockAddr;
- procedure DoNotify;
- protected
- procedure DoTerminate; override;
- procedure Execute; override;
- public
- constructor Create(CreateSuspended:Boolean;ASock:TProxySock);
- destructor Destroy;override;
- end;
- TSwitchDirection=(sdRecv,sdSend);
- TSockNotifyEvent=procedure (buf:array of char;buflen:integer;from:TSockAddr;Dest:TSockAddr;var drop:Boolean) of object;
- TUDPSwitcher=class;
- PUDPSwitcher=^TUDPSwitcher;
- TProxySock=class
- private
- FDirection:TSwitchDirection;
- FSocket:TSocket;
- FReadThread:TProxyReadThread;
- FSwitcher:TUDPSwitcher;
- procedure Init;
- public
- Tag:Integer;
- ThisAddr,ProxyAddr:TSockAddr;
- constructor Create(aProxyAddr:TSockAddr);overload;
- constructor Create(aThisAddr:TSockAddr;aProxyAddr:TSockAddr);overload;
- constructor Create(ThisPort:WORD;aProxyAddr:TSockAddr);overload;
- constructor Create(ThisPort:WORD;ProxyIp:String;ProxyPort:WORD);overload;
- destructor Destroy;override;
- function CreateSocket:Boolean;
- procedure OnRecv(buf:array of char;buflen:Integer;from:TSockAddr);
- function SendBuf(buf:array of char;buflen:Integer;Dest:TSockAddr):Boolean;overload;
- function SendBuf(buf:array of char;buflen:Integer;DestIp:String;DestPort:Word):Boolean;overload;
- function StartThread:Boolean;
- procedure StopThread;
- end;
- PProxySock=^TProxySock;
- TUDPSwitcher=class
- private
- FSockets:array of TProxySock;
- FInternalFlag:array of boolean;
- FOnSend: TSockNotifyEvent;
- FOnRecv: TSockNotifyEvent;
- FOnNewSocket: TNotifyEvent;
- {$ifdef SYNC}
- FSockLock:TMultiReadExclusiveWriteSynchronizer;
- {$endif}
- FInternalProxyCount: Integer;
- FExternalProxyCount: Integer;
- procedure SetOnRecv(const Value: TSockNotifyEvent);
- procedure SetOnSend(const Value: TSockNotifyEvent);
- procedure SetOnNewSocket(const Value: TNotifyEvent);
- function GetSocketByDirection(index:integer;direction:TSwitchDirection):TProxySock;
- public
- property OnNewSocket:TNotifyEvent read FOnNewSocket write SetOnNewSocket;
- property OnRecv:TSockNotifyEvent read FOnRecv write SetOnRecv;
- property OnSend:TSockNotifyEvent read FOnSend write SetOnSend;
- property InternalProxyCount:Integer read FInternalProxyCount;
- property ExternalProxyCount:Integer read FExternalProxyCount;
- function RegisterSocket(sock:TProxySock;Direction:TSwitchDirection;InternalFlag:Boolean=false):Integer;
- procedure UnregisterSocket(sock:TProxySock);
- function FindSocket(addr:TSockAddr):TProxySock;overload;
- function FindSocket(ip:String;port:WORD):TProxySock;overload;
- function FindSocketByTag(tag:Integer):TProxySock;
- function GetInternalProxy(index:Integer):TProxySock;
- function GetExternalProxy(index:Integer):TProxySock;
- procedure SwitchPackage(buf:array of char;buflen:Integer;from:TSockAddr;Dest:TSockAddr;hint:TSwitchDirection);
- constructor Create(primary:TProxySock);overload;
- constructor Create(thisPort:Word;proxyAddr:String;proxyPort:Word);overload;
- destructor Destroy;override;
- function GetPrimarySocket:TProxySock;
- end;
- implementation
- uses IpHdr;
- { TProxySock }
- constructor TProxySock.Create(aThisAddr, aProxyAddr: TSockAddr);
- begin
- Init;
- ThisAddr:=aThisAddr;
- ProxyAddr:=aProxyAddr;
- end;
- constructor TProxySock.Create(aProxyAddr: TSockAddr);
- begin
- Init;
- ThisAddr.sin_family:=AF_INET;
- ThisAddr.sin_addr.S_addr:=INADDR_ANY;
- ThisAddr.sin_port:=0;
- ProxyAddr:=aProxyAddr;
- CreateSocket;
- end;
- constructor TProxySock.Create(ThisPort: WORD; ProxyIp: String;
- ProxyPort: WORD);
- begin
- Init;
- ThisAddr.sin_family:=AF_INET;
- ThisAddr.sin_addr.S_addr:=INADDR_ANY;
- ThisAddr.sin_port:=htons(ThisPort);
- ProxyAddr.sin_family:=AF_INET;
- ProxyAddr.sin_port:=htons(ProxyPort);
- LookupName(proxyIp,ProxyAddr.sin_addr);
- CreateSocket;
- end;
- constructor TProxySock.Create(ThisPort: WORD; aProxyAddr: TSockAddr);
- begin
- Init;
- ThisAddr.sin_family:=AF_INET;
- ThisAddr.sin_port:=htons(ThisPort);
- ThisAddr.sin_addr.S_addr:=INADDR_ANY;
- ProxyAddr:=aProxyAddr;
- CreateSocket;
- end;
- function TProxySock.CreateSocket: Boolean;
- begin
- FSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
- if(FSocket<>INVALID_SOCKET)then
- begin
- if(bind(FSocket,ThisAddr,SizeOf(ThisAddr))<>SOCKET_ERROR)then
- begin
- if(not StartThread)then
- begin
- closesocket(FSocket);
- FSocket:=INVALID_SOCKET;
- Result:=False;
- end
- else Result:=TRUE;
- end
- else
- begin
- closesocket(FSocket);
- FSocket:=INVALID_SOCKET;
- Result:=False;
- end;
- end
- else Result:=False;
- end;
- destructor TProxySock.Destroy;
- begin
- if(FSocket<>INVALID_SOCKET)then closesocket(FSocket);
- if(Assigned(FReadThread))then FReadThread.Terminate;
- if(FSwitcher<>nil)then FSwitcher.UnregisterSocket(self);
- inherited;
- end;
- procedure TProxySock.Init;
- begin
- FReadThread:=nil;
- FSocket:=INVALID_SOCKET;
- FSwitcher:=nil;
- end;
- procedure TProxySock.OnRecv(buf: array of char; buflen: Integer;
- from: TSockAddr);
- var
- drop:Boolean;
- begin
- drop:=False;
- case FDirection of
- sdSend:
- begin
- if(Assigned(FSwitcher) and Assigned(FSwitcher.FOnSend))then
- FSwitcher.FOnSend(buf,buflen,from,ProxyAddr,drop);
- end;
- sdRecv:
- begin
- if(Assigned(FSwitcher)and Assigned(FSwitcher.FOnRecv))then
- FSwitcher.FOnRecv(buf,buflen,from,ProxyAddr,drop);
- end;
- end;
- if((not drop) and (FSwitcher<>nil))then
- begin
- FSwitcher.SwitchPackage(buf,buflen,from,ProxyAddr,FDirection);
- end;
- end;
- function TProxySock.SendBuf(buf: array of char; buflen: Integer;
- Dest: TSockAddr): Boolean;
- begin
- if(FSocket<>INVALID_SOCKET)then
- begin
- Result:=(WinSock.sendto(FSocket,buf,buflen,0,Dest,SizeOf(Dest))<>SOCKET_ERROR);
- end
- else Result:=False;
- end;
- function TProxySock.SendBuf(buf: array of char; buflen: Integer;
- DestIp: String; DestPort: Word): Boolean;
- var
- addr:TSockAddr;
- begin
- addr.sin_family:=AF_INET;
- addr.sin_addr.S_addr:=inet_addr(PChar(DestIp));
- addr.sin_port:=DestPort;
- Result:=SendBuf(buf,buflen,addr);
- end;
- function TProxySock.StartThread: Boolean;
- begin
- try
- FReadThread:=TProxyReadThread.Create(False,self);
- Result:=True;
- except
- Result:=False;
- end;
- end;
- procedure TProxySock.StopThread;
- begin
- FReadThread.Terminate;
- end;
- { TUDPSwitcher }
- constructor TUDPSwitcher.Create(primary: TProxySock);
- begin
- FOnRecv:=nil;
- FOnSend:=nil;
- {$ifdef SYNC}
- FSockLock:=TMultiReadExclusiveWriteSynchronizer.Create;
- {$endif}
- RegisterSocket(primary,sdSend,true);
- end;
- constructor TUDPSwitcher.Create(thisPort: Word; proxyAddr: String;
- proxyPort: Word);
- var
- s:TProxySock;
- begin
- FOnRecv:=nil;
- FOnSend:=nil;
- {$ifdef SYNC}
- FSockLock:=TMultiReadExclusiveWriteSynchronizer.Create;
- {$endif}
- s:=TProxySock.Create(thisPort,ProxyAddr,ProxyPort);
- RegisterSocket(s,sdSend,true);
- end;
- destructor TUDPSwitcher.Destroy;
- var
- i,len:Integer;
- begin
- len:=Length(FSockets);
- for i:=0 to len-1 do
- begin
- UnregisterSocket(FSockets[i]);
- end;
- end;
- function TUDPSwitcher.FindSocket(addr: TSockAddr): TProxySock;
- var
- i,len:Integer;
- begin
- Result:=nil;
- {$ifdef SYNC}
- FSockLock.BeginRead;
- {$endif}
- len:=Length(FSockets);
- for i:=0 to len-1 do
- begin
- if((FSockets[i].ProxyAddr.sin_addr.S_addr=addr.sin_addr.S_addr)
- and(FSockets[i].ProxyAddr.sin_port=addr.sin_port)
- and(FSockets[i].ProxyAddr.sin_family=addr.sin_family))then
- begin
- Result:=FSockets[i];
- end;
- end;
- {$ifdef SYNC}
- FSockLock.EndRead;
- {$endif}
- end;
- function TUDPSwitcher.FindSocket(ip: String; port: WORD): TProxySock;
- var
- addr:TSockAddr;
- begin
- addr.sin_family:=AF_INET;
- addr.sin_addr.S_addr:=inet_addr(PChar(ip));
- addr.sin_port:=htons(port);
- Result:=FindSocket(addr);
- end;
- function TUDPSwitcher.FindSocketByTag(tag: Integer): TProxySock;
- var
- i,len:Integer;
- begin
- Result:=nil;
- len:=Length(FSockets);
- for i:=0 to len-1 do
- begin
- if(FSockets[i].Tag=tag)then
- begin
- Result:=FSockets[i];
- end;
- end;
- end;
- function TUDPSwitcher.GetExternalProxy(index: Integer): TProxySock;
- begin
- Result:=GetSocketByDirection(index,sdRecv);
- end;
- function TUDPSwitcher.GetInternalProxy(index: Integer): TProxySock;
- begin
- Result:=GetSocketByDirection(index,sdSend);
- end;
- function TUDPSwitcher.GetPrimarySocket: TProxySock;
- begin
- Result:=FSockets[0];
- end;
- function TUDPSwitcher.GetSocketByDirection(index: integer;
- direction: TSwitchDirection): TProxySock;
- var
- cnt,i,len:Integer;
- begin
- Result:=nil;
- cnt:=0;
- len:=Length(FSockets);
- for i:=0 to len-1 do
- begin
- if(FSockets[i].FDirection=direction)then
- begin
- if(cnt=index)then
- begin
- Result:=FSockets[i];
- Break;
- end;
- Inc(cnt);
- end;
- end;
- end;
- function TUDPSwitcher.RegisterSocket(sock: TProxySock;Direction:TSwitchDirection;InternalFlag:Boolean=false):Integer;
- var
- len,i:Integer;
- begin
- Result:=-1;
- {$ifdef SYNC}
- FSockLock.BeginWrite;
- {$endif}
- sock.FSwitcher:=self;
- sock.FDirection:=Direction;
- len:=Length(FSockets);
- for i:=0 to len-1 do
- begin
- if(FSockets[i]=nil)then
- begin
- FSockets[i]:=sock;
- FInternalFlag[i]:=InternalFlag;
- Result:=i;
- end;
- end;
- if(Result=-1)then
- begin
- SetLength(FSockets,len+1);
- SetLength(FInternalFlag,len+1);
- FSockets[len]:=sock;
- FInternalFlag[len]:=InternalFlag;
- Result:=len;
- end;
- {$ifdef SYNC}
- FSockLock.EndWrite;
- {$endif}
- end;
- procedure TUDPSwitcher.SetOnNewSocket(const Value: TNotifyEvent);
- begin
- FOnNewSocket := Value;
- end;
- procedure TUDPSwitcher.SetOnRecv(const Value: TSockNotifyEvent);
- begin
- FOnRecv := Value;
- end;
- procedure TUDPSwitcher.SetOnSend(const Value: TSockNotifyEvent);
- begin
- FOnSend := Value;
- end;
- procedure TUDPSwitcher.SwitchPackage(buf: array of char; buflen: Integer;
- from, Dest: TSockAddr;hint:TSwitchDirection);
- var
- sock:TProxySock;
- begin
- sock:=FindSocket(from);
- if(sock=nil)then
- begin
- if(hint=sdSend)then hint:=sdRecv
- else hint:=sdSend;
- sock:=TProxySock.Create(from);
- if(sock<>nil)then
- begin
- RegisterSocket(sock,hint,true);
- if(Assigned(OnNewSocket))then OnNewSocket(sock);
- end;
- end;
- sock.SendBuf(buf,buflen,Dest);
- end;
- procedure TUDPSwitcher.UnregisterSocket(sock: TProxySock);
- var
- i,len:Integer;
- begin
- {$ifdef SYNC}
- FSockLock.BeginWrite;
- {$endif}
- len:=Length(FSockets);
- sock.FSwitcher:=nil;
- for i:=0 to len-1 do
- begin
- if(FSockets[i]=sock)then
- begin
- if(FInternalFlag[i])then sock.Destroy;
- FSockets[i]:=nil;
- Break;
- end;
- end;
- {$ifdef SYNC}
- FSockLock.EndWrite;
- {$endif}
- end;
- { TProxyReadThread }
- constructor TProxyReadThread.Create(CreateSuspended: Boolean;
- ASock: TProxySock);
- begin
- FreeOnTerminate := True;
- FProxySock:=ASock;
- inherited Create(CreateSuspended);
- end;
- destructor TProxyReadThread.Destroy;
- begin
- inherited;
- end;
- procedure TProxyReadThread.DoNotify;
- begin
- if(Assigned(FProxySock))then
- FProxySock.OnRecv(FBuffer,FBuflen,FFromAddr);
- end;
- procedure TProxyReadThread.DoTerminate;
- begin
- inherited;
- if(Assigned(FProxySock)
- and Assigned(FProxySock.FReadThread)
- and (FProxySock.FReadThread=self))then
- begin
- FProxySock.FReadThread:=nil;
- end;
- end;
- procedure TProxyReadThread.Execute;
- var
- fromlen:Integer;
- begin
- while((not Terminated) and Assigned(FProxySock))do
- begin
- fromlen:=sizeof(FFromAddr);
- FBufLen:=recvfrom(FProxySock.FSocket,FBuffer,2048,0,FFromAddr,fromlen);
- if(FBuflen<>SOCKET_ERROR)then
- begin
- Synchronize(DoNotify);
- end;
- end;
- end;
- end.