11from socketserver import BaseRequestHandler , TCPServer
2- from socket import socket , AF_INET , SOCK_STREAM
2+ from socket import socket , AF_INET , SOCK_STREAM , gethostbyname , error
33import threading
44import logging
55from enum import Enum , auto
6-
6+ import fcntl , os
7+ import errno
8+ import time
79
810class ProxyType (Enum ):
911 TCP = auto ()
@@ -23,25 +25,42 @@ class TcpProxySockHandler(BaseRequestHandler):
2325
2426 def handle (self ):
2527 # self.request is the TCP socket connected to the client
26- self .data = self .request .recv (1024 )
27- self .Logger .info ("Passing data from: {}" .format (self .client_address [0 ]))
28-
28+ self .Logger .info ("Passing data from: %s -> %s:%s" % (self .client_address [0 ], self .PROXY_HOST , self .PROXY_PORT ))
2929 # Create a socket to the localhost server
3030 sock = socket (AF_INET , SOCK_STREAM )
3131 # Try to connect to the server and send data
3232 try :
3333 sock .connect ((self .PROXY_HOST , self .PROXY_PORT ))
34- sock . sendall (self .data )
34+ self . transferData (self .request , sock )
3535 # Receive data from the server
36- while 1 :
37- received = sock .recv (1024 )
38- if not received :
39- break
40- # Send back received data
41- self .request .sendall (received )
36+ self .Logger .info ("Receive data: %s <- %s:%s" % (self .client_address [0 ], self .PROXY_HOST , self .PROXY_PORT ))
37+ self .transferData (sock , self .request )
4238 finally :
4339 sock .close ()
4440
41+ def transferData (self , sock1 : socket , sock2 : socket , max_read_try = 1 , receive_message_length = 4096 ):
42+ read_try = 0
43+ fcntl .fcntl (sock1 , fcntl .F_SETFL , os .O_NONBLOCK )
44+ while True :
45+ try :
46+ msg = sock1 .recv (receive_message_length )
47+ if not msg :
48+ break
49+ sock2 .sendall (msg )
50+ if len (msg ) < receive_message_length :
51+ return
52+ except error as e :
53+ err = e .args [0 ]
54+ if err == errno .EAGAIN or err == errno .EWOULDBLOCK :
55+ if read_try > max_read_try :
56+ return
57+ read_try += 1
58+ time .sleep (1 )
59+ continue
60+ raise e
61+
62+
63+
4564
4665class ProxyServer ():
4766
@@ -55,7 +74,7 @@ def __init__(self, proxy_host, proxy_port, type=ProxyType.TCP):
5574 HOST = "127.0.0.1"
5675
5776 class ThreadedTcpProxyHandler (TcpProxySockHandler ):
58- PROXY_HOST = proxy_host
77+ PROXY_HOST = gethostbyname ( proxy_host )
5978 PROXY_PORT = proxy_port
6079
6180 self .server = TCPServer ((HOST , proxy_port ), ThreadedTcpProxyHandler )
0 commit comments