Skip to content

Instantly share code, notes, and snippets.

@lmyyao
Created September 24, 2024 07:36
Show Gist options
  • Save lmyyao/9957f204ae5bc978d39099eef24555a7 to your computer and use it in GitHub Desktop.
Save lmyyao/9957f204ae5bc978d39099eef24555a7 to your computer and use it in GitHub Desktop.
splice system call implement socket proxy
import socket
import select
import os
import fcntl
import threading
buffer_size = 1024
def thread_worker(client, pair):
print(f"thread worker: {client}")
fcntl.fcntl(client, fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(pair, fcntl.F_SETFL, os.O_NONBLOCK)
c = client.fileno()
p = pair.fileno()
rp, wp = os.pipe()
flags = os.SPLICE_F_MORE
while 1:
print("xxx")
r, *_ = select.select([client, pair], [], [])
print(r)
break_flag = False
for s in r:
if s == client:
size = os.splice(c, wp, buffer_size, flags=flags)
os.splice(rp, p, size)
if size == 0:
break_flag = True
continue
if s == pair:
size = os.splice(p, wp, buffer_size, flags=flags)
os.splice(rp, c, size)
if size == 0:
break_flag = True
continue
if break_flag:
client.close()
pair.close()
break
# must close
os.close(rp)
os.close(wp)
print("thread end")
class ProxyServer:
def __init__(self, host, port, listen):
self.host = host
self.port = port
self.listen = listen
def connect_host(self):
s = socket.socket()
s.connect((self.host, self.port))
return s
def server(self):
server = socket.socket()
server.bind(("", self.listen))
server.listen()
while 1:
client, addr = server.accept()
print(f"info: {client}")
pair = self.connect_host()
t = threading.Thread(target=thread_worker, args=(client, pair))
t.start()
if __name__ == "__main__":
ProxyServer("localhost", 8000, 7777).server()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment