126 lines
3.5 KiB
Python
126 lines
3.5 KiB
Python
import threading
|
|
import uuid
|
|
|
|
from utils import *
|
|
|
|
client_token = f"client_{uuid.uuid4().hex[:8]}"
|
|
my_charactor = "client"
|
|
client_name = 'awin_client'
|
|
|
|
server_name = 'awin_server'
|
|
service_name = 'alist'
|
|
|
|
co_server = 'www.awin-x.top'
|
|
co_port = 5000
|
|
|
|
co_server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
co_server_sock.connect((co_server, co_port))
|
|
|
|
listen_port = 12345
|
|
listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
listen_sock.bind(('0.0.0.0', listen_port))
|
|
listen_sock.listen(5)
|
|
|
|
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
udp_sock.bind(('0.0.0.0', 0))
|
|
tcp_port = udp_sock.getsockname()[1]
|
|
|
|
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
|
|
conns = {}
|
|
|
|
|
|
def client_thread(conn_id):
|
|
client_sock = conns[conn_id]['client_sock']
|
|
while True:
|
|
data = client_sock.recv(4096)
|
|
send_data_tcp(server_sock, data, {'conn_id': conn_id})
|
|
|
|
|
|
def tcp_accept_thread():
|
|
while True:
|
|
client_sock, client_addr = listen_sock.accept()
|
|
conn_id = f"conn_{uuid.uuid4().hex[:8]}"
|
|
conns[conn_id] = {
|
|
'client_sock': client_sock,
|
|
'client_addr': client_addr,
|
|
'ready': False
|
|
}
|
|
send_action_tcp(server_sock, 'connect_service', {
|
|
'service': service_name,
|
|
'conn_id': conn_id,
|
|
'client_addr': client_addr,
|
|
'client_name': client_name
|
|
})
|
|
count = 0
|
|
while not conns[conn_id]['ready']:
|
|
if count > 50:
|
|
send_action_tcp(server_sock, 'disconnect_service', {
|
|
'conn_id': conn_id
|
|
})
|
|
break
|
|
time.sleep(0.1)
|
|
threading.Thread(target=client_thread, args=conn_id).start()
|
|
|
|
|
|
def handle_data(conn_id, data):
|
|
conns[conn_id]['client_sock'].sendall(data)
|
|
|
|
|
|
def server_thread():
|
|
global client_name, client_token
|
|
send_action_tcp(server_sock, 'client_hello', {
|
|
'client_name': client_name,
|
|
'client_token': client_token
|
|
})
|
|
while True:
|
|
action, message, data = recv_tcp(server_sock)
|
|
if action == 'error':
|
|
print(message['message'])
|
|
elif action == 'data':
|
|
handle_data(message['conn_id'], data)
|
|
elif action == 'bye':
|
|
break
|
|
server_sock.close()
|
|
print("bye, from server")
|
|
exit()
|
|
|
|
|
|
def main():
|
|
send_action_tcp(co_server_sock, 'client_hello', {
|
|
'name': client_name,
|
|
'token': client_token,
|
|
'charactor': my_charactor,
|
|
})
|
|
send_action_tcp(co_server_sock, 'punch_request', {
|
|
'server_name': 'awin_server'
|
|
})
|
|
action, message, data = recv_tcp(co_server_sock)
|
|
if action == 'punch_request':
|
|
co_server_punch_port = message['co_server_punch_port']
|
|
else:
|
|
print('punch request failed')
|
|
return
|
|
print(f'暴露端口:{tcp_port}->{(co_server, co_server_punch_port)}')
|
|
packed = pack_data(action='client_punch_port')
|
|
for i in range(5):
|
|
udp_sock.sendto(packed, (co_server, co_server_punch_port))
|
|
time.sleep(0.1)
|
|
action, message, data = recv_tcp(co_server_sock)
|
|
if action == 'punch_to':
|
|
target_addr = tuple(message['target_addr'])
|
|
print(f'打洞到{target_addr}')
|
|
udp_sock.close()
|
|
server_sock.bind(('0.0.0.0', tcp_port))
|
|
server_sock.connect(target_addr)
|
|
threading.Thread(target=server_thread, daemon=True).start()
|
|
else:
|
|
print(action)
|
|
print('punch to failed')
|
|
return
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|