ProxySocket.pas
上传用户:hbtcygglw
上传日期:2007-01-07
资源大小:281k
文件大小:12k
源码类别:

其他

开发平台:

Delphi

  1. unit ProxySocket;
  2. {$define SYNC}
  3. {
  4. UDP Proxy core unit
  5. copyright (C) 2000-2002 NetGale
  6. }
  7. interface
  8. uses SysUtils,WIndows,WinSock,Classes,Dialogs;
  9. type
  10.     TProxySock=class;
  11.     TProxyReadThread=class(TThread)
  12.         private
  13.         FProxySock:TProxySock;
  14.         FBuffer:array [0..2048] of char;
  15.         FBuflen:Integer;
  16.         FFromAddr:TSockAddr;
  17.         procedure DoNotify;
  18.         protected
  19.         procedure DoTerminate; override;
  20.         procedure Execute; override;
  21.         public
  22.         constructor Create(CreateSuspended:Boolean;ASock:TProxySock);
  23.         destructor  Destroy;override;
  24.         end;
  25.     TSwitchDirection=(sdRecv,sdSend);
  26.     TSockNotifyEvent=procedure (buf:array of char;buflen:integer;from:TSockAddr;Dest:TSockAddr;var drop:Boolean) of object;
  27.     TUDPSwitcher=class;
  28.     PUDPSwitcher=^TUDPSwitcher;
  29.     TProxySock=class
  30.         private
  31.         FDirection:TSwitchDirection;
  32.         FSocket:TSocket;
  33.         FReadThread:TProxyReadThread;
  34.         FSwitcher:TUDPSwitcher;
  35.         procedure   Init;
  36.         public
  37.         Tag:Integer;
  38.         ThisAddr,ProxyAddr:TSockAddr;
  39.         constructor Create(aProxyAddr:TSockAddr);overload;
  40.         constructor Create(aThisAddr:TSockAddr;aProxyAddr:TSockAddr);overload;
  41.         constructor Create(ThisPort:WORD;aProxyAddr:TSockAddr);overload;
  42.         constructor Create(ThisPort:WORD;ProxyIp:String;ProxyPort:WORD);overload;
  43.         destructor  Destroy;override;
  44.         function    CreateSocket:Boolean;
  45.         procedure   OnRecv(buf:array of char;buflen:Integer;from:TSockAddr);
  46.         function    SendBuf(buf:array of char;buflen:Integer;Dest:TSockAddr):Boolean;overload;
  47.         function    SendBuf(buf:array of char;buflen:Integer;DestIp:String;DestPort:Word):Boolean;overload;
  48.         function    StartThread:Boolean;
  49.         procedure   StopThread;
  50.         end;
  51.     PProxySock=^TProxySock;
  52.     TUDPSwitcher=class
  53.         private
  54.         FSockets:array of TProxySock;
  55.         FInternalFlag:array of boolean;
  56.         FOnSend: TSockNotifyEvent;
  57.         FOnRecv: TSockNotifyEvent;
  58.         FOnNewSocket: TNotifyEvent;
  59. {$ifdef SYNC}
  60.         FSockLock:TMultiReadExclusiveWriteSynchronizer;
  61. {$endif}
  62.         FInternalProxyCount: Integer;
  63.         FExternalProxyCount: Integer;
  64.         procedure SetOnRecv(const Value: TSockNotifyEvent);
  65.         procedure SetOnSend(const Value: TSockNotifyEvent);
  66.         procedure SetOnNewSocket(const Value: TNotifyEvent);
  67.         function  GetSocketByDirection(index:integer;direction:TSwitchDirection):TProxySock;
  68.         public
  69.         property  OnNewSocket:TNotifyEvent read FOnNewSocket write SetOnNewSocket;
  70.         property  OnRecv:TSockNotifyEvent read FOnRecv write SetOnRecv;
  71.         property  OnSend:TSockNotifyEvent read FOnSend write SetOnSend;
  72.         property  InternalProxyCount:Integer read FInternalProxyCount;
  73.         property  ExternalProxyCount:Integer read FExternalProxyCount;
  74.         function  RegisterSocket(sock:TProxySock;Direction:TSwitchDirection;InternalFlag:Boolean=false):Integer;
  75.         procedure UnregisterSocket(sock:TProxySock);
  76.         function  FindSocket(addr:TSockAddr):TProxySock;overload;
  77.         function  FindSocket(ip:String;port:WORD):TProxySock;overload;
  78.         function  FindSocketByTag(tag:Integer):TProxySock;
  79.         function  GetInternalProxy(index:Integer):TProxySock;
  80.         function  GetExternalProxy(index:Integer):TProxySock;
  81.         procedure SwitchPackage(buf:array of char;buflen:Integer;from:TSockAddr;Dest:TSockAddr;hint:TSwitchDirection);
  82.         constructor Create(primary:TProxySock);overload;
  83.         constructor Create(thisPort:Word;proxyAddr:String;proxyPort:Word);overload;
  84.         destructor  Destroy;override;
  85.         function  GetPrimarySocket:TProxySock;
  86.         end;
  87. implementation
  88. uses IpHdr;
  89. { TProxySock }
  90. constructor TProxySock.Create(aThisAddr, aProxyAddr: TSockAddr);
  91. begin
  92. Init;
  93. ThisAddr:=aThisAddr;
  94. ProxyAddr:=aProxyAddr;
  95. end;
  96. constructor TProxySock.Create(aProxyAddr: TSockAddr);
  97. begin
  98. Init;
  99. ThisAddr.sin_family:=AF_INET;
  100. ThisAddr.sin_addr.S_addr:=INADDR_ANY;
  101. ThisAddr.sin_port:=0;
  102. ProxyAddr:=aProxyAddr;
  103. CreateSocket;
  104. end;
  105. constructor TProxySock.Create(ThisPort: WORD; ProxyIp: String;
  106.   ProxyPort: WORD);
  107. begin
  108. Init;
  109. ThisAddr.sin_family:=AF_INET;
  110. ThisAddr.sin_addr.S_addr:=INADDR_ANY;
  111. ThisAddr.sin_port:=htons(ThisPort);
  112. ProxyAddr.sin_family:=AF_INET;
  113. ProxyAddr.sin_port:=htons(ProxyPort);
  114. LookupName(proxyIp,ProxyAddr.sin_addr);
  115. CreateSocket;
  116. end;
  117. constructor TProxySock.Create(ThisPort: WORD; aProxyAddr: TSockAddr);
  118. begin
  119. Init;
  120. ThisAddr.sin_family:=AF_INET;
  121. ThisAddr.sin_port:=htons(ThisPort);
  122. ThisAddr.sin_addr.S_addr:=INADDR_ANY;
  123. ProxyAddr:=aProxyAddr;
  124. CreateSocket;
  125. end;
  126. function TProxySock.CreateSocket: Boolean;
  127. begin
  128. FSocket:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  129. if(FSocket<>INVALID_SOCKET)then
  130.     begin
  131.     if(bind(FSocket,ThisAddr,SizeOf(ThisAddr))<>SOCKET_ERROR)then
  132.         begin
  133.         if(not StartThread)then
  134.             begin
  135.             closesocket(FSocket);
  136.             FSocket:=INVALID_SOCKET;
  137.             Result:=False;
  138.             end
  139.         else Result:=TRUE;
  140.         end
  141.     else
  142.         begin
  143.         closesocket(FSocket);
  144.         FSocket:=INVALID_SOCKET;
  145.         Result:=False;
  146.         end;
  147.     end
  148. else Result:=False;
  149. end;
  150. destructor TProxySock.Destroy;
  151. begin
  152. if(FSocket<>INVALID_SOCKET)then closesocket(FSocket);
  153. if(Assigned(FReadThread))then FReadThread.Terminate;
  154. if(FSwitcher<>nil)then FSwitcher.UnregisterSocket(self);
  155. inherited;
  156. end;
  157. procedure TProxySock.Init;
  158. begin
  159. FReadThread:=nil;
  160. FSocket:=INVALID_SOCKET;
  161. FSwitcher:=nil;
  162. end;
  163. procedure TProxySock.OnRecv(buf: array of char; buflen: Integer;
  164.   from: TSockAddr);
  165. var
  166. drop:Boolean;
  167. begin
  168. drop:=False;
  169. case FDirection of
  170.     sdSend:
  171.         begin
  172.         if(Assigned(FSwitcher) and Assigned(FSwitcher.FOnSend))then
  173.             FSwitcher.FOnSend(buf,buflen,from,ProxyAddr,drop);
  174.         end;
  175.     sdRecv:
  176.         begin
  177.         if(Assigned(FSwitcher)and Assigned(FSwitcher.FOnRecv))then
  178.             FSwitcher.FOnRecv(buf,buflen,from,ProxyAddr,drop);
  179.         end;
  180.     end;
  181. if((not drop) and (FSwitcher<>nil))then
  182.     begin
  183.     FSwitcher.SwitchPackage(buf,buflen,from,ProxyAddr,FDirection);
  184.     end;
  185. end;
  186. function TProxySock.SendBuf(buf: array of char; buflen: Integer;
  187.   Dest: TSockAddr): Boolean;
  188. begin
  189. if(FSocket<>INVALID_SOCKET)then
  190.     begin
  191.     Result:=(WinSock.sendto(FSocket,buf,buflen,0,Dest,SizeOf(Dest))<>SOCKET_ERROR);
  192.     end
  193. else Result:=False;
  194. end;
  195. function TProxySock.SendBuf(buf: array of char; buflen: Integer;
  196.   DestIp: String; DestPort: Word): Boolean;
  197. var
  198. addr:TSockAddr;
  199. begin
  200. addr.sin_family:=AF_INET;
  201. addr.sin_addr.S_addr:=inet_addr(PChar(DestIp));
  202. addr.sin_port:=DestPort;
  203. Result:=SendBuf(buf,buflen,addr);
  204. end;
  205. function TProxySock.StartThread: Boolean;
  206. begin
  207. try
  208.     FReadThread:=TProxyReadThread.Create(False,self);
  209.     Result:=True;
  210. except
  211.     Result:=False;
  212.     end;
  213. end;
  214. procedure TProxySock.StopThread;
  215. begin
  216. FReadThread.Terminate;
  217. end;
  218. { TUDPSwitcher }
  219. constructor TUDPSwitcher.Create(primary: TProxySock);
  220. begin
  221. FOnRecv:=nil;
  222. FOnSend:=nil;
  223. {$ifdef SYNC}
  224. FSockLock:=TMultiReadExclusiveWriteSynchronizer.Create;
  225. {$endif}
  226. RegisterSocket(primary,sdSend,true);
  227. end;
  228. constructor TUDPSwitcher.Create(thisPort: Word; proxyAddr: String;
  229.   proxyPort: Word);
  230. var
  231. s:TProxySock;
  232. begin
  233. FOnRecv:=nil;
  234. FOnSend:=nil;
  235. {$ifdef SYNC}
  236. FSockLock:=TMultiReadExclusiveWriteSynchronizer.Create;
  237. {$endif}
  238. s:=TProxySock.Create(thisPort,ProxyAddr,ProxyPort);
  239. RegisterSocket(s,sdSend,true);
  240. end;
  241. destructor TUDPSwitcher.Destroy;
  242. var
  243. i,len:Integer;
  244. begin
  245. len:=Length(FSockets);
  246. for i:=0 to len-1 do
  247.     begin
  248.     UnregisterSocket(FSockets[i]);
  249.     end;
  250. end;
  251. function TUDPSwitcher.FindSocket(addr: TSockAddr): TProxySock;
  252. var
  253. i,len:Integer;
  254. begin
  255. Result:=nil;
  256. {$ifdef SYNC}
  257. FSockLock.BeginRead;
  258. {$endif}
  259. len:=Length(FSockets);
  260. for i:=0 to len-1 do
  261.     begin
  262.     if((FSockets[i].ProxyAddr.sin_addr.S_addr=addr.sin_addr.S_addr)
  263.         and(FSockets[i].ProxyAddr.sin_port=addr.sin_port)
  264.         and(FSockets[i].ProxyAddr.sin_family=addr.sin_family))then
  265.         begin
  266.         Result:=FSockets[i];
  267.         end;
  268.     end;
  269. {$ifdef SYNC}
  270. FSockLock.EndRead;
  271. {$endif}
  272. end;
  273. function TUDPSwitcher.FindSocket(ip: String; port: WORD): TProxySock;
  274. var
  275. addr:TSockAddr;
  276. begin
  277. addr.sin_family:=AF_INET;
  278. addr.sin_addr.S_addr:=inet_addr(PChar(ip));
  279. addr.sin_port:=htons(port);
  280. Result:=FindSocket(addr);
  281. end;
  282. function TUDPSwitcher.FindSocketByTag(tag: Integer): TProxySock;
  283. var
  284. i,len:Integer;
  285. begin
  286. Result:=nil;
  287. len:=Length(FSockets);
  288. for i:=0 to len-1 do
  289.     begin
  290.     if(FSockets[i].Tag=tag)then
  291.         begin
  292.         Result:=FSockets[i];
  293.         end;
  294.     end;
  295. end;
  296. function TUDPSwitcher.GetExternalProxy(index: Integer): TProxySock;
  297. begin
  298. Result:=GetSocketByDirection(index,sdRecv);
  299. end;
  300. function TUDPSwitcher.GetInternalProxy(index: Integer): TProxySock;
  301. begin
  302. Result:=GetSocketByDirection(index,sdSend);
  303. end;
  304. function TUDPSwitcher.GetPrimarySocket: TProxySock;
  305. begin
  306. Result:=FSockets[0];
  307. end;
  308. function TUDPSwitcher.GetSocketByDirection(index: integer;
  309.   direction: TSwitchDirection): TProxySock;
  310. var
  311. cnt,i,len:Integer;
  312. begin
  313. Result:=nil;
  314. cnt:=0;
  315. len:=Length(FSockets);
  316. for i:=0 to len-1 do
  317.     begin
  318.     if(FSockets[i].FDirection=direction)then
  319.         begin
  320.         if(cnt=index)then
  321.             begin
  322.             Result:=FSockets[i];
  323.             Break;
  324.             end;
  325.         Inc(cnt);
  326.         end;
  327.     end;
  328. end;
  329. function TUDPSwitcher.RegisterSocket(sock: TProxySock;Direction:TSwitchDirection;InternalFlag:Boolean=false):Integer;
  330. var
  331. len,i:Integer;
  332. begin
  333. Result:=-1;
  334. {$ifdef SYNC}
  335. FSockLock.BeginWrite;
  336. {$endif}
  337. sock.FSwitcher:=self;
  338. sock.FDirection:=Direction;
  339. len:=Length(FSockets);
  340. for i:=0 to len-1 do
  341.     begin
  342.     if(FSockets[i]=nil)then
  343.         begin
  344.         FSockets[i]:=sock;
  345.         FInternalFlag[i]:=InternalFlag;
  346.         Result:=i;
  347.         end;
  348.     end;
  349. if(Result=-1)then
  350.     begin
  351.     SetLength(FSockets,len+1);
  352.     SetLength(FInternalFlag,len+1);
  353.     FSockets[len]:=sock;
  354.     FInternalFlag[len]:=InternalFlag;
  355.     Result:=len;
  356.     end;
  357. {$ifdef SYNC}
  358. FSockLock.EndWrite;
  359. {$endif}
  360. end;
  361. procedure TUDPSwitcher.SetOnNewSocket(const Value: TNotifyEvent);
  362. begin
  363.   FOnNewSocket := Value;
  364. end;
  365. procedure TUDPSwitcher.SetOnRecv(const Value: TSockNotifyEvent);
  366. begin
  367.   FOnRecv := Value;
  368. end;
  369. procedure TUDPSwitcher.SetOnSend(const Value: TSockNotifyEvent);
  370. begin
  371.   FOnSend := Value;
  372. end;
  373. procedure TUDPSwitcher.SwitchPackage(buf: array of char; buflen: Integer;
  374.   from, Dest: TSockAddr;hint:TSwitchDirection);
  375. var
  376. sock:TProxySock;
  377. begin
  378. sock:=FindSocket(from);
  379. if(sock=nil)then
  380.     begin
  381.     if(hint=sdSend)then hint:=sdRecv
  382.     else hint:=sdSend;
  383.     sock:=TProxySock.Create(from);
  384.     if(sock<>nil)then
  385.         begin
  386.         RegisterSocket(sock,hint,true);
  387.         if(Assigned(OnNewSocket))then  OnNewSocket(sock);
  388.         end;
  389.     end;
  390. sock.SendBuf(buf,buflen,Dest);
  391. end;
  392. procedure TUDPSwitcher.UnregisterSocket(sock: TProxySock);
  393. var
  394. i,len:Integer;
  395. begin
  396. {$ifdef SYNC}
  397. FSockLock.BeginWrite;
  398. {$endif}
  399. len:=Length(FSockets);
  400. sock.FSwitcher:=nil;
  401. for i:=0 to len-1 do
  402.     begin
  403.     if(FSockets[i]=sock)then
  404.         begin
  405.         if(FInternalFlag[i])then sock.Destroy;
  406.         FSockets[i]:=nil;
  407.         Break;
  408.         end;
  409.     end;
  410. {$ifdef SYNC}
  411. FSockLock.EndWrite;
  412. {$endif}
  413. end;
  414. { TProxyReadThread }
  415. constructor TProxyReadThread.Create(CreateSuspended: Boolean;
  416.   ASock: TProxySock);
  417. begin
  418. FreeOnTerminate := True;
  419. FProxySock:=ASock;
  420. inherited Create(CreateSuspended);
  421. end;
  422. destructor TProxyReadThread.Destroy;
  423. begin
  424. inherited;
  425. end;
  426. procedure TProxyReadThread.DoNotify;
  427. begin
  428. if(Assigned(FProxySock))then
  429.     FProxySock.OnRecv(FBuffer,FBuflen,FFromAddr);
  430. end;
  431. procedure TProxyReadThread.DoTerminate;
  432. begin
  433.   inherited;
  434. if(Assigned(FProxySock)
  435.     and Assigned(FProxySock.FReadThread)
  436.     and (FProxySock.FReadThread=self))then
  437.     begin
  438.     FProxySock.FReadThread:=nil;
  439.     end;
  440. end;
  441. procedure TProxyReadThread.Execute;
  442. var
  443. fromlen:Integer;
  444. begin
  445. while((not Terminated) and Assigned(FProxySock))do
  446.     begin
  447.     fromlen:=sizeof(FFromAddr);
  448.     FBufLen:=recvfrom(FProxySock.FSocket,FBuffer,2048,0,FFromAddr,fromlen);
  449.     if(FBuflen<>SOCKET_ERROR)then
  450.         begin
  451.         Synchronize(DoNotify);
  452.         end;
  453.     end;
  454. end;
  455. end.