lanet 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/Gemfile.lock +1 -1
- data/README.md +163 -18
- data/index.html +388 -16
- data/lib/lanet/cli.rb +95 -14
- data/lib/lanet/file_transfer.rb +308 -0
- data/lib/lanet/scanner.rb +101 -135
- data/lib/lanet/version.rb +1 -1
- data/lib/lanet.rb +36 -27
- metadata +3 -2
data/index.html
CHANGED
@@ -9,9 +9,10 @@
|
|
9
9
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
10
10
|
line-height: 1.6;
|
11
11
|
color: #333;
|
12
|
-
max-width:
|
12
|
+
max-width: 960px;
|
13
13
|
margin: 0 auto;
|
14
14
|
padding: 20px;
|
15
|
+
background-color: #f9f9f9;
|
15
16
|
}
|
16
17
|
h1 {
|
17
18
|
color: #2c3e50;
|
@@ -22,21 +23,30 @@
|
|
22
23
|
color: #2980b9;
|
23
24
|
margin-top: 30px;
|
24
25
|
}
|
26
|
+
h3 {
|
27
|
+
color: #16a085;
|
28
|
+
margin-top: 25px;
|
29
|
+
}
|
30
|
+
h4 {
|
31
|
+
color: #27ae60;
|
32
|
+
margin-top: 20px;
|
33
|
+
}
|
25
34
|
pre {
|
26
35
|
background-color: #f8f8f8;
|
27
36
|
border: 1px solid #ddd;
|
28
37
|
border-left: 3px solid #3498db;
|
29
38
|
padding: 15px;
|
30
39
|
overflow-x: auto;
|
40
|
+
border-radius: 4px;
|
31
41
|
}
|
32
42
|
code {
|
33
43
|
font-family: 'Courier New', Courier, monospace;
|
34
44
|
}
|
35
45
|
.container {
|
36
46
|
background-color: #fff;
|
37
|
-
border-radius:
|
38
|
-
box-shadow: 0 2px
|
39
|
-
padding:
|
47
|
+
border-radius: 8px;
|
48
|
+
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
|
49
|
+
padding: 30px;
|
40
50
|
}
|
41
51
|
.feature {
|
42
52
|
margin: 20px 0;
|
@@ -47,6 +57,82 @@
|
|
47
57
|
background-color: #e8f4fc;
|
48
58
|
padding: 15px;
|
49
59
|
margin: 10px 0;
|
60
|
+
border-radius: 6px;
|
61
|
+
}
|
62
|
+
.cli-example {
|
63
|
+
background-color: #2c3e50;
|
64
|
+
color: #ecf0f1;
|
65
|
+
padding: 12px 18px;
|
66
|
+
margin: 10px 0;
|
67
|
+
border-radius: 6px;
|
68
|
+
font-family: 'Courier New', Courier, monospace;
|
69
|
+
position: relative;
|
70
|
+
}
|
71
|
+
.cli-example::before {
|
72
|
+
content: "$";
|
73
|
+
color: #3498db;
|
74
|
+
margin-right: 10px;
|
75
|
+
font-weight: bold;
|
76
|
+
}
|
77
|
+
.cli-section {
|
78
|
+
margin-bottom: 30px;
|
79
|
+
background-color: #f8f9fa;
|
80
|
+
padding: 20px;
|
81
|
+
border-radius: 6px;
|
82
|
+
}
|
83
|
+
.output-example {
|
84
|
+
background-color: #f0f0f0;
|
85
|
+
padding: 12px;
|
86
|
+
margin: 10px 0;
|
87
|
+
border-radius: 6px;
|
88
|
+
font-family: 'Courier New', Courier, monospace;
|
89
|
+
font-size: 0.9em;
|
90
|
+
border-left: 3px solid #9b59b6;
|
91
|
+
}
|
92
|
+
.tab-container {
|
93
|
+
border: 1px solid #ddd;
|
94
|
+
border-radius: 6px;
|
95
|
+
overflow: hidden;
|
96
|
+
margin: 20px 0;
|
97
|
+
}
|
98
|
+
.tab-buttons {
|
99
|
+
display: flex;
|
100
|
+
background-color: #f5f5f5;
|
101
|
+
}
|
102
|
+
.tab-button {
|
103
|
+
padding: 10px 20px;
|
104
|
+
background-color: transparent;
|
105
|
+
border: none;
|
106
|
+
cursor: pointer;
|
107
|
+
border-right: 1px solid #ddd;
|
108
|
+
transition: background-color 0.3s;
|
109
|
+
}
|
110
|
+
.tab-button:hover, .tab-button.active {
|
111
|
+
background-color: #e0e0e0;
|
112
|
+
}
|
113
|
+
.tab-content {
|
114
|
+
display: none;
|
115
|
+
padding: 15px;
|
116
|
+
}
|
117
|
+
.tab-content.active {
|
118
|
+
display: block;
|
119
|
+
}
|
120
|
+
.badge {
|
121
|
+
display: inline-block;
|
122
|
+
padding: 3px 8px;
|
123
|
+
border-radius: 4px;
|
124
|
+
font-size: 12px;
|
125
|
+
font-weight: bold;
|
126
|
+
}
|
127
|
+
.badge-new {
|
128
|
+
background-color: #2ecc71;
|
129
|
+
color: white;
|
130
|
+
}
|
131
|
+
.note {
|
132
|
+
background-color: #fff8e1;
|
133
|
+
padding: 12px;
|
134
|
+
border-left: 4px solid #ffc107;
|
135
|
+
margin: 10px 0;
|
50
136
|
border-radius: 4px;
|
51
137
|
}
|
52
138
|
</style>
|
@@ -54,17 +140,17 @@
|
|
54
140
|
<body>
|
55
141
|
<div class="container">
|
56
142
|
<h1>Lanet</h1>
|
57
|
-
<p>A secure network communication library
|
143
|
+
<p>A secure network communication library that enables reliable and protected message exchange between devices on the same network.</p>
|
58
144
|
|
59
145
|
<h2>Key Features</h2>
|
60
146
|
|
61
147
|
<div class="feature">
|
62
148
|
<h3>Encrypted Communication</h3>
|
63
|
-
<p>Protect your messages with
|
149
|
+
<p>Protect your messages with AES-256-CBC encryption to ensure confidentiality during transmission.</p>
|
64
150
|
</div>
|
65
151
|
|
66
152
|
<div class="feature">
|
67
|
-
<h3>Digital Signatures</h3>
|
153
|
+
<h3>Digital Signatures <span class="badge badge-new">New in v0.2.1</span></h3>
|
68
154
|
<p>Verify message authenticity and integrity with RSA-based digital signatures.</p>
|
69
155
|
|
70
156
|
<div class="security-feature">
|
@@ -79,18 +165,205 @@
|
|
79
165
|
</div>
|
80
166
|
|
81
167
|
<div class="feature">
|
82
|
-
<h3>
|
83
|
-
<p>
|
168
|
+
<h3>Network Discovery</h3>
|
169
|
+
<p>Automatically find active devices on your local network with advanced scanning capabilities.</p>
|
84
170
|
</div>
|
85
171
|
|
86
172
|
<div class="feature">
|
87
|
-
<h3>
|
88
|
-
<p>
|
173
|
+
<h3>Broadcasting</h3>
|
174
|
+
<p>Send messages to all devices on your network simultaneously.</p>
|
175
|
+
</div>
|
176
|
+
|
177
|
+
<div class="feature">
|
178
|
+
<h3>File Transfer <span class="badge badge-new">New in v0.3.0</span></h3>
|
179
|
+
<p>Securely transfer files between devices with encryption, digital signatures, and integrity verification.</p>
|
180
|
+
</div>
|
181
|
+
|
182
|
+
<h2>Command Line Interface</h2>
|
183
|
+
|
184
|
+
<div class="note">
|
185
|
+
<strong>Note:</strong> All Lanet commands have detailed help available. Try <code>lanet [command] --help</code> for more options.
|
89
186
|
</div>
|
90
187
|
|
91
|
-
<
|
188
|
+
<div class="cli-section">
|
189
|
+
<h3>Digital Signature Commands <span class="badge badge-new">New in v0.2.1</span></h3>
|
190
|
+
|
191
|
+
<h4>Generate a Key Pair</h4>
|
192
|
+
<p>Create RSA keys for signing and verifying messages:</p>
|
193
|
+
<div class="cli-example">
|
194
|
+
lanet keygen
|
195
|
+
</div>
|
196
|
+
|
197
|
+
<p>Generate keys with custom options:</p>
|
198
|
+
<div class="cli-example">
|
199
|
+
lanet keygen --bits 4096 --output ~/.lanet_keys
|
200
|
+
</div>
|
201
|
+
|
202
|
+
<div class="output-example">
|
203
|
+
Key pair generated!
|
204
|
+
Private key saved to: /home/user/.lanet_keys/lanet_private.key
|
205
|
+
Public key saved to: /home/user/.lanet_keys/lanet_public.key
|
206
|
+
|
207
|
+
IMPORTANT: Keep your private key secure and never share it.
|
208
|
+
Share your public key with others who need to verify your messages.
|
209
|
+
</div>
|
210
|
+
|
211
|
+
<h4>Send a Signed Message</h4>
|
212
|
+
<div class="cli-example">
|
213
|
+
lanet send --target 192.168.1.5 --message "Signed message" --private-key-file lanet_private.key
|
214
|
+
</div>
|
215
|
+
|
216
|
+
<h4>Send a Signed & Encrypted Message</h4>
|
217
|
+
<div class="cli-example">
|
218
|
+
lanet send --target 192.168.1.5 --message "Secure signed message" --key "my_secret_key" --private-key-file lanet_private.key
|
219
|
+
</div>
|
220
|
+
|
221
|
+
<h4>Broadcast a Signed Message</h4>
|
222
|
+
<div class="cli-example">
|
223
|
+
lanet broadcast --message "Important announcement" --private-key-file lanet_private.key
|
224
|
+
</div>
|
225
|
+
|
226
|
+
<h4>Listen for and Verify Signed Messages</h4>
|
227
|
+
<div class="cli-example">
|
228
|
+
lanet listen --public-key-file lanet_public.key
|
229
|
+
</div>
|
230
|
+
|
231
|
+
<h4>Listen for Encrypted & Signed Messages</h4>
|
232
|
+
<div class="cli-example">
|
233
|
+
lanet listen --encryption-key "my_secret_key" --public-key-file lanet_public.key
|
234
|
+
</div>
|
235
|
+
|
236
|
+
<p>Example output when receiving a signed message:</p>
|
237
|
+
<div class="output-example">
|
238
|
+
Message from 192.168.1.5:
|
239
|
+
Content: Hello, this is a signed message
|
240
|
+
Signature: ✓ VERIFIED
|
241
|
+
----------------------------------------
|
242
|
+
</div>
|
243
|
+
</div>
|
244
|
+
|
245
|
+
<div class="cli-section">
|
246
|
+
<h3>Basic Message Commands</h3>
|
247
|
+
|
248
|
+
<h4>Send a Message</h4>
|
249
|
+
<div class="cli-example">
|
250
|
+
lanet send --target 192.168.1.5 --message "Hello there!"
|
251
|
+
</div>
|
252
|
+
|
253
|
+
<h4>Send an Encrypted Message</h4>
|
254
|
+
<div class="cli-example">
|
255
|
+
lanet send --target 192.168.1.5 --message "Secret message" --key "my_secret_key"
|
256
|
+
</div>
|
257
|
+
|
258
|
+
<h4>Broadcast a Message</h4>
|
259
|
+
<div class="cli-example">
|
260
|
+
lanet broadcast --message "Announcement for everyone!"
|
261
|
+
</div>
|
262
|
+
|
263
|
+
<h4>Listen for Messages</h4>
|
264
|
+
<div class="cli-example">
|
265
|
+
lanet listen
|
266
|
+
</div>
|
267
|
+
|
268
|
+
<h4>Listen for Encrypted Messages</h4>
|
269
|
+
<div class="cli-example">
|
270
|
+
lanet listen --encryption-key "my_secret_key"
|
271
|
+
</div>
|
272
|
+
</div>
|
273
|
+
|
274
|
+
<div class="cli-section">
|
275
|
+
<h3>Network Discovery Commands</h3>
|
276
|
+
|
277
|
+
<h4>Scan Network</h4>
|
278
|
+
<div class="cli-example">
|
279
|
+
lanet scan --range 192.168.1.0/24
|
280
|
+
</div>
|
281
|
+
|
282
|
+
<h4>Detailed Network Scan</h4>
|
283
|
+
<div class="cli-example">
|
284
|
+
lanet scan --range 192.168.1.0/24 --verbose --threads 16 --timeout 2
|
285
|
+
</div>
|
286
|
+
|
287
|
+
<h4>Ping a Host</h4>
|
288
|
+
<div class="cli-example">
|
289
|
+
lanet ping 192.168.1.5
|
290
|
+
</div>
|
291
|
+
|
292
|
+
<h4>Continuous Ping</h4>
|
293
|
+
<div class="cli-example">
|
294
|
+
lanet ping 192.168.1.5 --continuous
|
295
|
+
</div>
|
296
|
+
|
297
|
+
<h4>Ping Multiple Hosts</h4>
|
298
|
+
<div class="cli-example">
|
299
|
+
lanet ping --hosts 192.168.1.5,192.168.1.6,192.168.1.7 --count 5
|
300
|
+
</div>
|
301
|
+
</div>
|
302
|
+
|
303
|
+
<div class="cli-section">
|
304
|
+
<h3>File Transfer Commands <span class="badge badge-new">New in v0.3.0</span></h3>
|
305
|
+
|
306
|
+
<h4>Send a File</h4>
|
307
|
+
<p>Send a file with encryption:</p>
|
308
|
+
<div class="cli-example">
|
309
|
+
lanet send-file --target 192.168.1.5 --file document.pdf --key "my_secret_key"
|
310
|
+
</div>
|
311
|
+
|
312
|
+
<p>Send a file with encryption and digital signature:</p>
|
313
|
+
<div class="cli-example">
|
314
|
+
lanet send-file --target 192.168.1.5 --file document.pdf --key "my_secret_key" --private-key-file lanet_private.key
|
315
|
+
</div>
|
316
|
+
|
317
|
+
<h4>Receive Files</h4>
|
318
|
+
<div class="cli-example">
|
319
|
+
lanet receive-file --output ./downloads --encryption-key "my_secret_key"
|
320
|
+
</div>
|
321
|
+
|
322
|
+
<p>With signature verification:</p>
|
323
|
+
<div class="cli-example">
|
324
|
+
lanet receive-file --output ./downloads --encryption-key "my_secret_key" --public-key-file lanet_public.key
|
325
|
+
</div>
|
326
|
+
|
327
|
+
<p>Example output during file transfer:</p>
|
328
|
+
<div class="output-example">
|
329
|
+
Receiving file: document.pdf from 192.168.1.5
|
330
|
+
Size: 1048576 bytes
|
331
|
+
Transfer ID: 8a7b6c5d-4e3f-2g1h-0i9j-8k7l6m5n4o3p
|
332
|
+
Progress: 75% (786432/1048576 bytes)
|
333
|
+
</div>
|
334
|
+
</div>
|
92
335
|
|
93
|
-
<
|
336
|
+
<h2>Ruby Code Examples</h2>
|
337
|
+
|
338
|
+
<div class="tab-container">
|
339
|
+
<div class="tab-buttons">
|
340
|
+
<button class="tab-button active" onclick="openTab(event, 'tab-basic')">Basic Usage</button>
|
341
|
+
<button class="tab-button" onclick="openTab(event, 'tab-signatures')">Digital Signatures</button>
|
342
|
+
<button class="tab-button" onclick="openTab(event, 'tab-advanced')">Advanced Usage</button>
|
343
|
+
<button class="tab-button" onclick="openTab(event, 'tab-filetransfer')">File Transfer</button>
|
344
|
+
</div>
|
345
|
+
|
346
|
+
<div id="tab-basic" class="tab-content active">
|
347
|
+
<pre><code>require 'lanet'
|
348
|
+
|
349
|
+
# Send a message to a specific IP
|
350
|
+
sender = Lanet::Sender.new(5000)
|
351
|
+
sender.send_to('192.168.1.5', 'Hello from Ruby!')
|
352
|
+
|
353
|
+
# Listen for incoming messages
|
354
|
+
receiver = Lanet::Receiver.new(5000)
|
355
|
+
receiver.listen do |data, ip|
|
356
|
+
puts "Received from #{ip}: #{data}"
|
357
|
+
end
|
358
|
+
|
359
|
+
# Work with encrypted messages
|
360
|
+
encrypted = Lanet::Encryptor.prepare_message('Secret message', 'my_encryption_key')
|
361
|
+
# Send the encrypted message
|
362
|
+
sender.send_to('192.168.1.5', encrypted)</code></pre>
|
363
|
+
</div>
|
364
|
+
|
365
|
+
<div id="tab-signatures" class="tab-content">
|
366
|
+
<pre><code>require 'lanet'
|
94
367
|
|
95
368
|
# Generate RSA key pair for signing
|
96
369
|
key_pair = Lanet::Signer.generate_key_pair
|
@@ -121,7 +394,87 @@ receiver.listen do |data, sender_ip|
|
|
121
394
|
|
122
395
|
puts "Message: #{result[:content]}"
|
123
396
|
puts "Verified: #{result[:verified]}"
|
397
|
+
puts "Verification status: #{result[:verification_status]}"
|
124
398
|
end</code></pre>
|
399
|
+
</div>
|
400
|
+
|
401
|
+
<div id="tab-advanced" class="tab-content">
|
402
|
+
<pre><code>require 'lanet'
|
403
|
+
|
404
|
+
# Create a scanner and find active devices
|
405
|
+
scanner = Lanet::Scanner.new
|
406
|
+
active_hosts = scanner.scan('192.168.1.0/24', 1, 32, true)
|
407
|
+
|
408
|
+
active_hosts.each do |host|
|
409
|
+
puts "Host: #{host[:ip]}, Hostname: #{host[:hostname]}"
|
410
|
+
puts "Response time: #{host[:response_time]}ms"
|
411
|
+
|
412
|
+
if host[:ports]
|
413
|
+
puts "Open ports:"
|
414
|
+
host[:ports].each do |port, service|
|
415
|
+
puts " - #{port}: #{service}"
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
# Ping a specific host
|
421
|
+
pinger = Lanet::Ping.new
|
422
|
+
result = pinger.ping_host('192.168.1.5', true)
|
423
|
+
puts "Host reachable: #{result[:status]}"
|
424
|
+
puts "Response time: #{result[:response_time]}ms"
|
425
|
+
|
426
|
+
# Broadcast a signed and encrypted message
|
427
|
+
encryption_key = "network-shared-key"
|
428
|
+
message = "Important system notification"
|
429
|
+
signed_message = Lanet::Encryptor.prepare_message(
|
430
|
+
message,
|
431
|
+
encryption_key,
|
432
|
+
private_key
|
433
|
+
)
|
434
|
+
sender.broadcast(signed_message)</code></pre>
|
435
|
+
</div>
|
436
|
+
|
437
|
+
<div id="tab-filetransfer" class="tab-content">
|
438
|
+
<pre><code>require 'lanet'
|
439
|
+
|
440
|
+
# Create a file transfer instance
|
441
|
+
file_transfer = Lanet.file_transfer
|
442
|
+
|
443
|
+
# Send a file with encryption
|
444
|
+
file_transfer.send_file(
|
445
|
+
'192.168.1.5',
|
446
|
+
'document.pdf',
|
447
|
+
'encryption_key'
|
448
|
+
) do |progress, bytes, total|
|
449
|
+
puts "Progress: #{progress}% (#{bytes}/#{total} bytes)"
|
450
|
+
end
|
451
|
+
|
452
|
+
# Send a file with encryption and digital signature
|
453
|
+
key_pair = Lanet::Signer.generate_key_pair
|
454
|
+
file_transfer.send_file(
|
455
|
+
'192.168.1.5',
|
456
|
+
'document.pdf',
|
457
|
+
'encryption_key',
|
458
|
+
key_pair[:private_key]
|
459
|
+
)
|
460
|
+
|
461
|
+
# Receive files
|
462
|
+
file_transfer.receive_file('./downloads', 'encryption_key') do |event, data|
|
463
|
+
case event
|
464
|
+
when :start
|
465
|
+
puts "Receiving file: #{data[:file_name]}"
|
466
|
+
puts "From: #{data[:sender_ip]}"
|
467
|
+
puts "Size: #{data[:file_size]} bytes"
|
468
|
+
when :progress
|
469
|
+
puts "Progress: #{data[:progress]}%"
|
470
|
+
when :complete
|
471
|
+
puts "File saved to: #{data[:file_path]}"
|
472
|
+
when :error
|
473
|
+
puts "Error: #{data[:error]}"
|
474
|
+
end
|
475
|
+
end</code></pre>
|
476
|
+
</div>
|
477
|
+
</div>
|
125
478
|
|
126
479
|
<h2>Installation</h2>
|
127
480
|
|
@@ -132,11 +485,30 @@ end</code></pre>
|
|
132
485
|
<pre><code>gem install lanet</code></pre>
|
133
486
|
|
134
487
|
<h2>Documentation</h2>
|
135
|
-
<p>For complete documentation, please visit the <a href="https://github.com/
|
488
|
+
<p>For complete documentation, please visit the <a href="https://github.com/davidesantangelo/lanet">GitHub repository</a>.</p>
|
136
489
|
|
137
490
|
<footer style="margin-top: 40px; text-align: center; color: #7f8c8d;">
|
138
|
-
<p>Lanet - Secure Network Communications Library</p>
|
491
|
+
<p>Lanet v0.2.1 - Secure Network Communications Library</p>
|
139
492
|
</footer>
|
140
493
|
</div>
|
494
|
+
|
495
|
+
<script>
|
496
|
+
function openTab(evt, tabName) {
|
497
|
+
var i, tabContent, tabButtons;
|
498
|
+
|
499
|
+
tabContent = document.getElementsByClassName("tab-content");
|
500
|
+
for (i = 0; i < tabContent.length; i++) {
|
501
|
+
tabContent[i].className = tabContent[i].className.replace(" active", "");
|
502
|
+
}
|
503
|
+
|
504
|
+
tabButtons = document.getElementsByClassName("tab-button");
|
505
|
+
for (i = 0; i < tabButtons.length; i++) {
|
506
|
+
tabButtons[i].className = tabButtons[i].className.replace(" active", "");
|
507
|
+
}
|
508
|
+
|
509
|
+
document.getElementById(tabName).className += " active";
|
510
|
+
evt.currentTarget.className += " active";
|
511
|
+
}
|
512
|
+
</script>
|
141
513
|
</body>
|
142
|
-
</html>
|
514
|
+
</html>
|
data/lib/lanet/cli.rb
CHANGED
@@ -178,6 +178,101 @@ module Lanet
|
|
178
178
|
puts "Share your public key with others who need to verify your messages."
|
179
179
|
end
|
180
180
|
|
181
|
+
desc "send-file", "Send a file to a specific target"
|
182
|
+
option :target, type: :string, required: true, desc: "Target IP address"
|
183
|
+
option :file, type: :string, required: true, desc: "File to send"
|
184
|
+
option :key, type: :string, desc: "Encryption key (optional)"
|
185
|
+
option :private_key_file, type: :string, desc: "Path to private key file for signing (optional)"
|
186
|
+
option :port, type: :numeric, default: 5001, desc: "Port number"
|
187
|
+
def send_file
|
188
|
+
unless File.exist?(options[:file]) && File.file?(options[:file])
|
189
|
+
puts "Error: File not found or is not a regular file: #{options[:file]}"
|
190
|
+
return
|
191
|
+
end
|
192
|
+
|
193
|
+
private_key = nil
|
194
|
+
if options[:private_key_file]
|
195
|
+
begin
|
196
|
+
private_key = File.read(options[:private_key_file])
|
197
|
+
puts "File will be digitally signed"
|
198
|
+
rescue StandardError => e
|
199
|
+
puts "Error reading private key file: #{e.message}"
|
200
|
+
return
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
file_transfer = Lanet::FileTransfer.new(options[:port])
|
205
|
+
|
206
|
+
puts "Sending file #{File.basename(options[:file])} to #{options[:target]}..."
|
207
|
+
puts "File size: #{File.size(options[:file])} bytes"
|
208
|
+
|
209
|
+
begin
|
210
|
+
file_transfer.send_file(
|
211
|
+
options[:target],
|
212
|
+
options[:file],
|
213
|
+
options[:key],
|
214
|
+
private_key
|
215
|
+
) do |progress, bytes, total|
|
216
|
+
# Update progress bar
|
217
|
+
print "\rProgress: #{progress}% (#{bytes}/#{total} bytes)"
|
218
|
+
end
|
219
|
+
|
220
|
+
puts "\nFile sent successfully!"
|
221
|
+
rescue Lanet::FileTransfer::Error => e
|
222
|
+
puts "\nError: #{e.message}"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
desc "receive-file", "Listen for incoming files"
|
227
|
+
option :output, type: :string, default: "./received", desc: "Output directory for received files"
|
228
|
+
option :encryption_key, type: :string, desc: "Encryption key (optional)"
|
229
|
+
option :public_key_file, type: :string, desc: "Path to public key file for verification (optional)"
|
230
|
+
option :port, type: :numeric, default: 5001, desc: "Port number"
|
231
|
+
def receive_file
|
232
|
+
public_key = nil
|
233
|
+
if options[:public_key_file]
|
234
|
+
begin
|
235
|
+
public_key = File.read(options[:public_key_file])
|
236
|
+
puts "Digital signature verification enabled"
|
237
|
+
rescue StandardError => e
|
238
|
+
puts "Error reading public key file: #{e.message}"
|
239
|
+
return
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
output_dir = File.expand_path(options[:output])
|
244
|
+
FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)
|
245
|
+
|
246
|
+
puts "Listening for incoming files on port #{options[:port]}..."
|
247
|
+
puts "Files will be saved to #{output_dir}"
|
248
|
+
puts "Press Ctrl+C to stop"
|
249
|
+
|
250
|
+
file_transfer = Lanet::FileTransfer.new(options[:port])
|
251
|
+
|
252
|
+
begin
|
253
|
+
file_transfer.receive_file(
|
254
|
+
output_dir,
|
255
|
+
options[:encryption_key],
|
256
|
+
public_key
|
257
|
+
) do |event, data|
|
258
|
+
case event
|
259
|
+
when :start
|
260
|
+
puts "\nReceiving file: #{data[:file_name]} from #{data[:sender_ip]}"
|
261
|
+
puts "Size: #{data[:file_size]} bytes"
|
262
|
+
puts "Transfer ID: #{data[:transfer_id]}"
|
263
|
+
when :progress
|
264
|
+
print "\rProgress: #{data[:progress]}% (#{data[:bytes_received]}/#{data[:total_bytes]} bytes)"
|
265
|
+
when :complete
|
266
|
+
puts "\nFile received and saved to: #{data[:file_path]}"
|
267
|
+
when :error
|
268
|
+
puts "\nError during file transfer: #{data[:error]}"
|
269
|
+
end
|
270
|
+
end
|
271
|
+
rescue Interrupt
|
272
|
+
puts "\nFile receiver stopped."
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
181
276
|
desc "version", "Display the version of Lanet"
|
182
277
|
def version
|
183
278
|
puts "Lanet version #{Lanet::VERSION}"
|
@@ -259,19 +354,5 @@ module Lanet
|
|
259
354
|
puts "\nOutput:"
|
260
355
|
puts result[:output]
|
261
356
|
end
|
262
|
-
|
263
|
-
# Override method_missing to provide helpful error messages for common mistakes
|
264
|
-
def method_missing(method, *args)
|
265
|
-
if method.to_s == "ping" && args.any?
|
266
|
-
invoke "ping", [], { host: args.first, timeout: options[:timeout], count: options[:count],
|
267
|
-
quiet: options[:quiet], continuous: options[:continuous] }
|
268
|
-
else
|
269
|
-
super
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
def respond_to_missing?(method, include_private = false)
|
274
|
-
method.to_s == "ping" || super
|
275
|
-
end
|
276
357
|
end
|
277
358
|
end
|