pyflow-net 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PyFlow/__init__.py +4 -0
- PyFlow/__main__.py +4 -0
- PyFlow/command_control_extension_tcp.py +252 -0
- PyFlow/flow_setup.py +283 -0
- PyFlow/network_api/__init__.py +0 -0
- PyFlow/network_api/connect_tcp.py +3255 -0
- PyFlow/network_api/connect_udp.py +66 -0
- PyFlow/network_api/rsa_crypto.py +560 -0
- pyflow_net-0.1.0.dist-info/METADATA +7 -0
- pyflow_net-0.1.0.dist-info/RECORD +13 -0
- pyflow_net-0.1.0.dist-info/WHEEL +5 -0
- pyflow_net-0.1.0.dist-info/licenses/LICENSE +674 -0
- pyflow_net-0.1.0.dist-info/top_level.txt +1 -0
PyFlow/__init__.py
ADDED
PyFlow/__main__.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import ast
|
|
3
|
+
import json
|
|
4
|
+
import copy
|
|
5
|
+
import shlex
|
|
6
|
+
import shutil
|
|
7
|
+
import traceback
|
|
8
|
+
import threading
|
|
9
|
+
import subprocess
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from .network_api import connect_tcp
|
|
12
|
+
|
|
13
|
+
server_instance = None
|
|
14
|
+
client_instance = None
|
|
15
|
+
command_counter = {}
|
|
16
|
+
command_counter_lock = threading.Lock()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _load_json_file(path):
|
|
20
|
+
try:
|
|
21
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
22
|
+
data = json.load(f)
|
|
23
|
+
return data if isinstance(data, dict) else {}
|
|
24
|
+
except Exception:
|
|
25
|
+
return {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _merge_log_dicts(base_data, extra_data):
|
|
29
|
+
merged = {}
|
|
30
|
+
for command, entries in base_data.items():
|
|
31
|
+
merged[command] = list(entries) if isinstance(entries, list) else [entries]
|
|
32
|
+
for command, entries in extra_data.items():
|
|
33
|
+
if command not in merged:
|
|
34
|
+
merged[command] = []
|
|
35
|
+
if isinstance(entries, list):
|
|
36
|
+
merged[command].extend(entries)
|
|
37
|
+
else:
|
|
38
|
+
merged[command].append(entries)
|
|
39
|
+
return merged
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _merge_all_logs(log_dir, merged_filename="merged_logs.json"):
|
|
43
|
+
merged_data = {}
|
|
44
|
+
for filename in sorted(os.listdir(log_dir)):
|
|
45
|
+
if not filename.endswith(".json") or filename == merged_filename:
|
|
46
|
+
continue
|
|
47
|
+
file_path = os.path.join(log_dir, filename)
|
|
48
|
+
if os.path.isfile(file_path):
|
|
49
|
+
merged_data = _merge_log_dicts(merged_data, _load_json_file(file_path))
|
|
50
|
+
with open(os.path.join(log_dir, merged_filename), "w", encoding="utf-8") as f:
|
|
51
|
+
json.dump(merged_data, f, ensure_ascii=False, indent=2)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _setup_command():
|
|
55
|
+
print("Setting up server command...")
|
|
56
|
+
server_instance.register_command(
|
|
57
|
+
command_name="/command", handler=_command_handler, where_to_run="client", run_in_thread=True
|
|
58
|
+
)
|
|
59
|
+
server_instance.register_command(
|
|
60
|
+
command_name="/command_done",
|
|
61
|
+
handler=_command_done_dealing_server,
|
|
62
|
+
where_to_run="server",
|
|
63
|
+
run_in_thread=True,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _setup_client_command():
|
|
68
|
+
print("Setting up client command...")
|
|
69
|
+
client_instance.register_command(
|
|
70
|
+
command_name="/command",
|
|
71
|
+
handler=_command_handler_server_setup,
|
|
72
|
+
where_to_run="server",
|
|
73
|
+
run_in_thread=True,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _command_handler(sock, addr, cmd):
|
|
78
|
+
print(f"Received command from {addr}: {cmd}")
|
|
79
|
+
client_class = server_instance.clients
|
|
80
|
+
cmd_part = shlex.split(cmd)
|
|
81
|
+
del cmd_part[0] # Remove the command name
|
|
82
|
+
command_client_pair = []
|
|
83
|
+
clients_list = []
|
|
84
|
+
commands_list = []
|
|
85
|
+
clients_num = 0
|
|
86
|
+
for part in cmd_part:
|
|
87
|
+
if part.startswith("(") and part.endswith(")"):
|
|
88
|
+
try:
|
|
89
|
+
clients_num += 1
|
|
90
|
+
client_part = ast.literal_eval(part)
|
|
91
|
+
clients_list.append(client_part)
|
|
92
|
+
print(f"client part: {clients_list}")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
print(f"Error evaluating part '{part}': {e}")
|
|
95
|
+
else:
|
|
96
|
+
if clients_num != 0:
|
|
97
|
+
command_client_pair.append([commands_list, clients_list])
|
|
98
|
+
clients_num = 0
|
|
99
|
+
clients_list = []
|
|
100
|
+
commands_list = []
|
|
101
|
+
commands_list.append(part)
|
|
102
|
+
print(f"command part: {commands_list}")
|
|
103
|
+
if clients_num != 0:
|
|
104
|
+
print([commands_list, clients_list])
|
|
105
|
+
command_client_pair.append([commands_list, clients_list])
|
|
106
|
+
clients_num = 0
|
|
107
|
+
clients_list = []
|
|
108
|
+
commands_list = []
|
|
109
|
+
client_id = 0
|
|
110
|
+
for pair in command_client_pair:
|
|
111
|
+
for msg in pair[0]:
|
|
112
|
+
command_msg = (
|
|
113
|
+
"/command" + " " + shlex.quote(msg) + " " + shlex.quote(str(len(pair[0]))) + " "
|
|
114
|
+
)
|
|
115
|
+
for client in pair[1]:
|
|
116
|
+
temp_msg = (
|
|
117
|
+
command_msg
|
|
118
|
+
+ shlex.quote(str(client_id))
|
|
119
|
+
+ " "
|
|
120
|
+
+ shlex.quote(str(client))
|
|
121
|
+
+ "\n"
|
|
122
|
+
)
|
|
123
|
+
client_socket = client_class[client]["socket"]
|
|
124
|
+
server_instance.send_message(client_socket=client_socket, message=temp_msg)
|
|
125
|
+
print(f"Sending command to clients: {command_msg}")
|
|
126
|
+
client_id += 1
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _command_handler_server_setup(sock, addr, cmd):
|
|
130
|
+
global command_counter
|
|
131
|
+
print(f"Received command from {addr}: {cmd}")
|
|
132
|
+
try:
|
|
133
|
+
cmd_parts = shlex.split(cmd)
|
|
134
|
+
except Exception as e:
|
|
135
|
+
print(f"Error parsing command: {e}")
|
|
136
|
+
return
|
|
137
|
+
if len(cmd_parts) < 3 or cmd_parts[0] != "/command":
|
|
138
|
+
print("Invalid command format.")
|
|
139
|
+
return
|
|
140
|
+
command = cmd_parts[1]
|
|
141
|
+
client_addr = cmd_parts[4]
|
|
142
|
+
command_total_num = int(cmd_parts[2])
|
|
143
|
+
client_id = cmd_parts[3]
|
|
144
|
+
log_dir = os.path.join(os.path.dirname(__file__), "logs")
|
|
145
|
+
if not os.path.exists(log_dir):
|
|
146
|
+
os.makedirs(log_dir)
|
|
147
|
+
with command_counter_lock:
|
|
148
|
+
if str(client_id) not in command_counter:
|
|
149
|
+
command_counter[str(client_id)] = 1
|
|
150
|
+
else:
|
|
151
|
+
command_counter[str(client_id)] += 1
|
|
152
|
+
cmd_id = copy.copy(command_counter[str(client_id)])
|
|
153
|
+
log_filename = "logs{}.json".format("_" + str(client_id))
|
|
154
|
+
log_path = os.path.join(log_dir, log_filename)
|
|
155
|
+
try:
|
|
156
|
+
result = subprocess.run(command, capture_output=True, text=True, shell=True)
|
|
157
|
+
output = result.stdout.strip()
|
|
158
|
+
error = result.stderr.strip()
|
|
159
|
+
returncode = result.returncode
|
|
160
|
+
except Exception as e:
|
|
161
|
+
output = ""
|
|
162
|
+
error = str(e)
|
|
163
|
+
returncode = -1
|
|
164
|
+
log_line = {
|
|
165
|
+
"timestamp": datetime.now().isoformat(),
|
|
166
|
+
"command": command,
|
|
167
|
+
"cmd_id": str(cmd_id),
|
|
168
|
+
"client_id": str(client_id),
|
|
169
|
+
"client": client_addr,
|
|
170
|
+
"from": str(addr),
|
|
171
|
+
"output": output,
|
|
172
|
+
"error": error,
|
|
173
|
+
"returncode": returncode,
|
|
174
|
+
}
|
|
175
|
+
if os.path.exists(log_path):
|
|
176
|
+
with open(log_path, "r", encoding="utf-8") as f:
|
|
177
|
+
try:
|
|
178
|
+
log_data = json.load(f)
|
|
179
|
+
except Exception:
|
|
180
|
+
log_data = {}
|
|
181
|
+
else:
|
|
182
|
+
log_data = {}
|
|
183
|
+
if command not in log_data:
|
|
184
|
+
log_data[command] = []
|
|
185
|
+
log_data[command].append(log_line)
|
|
186
|
+
with open(log_path, "w", encoding="utf-8") as f:
|
|
187
|
+
json.dump(log_data, f, ensure_ascii=False, indent=2)
|
|
188
|
+
print(f"Log written to {log_path}")
|
|
189
|
+
msg = '/file "{}"'.format(log_path)
|
|
190
|
+
if cmd_id == command_total_num:
|
|
191
|
+
command_counter[str(client_id)] = 0
|
|
192
|
+
client_instance.file_transfer_client_recv_client_start(
|
|
193
|
+
message=msg, file_folder_abspath=None
|
|
194
|
+
)
|
|
195
|
+
client_instance.send_message(
|
|
196
|
+
client_socket=client_instance.client_socket,
|
|
197
|
+
message='/command_done "{}" "{}"'.format(log_filename, log_path),
|
|
198
|
+
)
|
|
199
|
+
else:
|
|
200
|
+
pass
|
|
201
|
+
print("Dealing the command successfully!")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _command_done_dealing_server(sock, addr, cmd):
|
|
205
|
+
cmd_parts = shlex.split(cmd)
|
|
206
|
+
log_filename = cmd_parts[1]
|
|
207
|
+
log_path = cmd_parts[2]
|
|
208
|
+
log_dir = os.path.join(os.path.dirname(__file__), "logs")
|
|
209
|
+
os.makedirs(log_dir, exist_ok=True)
|
|
210
|
+
received_log_file = os.path.join(server_instance.file_transfer_dir, os.path.basename(log_path))
|
|
211
|
+
destination_log_file = os.path.join(log_dir, log_filename)
|
|
212
|
+
try:
|
|
213
|
+
if os.path.exists(destination_log_file):
|
|
214
|
+
existing_logs = _load_json_file(destination_log_file)
|
|
215
|
+
incoming_logs = _load_json_file(received_log_file)
|
|
216
|
+
merged_logs = _merge_log_dicts(existing_logs, incoming_logs)
|
|
217
|
+
with open(destination_log_file, "w", encoding="utf-8") as f:
|
|
218
|
+
json.dump(merged_logs, f, ensure_ascii=False, indent=2)
|
|
219
|
+
os.remove(received_log_file)
|
|
220
|
+
else:
|
|
221
|
+
shutil.move(received_log_file, destination_log_file)
|
|
222
|
+
_merge_all_logs(log_dir)
|
|
223
|
+
print("Command Done!")
|
|
224
|
+
except Exception:
|
|
225
|
+
traceback.print_exc()
|
|
226
|
+
print("ErrorWhileMovingTheLogFile: moving log file failed.")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def client_setup():
|
|
230
|
+
global client_instance
|
|
231
|
+
client_instance = connect_tcp.TCP_Client_Base(
|
|
232
|
+
host="127.0.0.1",
|
|
233
|
+
port=65000,
|
|
234
|
+
client_host="127.0.0.1",
|
|
235
|
+
is_input_command_in_console=True,
|
|
236
|
+
is_extend_command=True,
|
|
237
|
+
)
|
|
238
|
+
_setup_client_command()
|
|
239
|
+
client_instance.start_TCP_client()
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def server_setup():
|
|
243
|
+
global server_instance
|
|
244
|
+
server_instance = connect_tcp.TCP_Server_Base(
|
|
245
|
+
host="127.0.0.1",
|
|
246
|
+
port=65000,
|
|
247
|
+
max_clients=10,
|
|
248
|
+
is_input_command_in_console=True,
|
|
249
|
+
is_extend_command=True,
|
|
250
|
+
)
|
|
251
|
+
_setup_command()
|
|
252
|
+
server_instance.start_TCP_Server()
|
PyFlow/flow_setup.py
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
4
|
+
import shutil
|
|
5
|
+
import platform
|
|
6
|
+
import tempfile
|
|
7
|
+
import argparse
|
|
8
|
+
import subprocess
|
|
9
|
+
import traceback
|
|
10
|
+
from .network_api.connect_tcp import TCP_Server_Base, TCP_Client_Base
|
|
11
|
+
|
|
12
|
+
SERVER_DEFAULTS = {
|
|
13
|
+
"host": "127.0.0.1",
|
|
14
|
+
"port": 65432,
|
|
15
|
+
"max_clients": 10,
|
|
16
|
+
"port_add_step": 1,
|
|
17
|
+
"port_range_num": 100,
|
|
18
|
+
"max_file_transfer_thread_num": 10,
|
|
19
|
+
"is_hand_alloc_port": False,
|
|
20
|
+
"is_input_command_in_console": True,
|
|
21
|
+
"max_custom_workers": 10,
|
|
22
|
+
"is_extend_command": False,
|
|
23
|
+
"is_enable_encrypto": True,
|
|
24
|
+
"is_custom_keys": None,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
CLIENT_DEFAULTS = {
|
|
28
|
+
"host": None,
|
|
29
|
+
"client_host": "127.0.0.1",
|
|
30
|
+
"port": 65432,
|
|
31
|
+
"client_port": None,
|
|
32
|
+
"timeout": None,
|
|
33
|
+
"port_add_step": 1,
|
|
34
|
+
"max_thread_num": 10,
|
|
35
|
+
"is_input_command_in_console": True,
|
|
36
|
+
"is_wait_server": True,
|
|
37
|
+
"max_custom_workers": 10,
|
|
38
|
+
"is_extend_command": False,
|
|
39
|
+
"is_enable_encrypto": True,
|
|
40
|
+
"is_custom_keys": None,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def parse_addr_port(addr_port):
|
|
45
|
+
host, port_str = addr_port.strip().split(":")
|
|
46
|
+
return host, int(port_str)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def load_existing_config():
|
|
50
|
+
if os.path.exists("setup.json"):
|
|
51
|
+
with open("setup.json", "r", encoding="utf-8") as f:
|
|
52
|
+
return json.load(f)
|
|
53
|
+
return {"servers": [], "clients": []}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def complete_server_config(cfg):
|
|
57
|
+
full = SERVER_DEFAULTS.copy()
|
|
58
|
+
full.update(cfg)
|
|
59
|
+
return full
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def complete_client_config(cfg):
|
|
63
|
+
full = CLIENT_DEFAULTS.copy()
|
|
64
|
+
full.update(cfg)
|
|
65
|
+
return full
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def save_config(servers, clients):
|
|
69
|
+
if servers:
|
|
70
|
+
servers = [servers[-1]]
|
|
71
|
+
else:
|
|
72
|
+
servers = []
|
|
73
|
+
if clients:
|
|
74
|
+
clients = [clients[-1]]
|
|
75
|
+
else:
|
|
76
|
+
clients = []
|
|
77
|
+
data = {
|
|
78
|
+
"servers": [complete_server_config(cfg) for cfg in servers],
|
|
79
|
+
"clients": [complete_client_config(cfg) for cfg in clients],
|
|
80
|
+
}
|
|
81
|
+
with open("setup.json", "w", encoding="utf-8") as f:
|
|
82
|
+
json.dump(data, f, indent=4, ensure_ascii=False)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def launch_instance(config, instance_type):
|
|
86
|
+
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False, encoding="utf-8") as f:
|
|
87
|
+
json.dump(config, f)
|
|
88
|
+
config_file_path = f.name
|
|
89
|
+
script = os.path.abspath(__file__)
|
|
90
|
+
python = sys.executable
|
|
91
|
+
launch_arg = f"--launch_{instance_type}"
|
|
92
|
+
system = platform.system()
|
|
93
|
+
try:
|
|
94
|
+
if system == "Windows":
|
|
95
|
+
cmd = f'start cmd /k {python} {script} {launch_arg} --config-file "{config_file_path}"'
|
|
96
|
+
subprocess.Popen(cmd, shell=True)
|
|
97
|
+
elif system == "Linux":
|
|
98
|
+
terminals = ["gnome-terminal", "xterm", "x-terminal-emulator"]
|
|
99
|
+
launched = False
|
|
100
|
+
for term in terminals:
|
|
101
|
+
if shutil.which(term):
|
|
102
|
+
cmd = f'{term} -- {python} {script} {launch_arg} --config-file "{config_file_path}"'
|
|
103
|
+
subprocess.Popen(cmd, shell=True)
|
|
104
|
+
launched = True
|
|
105
|
+
break
|
|
106
|
+
if not launched:
|
|
107
|
+
subprocess.Popen(
|
|
108
|
+
[python, script, launch_arg, "--config-file", config_file_path],
|
|
109
|
+
stdout=subprocess.DEVNULL,
|
|
110
|
+
stderr=subprocess.DEVNULL,
|
|
111
|
+
stdin=subprocess.DEVNULL,
|
|
112
|
+
start_new_session=True,
|
|
113
|
+
)
|
|
114
|
+
elif system == "Darwin":
|
|
115
|
+
cmd = f'open -a Terminal.app {python} {script} {launch_arg} --config-file "{config_file_path}"'
|
|
116
|
+
subprocess.Popen(cmd, shell=True)
|
|
117
|
+
else:
|
|
118
|
+
subprocess.Popen(
|
|
119
|
+
[python, script, launch_arg, "--config-file", config_file_path],
|
|
120
|
+
stdout=subprocess.DEVNULL,
|
|
121
|
+
stderr=subprocess.DEVNULL,
|
|
122
|
+
stdin=subprocess.DEVNULL,
|
|
123
|
+
start_new_session=True,
|
|
124
|
+
)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
print(f"Failed to launch instance: {e}")
|
|
127
|
+
traceback.print_exc()
|
|
128
|
+
try:
|
|
129
|
+
os.unlink(config_file_path)
|
|
130
|
+
except:
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def interactive_collect():
|
|
135
|
+
servers = []
|
|
136
|
+
clients = []
|
|
137
|
+
while True:
|
|
138
|
+
print("\n--- Add New Instance ---")
|
|
139
|
+
while True:
|
|
140
|
+
type_choice = input("Select type (0=Server, 1=Client): ").strip()
|
|
141
|
+
if type_choice in ("0", "1"):
|
|
142
|
+
break
|
|
143
|
+
print("Invalid input, please enter 0 or 1")
|
|
144
|
+
is_server = type_choice == "0"
|
|
145
|
+
while True:
|
|
146
|
+
setup_addr = input("Enter bind address and port (format host:port): ").strip()
|
|
147
|
+
try:
|
|
148
|
+
host, port = parse_addr_port(setup_addr)
|
|
149
|
+
break
|
|
150
|
+
except:
|
|
151
|
+
print("Invalid format, please retry")
|
|
152
|
+
if is_server:
|
|
153
|
+
config = {"host": host, "port": port}
|
|
154
|
+
servers = [config]
|
|
155
|
+
print(f"Server config set to: {host}:{port}")
|
|
156
|
+
else:
|
|
157
|
+
while True:
|
|
158
|
+
conn_addr = input(
|
|
159
|
+
"Enter server address and port to connect (format host:port): "
|
|
160
|
+
).strip()
|
|
161
|
+
try:
|
|
162
|
+
srv_host, srv_port = parse_addr_port(conn_addr)
|
|
163
|
+
break
|
|
164
|
+
except:
|
|
165
|
+
print("Invalid format, please retry")
|
|
166
|
+
config = {"client_host": host, "client_port": port, "host": srv_host, "port": srv_port}
|
|
167
|
+
clients = [config]
|
|
168
|
+
print(f"Client config set to: local {host}:{port} -> server {srv_host}:{srv_port}")
|
|
169
|
+
cont = input("Continue adding more instances? (Y/N): ").strip().lower()
|
|
170
|
+
if cont != "y":
|
|
171
|
+
break
|
|
172
|
+
return servers, clients
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def generate_configs_from_args(args):
|
|
176
|
+
if args.setup_num > 1:
|
|
177
|
+
print("Warning: --setup_num is ignored because only one instance per type is allowed.")
|
|
178
|
+
host, port = parse_addr_port(args.setup_addr_port)
|
|
179
|
+
if args.type == 0:
|
|
180
|
+
config = {"host": host, "port": port}
|
|
181
|
+
return [config], []
|
|
182
|
+
else:
|
|
183
|
+
srv_host, srv_port = parse_addr_port(args.connect_addr_port)
|
|
184
|
+
config = {"client_host": host, "client_port": port, "host": srv_host, "port": srv_port}
|
|
185
|
+
return [], [config]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def run_launched_instance(instance_type, config_file_path):
|
|
189
|
+
try:
|
|
190
|
+
with open(config_file_path, "r", encoding="utf-8") as f:
|
|
191
|
+
config = json.load(f)
|
|
192
|
+
try:
|
|
193
|
+
os.unlink(config_file_path)
|
|
194
|
+
except:
|
|
195
|
+
pass
|
|
196
|
+
if instance_type == "server":
|
|
197
|
+
server = TCP_Server_Base(**config)
|
|
198
|
+
else:
|
|
199
|
+
client = TCP_Client_Base(**config)
|
|
200
|
+
except Exception as e:
|
|
201
|
+
print(f"Failed to start instance: {e}")
|
|
202
|
+
traceback.print_exc()
|
|
203
|
+
input("Press any key to exit...")
|
|
204
|
+
sys.exit(1)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main():
|
|
208
|
+
if "--launch_server" in sys.argv:
|
|
209
|
+
idx = sys.argv.index("--launch_server")
|
|
210
|
+
try:
|
|
211
|
+
cfg_idx = sys.argv.index("--config-file", idx)
|
|
212
|
+
if cfg_idx + 1 < len(sys.argv):
|
|
213
|
+
config_file = sys.argv[cfg_idx + 1]
|
|
214
|
+
run_launched_instance("server", config_file)
|
|
215
|
+
else:
|
|
216
|
+
print("Error: missing --config-file argument")
|
|
217
|
+
sys.exit(1)
|
|
218
|
+
except ValueError:
|
|
219
|
+
print("Error: missing --config-file argument")
|
|
220
|
+
sys.exit(1)
|
|
221
|
+
return
|
|
222
|
+
if "--launch_client" in sys.argv:
|
|
223
|
+
idx = sys.argv.index("--launch_client")
|
|
224
|
+
try:
|
|
225
|
+
cfg_idx = sys.argv.index("--config-file", idx)
|
|
226
|
+
if cfg_idx + 1 < len(sys.argv):
|
|
227
|
+
config_file = sys.argv[cfg_idx + 1]
|
|
228
|
+
run_launched_instance("client", config_file)
|
|
229
|
+
else:
|
|
230
|
+
print("Error: missing --config-file argument")
|
|
231
|
+
sys.exit(1)
|
|
232
|
+
except ValueError:
|
|
233
|
+
print("Error: missing --config-file argument")
|
|
234
|
+
sys.exit(1)
|
|
235
|
+
return
|
|
236
|
+
parser = argparse.ArgumentParser(description="Flow Setup Launcher")
|
|
237
|
+
parser.add_argument("--type", type=int, choices=[0, 1], help="0=Server, 1=Client")
|
|
238
|
+
parser.add_argument("--setup_addr_port", type=str, help="Bind address and port (host:port)")
|
|
239
|
+
parser.add_argument(
|
|
240
|
+
"--connect_addr_port", type=str, help="Server address and port to connect (client required)"
|
|
241
|
+
)
|
|
242
|
+
parser.add_argument(
|
|
243
|
+
"--setup_num", type=int, default=1, help="Number of instances to launch (only 1 is allowed)"
|
|
244
|
+
)
|
|
245
|
+
args = parser.parse_args()
|
|
246
|
+
if args.type is not None:
|
|
247
|
+
if args.type == 0 and args.connect_addr_port is not None:
|
|
248
|
+
print("Error: --connect_addr_port cannot be used in Server mode")
|
|
249
|
+
sys.exit(1)
|
|
250
|
+
if args.type == 1 and (args.setup_addr_port is None or args.connect_addr_port is None):
|
|
251
|
+
print("Error: Client mode requires both --setup_addr_port and --connect_addr_port")
|
|
252
|
+
sys.exit(1)
|
|
253
|
+
if args.type == 0 and args.setup_addr_port is None:
|
|
254
|
+
print("Error: Server mode requires --setup_addr_port")
|
|
255
|
+
sys.exit(1)
|
|
256
|
+
servers, clients = generate_configs_from_args(args)
|
|
257
|
+
save_config(servers, clients)
|
|
258
|
+
for cfg in servers:
|
|
259
|
+
launch_instance(cfg, "server")
|
|
260
|
+
for cfg in clients:
|
|
261
|
+
launch_instance(cfg, "client")
|
|
262
|
+
return
|
|
263
|
+
if os.path.exists("setup.json"):
|
|
264
|
+
choice = input("setup.json exists. Overwrite configuration data? (Y/N): ").strip().lower()
|
|
265
|
+
if choice == "n":
|
|
266
|
+
config_data = load_existing_config()
|
|
267
|
+
for cfg in config_data.get("servers", []):
|
|
268
|
+
launch_instance(cfg, "server")
|
|
269
|
+
for cfg in config_data.get("clients", []):
|
|
270
|
+
launch_instance(cfg, "client")
|
|
271
|
+
return
|
|
272
|
+
else:
|
|
273
|
+
choice = "y"
|
|
274
|
+
servers, clients = interactive_collect()
|
|
275
|
+
save_config(servers, clients)
|
|
276
|
+
for cfg in servers:
|
|
277
|
+
launch_instance(cfg, "server")
|
|
278
|
+
for cfg in clients:
|
|
279
|
+
launch_instance(cfg, "client")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
if __name__ == "__main__":
|
|
283
|
+
main()
|
|
File without changes
|