@trap_stevo/filetide 0.0.84 → 0.0.86
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.
- package/SCL-1.0-Universal.md +228 -0
- package/dist/cjs/FileMessagerClient.js +138 -71
- package/dist/cjs/FileTide.js +165 -83
- package/dist/cjs/{FileMessager.js → FileTideAnchor.js} +444 -264
- package/dist/cjs/HUDComponents/FileTidePathsConfigurations.js +57 -0
- package/dist/cjs/HUDManagers/EndpointManager.js +157 -0
- package/dist/cjs/HUDManagers/FileMessagerConfigManager.js +2 -0
- package/dist/cjs/HUDManagers/{FileNetClientManager.js → FileTideAnchorClientManager.js} +3 -2
- package/dist/cjs/HUDManagers/{FileNetUtilityManager.js → FileTideAnchorUtilityManager.js} +2 -2
- package/dist/cjs/HUDManagers/FileTideDebugUtilityManager.js +6 -0
- package/dist/cjs/HUDManagers/FileTideNetworkTrafficManager.js +419 -0
- package/dist/cjs/HUDManagers/FileTideUniversalPathsUtilityManager.js +14 -0
- package/dist/cjs/HUDManagers/FileTransferManager.js +90 -157
- package/dist/cjs/HUDManagers/FileTransferReceiverManager.js +169 -9
- package/dist/cjs/HUDManagers/FileTransferStatsManager.js +138 -0
- package/dist/cjs/HUDManagers/FileTransferTrackingManager.js +22 -0
- package/dist/cjs/HUDManagers/FileUtilityManager.js +2 -1
- package/dist/cjs/HUDManagers/TidalyticsInstanceManager.js +2 -1
- package/dist/cjs/HUDManagers/TideSentinelManager.js +8 -7
- package/dist/cjs/HUDManagers/TideTokenEnforcementManager.js +2 -1
- package/package.json +4 -5
- package/LICENSE.md +0 -79
- package/dist/cjs/HUDComponents/ConsoleProgressBarManager.js +0 -288
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# SCL-1.0-Universal — Steven Compton Universal License v1.0
|
|
2
|
+
(Source-Available, No Redistribution, No Reverse Engineering)
|
|
3
|
+
|
|
4
|
+
**Effective Date:** September 10, 2024
|
|
5
|
+
**Licensor:** Hassan Steven Compton (Steven Compton) (“Licensor”)
|
|
6
|
+
**Package:** @trap_stevo/filetide (“Package”)
|
|
7
|
+
**Licensee:** Any individual or entity installing, using, referencing, or integrating the “Package”
|
|
8
|
+
|
|
9
|
+
**SPDX Identifier:** SCL-1.0-Universal
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Definitions
|
|
14
|
+
|
|
15
|
+
### **1.1 “Package”**
|
|
16
|
+
Refers to the software identified as @trap_stevo/filetide, including its source code, object code, binaries, compiled outputs, metadata, and documentation.
|
|
17
|
+
|
|
18
|
+
### **1.2 “Source Code”**
|
|
19
|
+
Human-readable implementation of the “Package”, whether distributed or not.
|
|
20
|
+
|
|
21
|
+
### **1.3 “Dependent System”**
|
|
22
|
+
Means any system, software, hardware, firmware, service, device, environment, runtime, application, platform, embedded implementation, virtual machine, cloud service, or any other construct that uses, integrates, links to, or depends upon the “Package”, directly or indirectly, without including or exposing the “Package’s” code or internal structure.
|
|
23
|
+
|
|
24
|
+
### **1.4 “Derivative Work”**
|
|
25
|
+
Any software, product, service, system, or implementation based on or derived from the “Package’s” source code, object code, architecture, structure, behavior, or design, in part or in whole.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Ownership
|
|
30
|
+
|
|
31
|
+
The “Licensor” retains exclusive ownership of all rights, title, and interest in and to the “Package”, including all associated intellectual property.
|
|
32
|
+
|
|
33
|
+
This Agreement transfers no ownership rights to the “Licensee”.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Grant of License
|
|
38
|
+
|
|
39
|
+
Subject to all terms of this Agreement, the “Licensor” grants the “Licensee” a limited, non-exclusive, revocable, non-transferable, and non-sublicensable license to:
|
|
40
|
+
|
|
41
|
+
1. Use the “Package” as a dependency in “Dependent Systems” created by the “Licensee”.
|
|
42
|
+
2. Distribute “Dependent Systems”, provided the “Package” is **never** included, exposed, modified, redistributed, or replicated in any form.
|
|
43
|
+
|
|
44
|
+
Nothing in this Agreement grants the “Licensee” permission to:
|
|
45
|
+
|
|
46
|
+
- modify the “Package”
|
|
47
|
+
- redistribute the “Package”
|
|
48
|
+
- fork the “Package”
|
|
49
|
+
- repackage the “Package”
|
|
50
|
+
- host the “Package”
|
|
51
|
+
- analyze the “Package”
|
|
52
|
+
- expose internal behavior of the “Package”
|
|
53
|
+
- create derivative or competing software based on the “Package”
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. Prohibited Uses
|
|
58
|
+
|
|
59
|
+
Without the express written permission of the “Licensor”, the “Licensee” shall not:
|
|
60
|
+
|
|
61
|
+
1. Modify, decompile, reverse-engineer, or disassemble the “Package” in any way.
|
|
62
|
+
2. Include the “Package’s” source code or object code in any distributed software, service, or application.
|
|
63
|
+
3. Use the “Package” to create a competing product or service that replicates the functionality of the “Package”.
|
|
64
|
+
4. Make the “Package” publicly available, including uploading it to public repositories or including it in distributed software bundles.
|
|
65
|
+
5. Attempt to extract or analyze the functionality, structure, or behavior of the “Package” through runtime inspection, instrumentation, reflection, or behavioral analysis.
|
|
66
|
+
6. Privately share, sublicense, or distribute the “Package” or any portion thereof, whether internally within an organization or externally to any third party, without written authorization.
|
|
67
|
+
7. Remove, obscure, obfuscate, or alter any attribution, copyright notices, proprietary labels, or identifiers included in the “Package”.
|
|
68
|
+
8. Re-upload, rename, fork, or redistribute the “Package” or any portion thereof on any registry, platform, or namespace other than that explicitly maintained or authorized by the “Licensor”.
|
|
69
|
+
9. Use the “Package” in any way that violates applicable laws, infringes on third-party rights, or breaches this Agreement.
|
|
70
|
+
|
|
71
|
+
Any attempt to bypass or circumvent these restrictions constitutes a material breach.
|
|
72
|
+
|
|
73
|
+
### 4.A. No Competitive Re-implementation
|
|
74
|
+
|
|
75
|
+
“Licensee” shall not create, develop, train, test, benchmark, or distribute any software, system, service, model, or method that uses, incorporates, is derived from, or is based upon the “Package’s” source code, object code, algorithms, data structures, interfaces, protocols, internal behavior, design, architecture, or execution characteristics for the purpose of creating a product or service that provides substantially similar functionality to the “Package”, competes with the “Package”, or reproduces its core operations.
|
|
76
|
+
|
|
77
|
+
“Licensee” shall not directly or indirectly analyze, observe, measure, study, or evaluate the behavior, performance, outputs, or internal characteristics of the “Package” for the purpose of creating, validating, training, improving, or assisting any competing or functionally similar software, system, service, or model.
|
|
78
|
+
|
|
79
|
+
Any such activity shall constitute creation of an unauthorized derivative work and is strictly prohibited.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 5. Dependent System Requirements
|
|
84
|
+
|
|
85
|
+
The “Licensee” may create and distribute “Dependent Systems” only if all of the following conditions are met:
|
|
86
|
+
|
|
87
|
+
1. The “Dependent System” does **not** include or expose any portion of the “Package’s” source code or object code.
|
|
88
|
+
2. The “Dependent System” identifies the “Package” as a dependency in its documentation.
|
|
89
|
+
3. The “Dependent System” provides substantial original functionality.
|
|
90
|
+
4. The “Dependent System” does not replicate, emulate, reimplement, or mimic any significant part of the “Package’s” behavior or design.
|
|
91
|
+
5. The “Dependent System” complies fully with this Agreement.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 6. Request for Additional Permissions
|
|
96
|
+
|
|
97
|
+
The “Licensee” may request additional rights by contacting:
|
|
98
|
+
|
|
99
|
+
**h.steven.compton13@gmail.com**
|
|
100
|
+
|
|
101
|
+
Requests must:
|
|
102
|
+
|
|
103
|
+
1. Be submitted in writing
|
|
104
|
+
2. Describe purpose, scope, and distribution method
|
|
105
|
+
|
|
106
|
+
The “Licensor” may:
|
|
107
|
+
|
|
108
|
+
- approve or deny at sole discretion
|
|
109
|
+
- impose additional terms
|
|
110
|
+
- revoke previously granted permissions with written notice
|
|
111
|
+
|
|
112
|
+
All permissions must be explicit and in writing.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 7. Violation of Terms (Termination)
|
|
117
|
+
|
|
118
|
+
1. Any violation of this Agreement results in immediate termination of all licensed rights.
|
|
119
|
+
2. Upon termination, the “Licensee” must:
|
|
120
|
+
- cease all use of the “Package”
|
|
121
|
+
- remove the “Package” from all systems and environments
|
|
122
|
+
- destroy all copies, including caches and build artifacts
|
|
123
|
+
- confirm destruction in writing if requested
|
|
124
|
+
3. The “Licensor” may pursue damages, injunctive relief, or any other legal remedy.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 8. No Warranty
|
|
129
|
+
|
|
130
|
+
The “Package” is provided **“AS IS”**, without any warranty, express or implied, including but not limited to merchantability, fitness for a particular purpose, or non-infringement.
|
|
131
|
+
|
|
132
|
+
The “Licensee” assumes all risk associated with use.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 9. Intellectual Property Limitations
|
|
137
|
+
|
|
138
|
+
Nothing in this Agreement grants the “Licensee” any rights under any patent, whether by implication, estoppel, exhaustion, or otherwise. Any use of the “Package” that would require a patent license must receive separate written permission from the “Licensor”.
|
|
139
|
+
|
|
140
|
+
This Agreement also grants no rights to use the “Licensor’s” trademarks, service marks, branding, logos, product names, or organizational names. Any such use requires separate written permission.
|
|
141
|
+
|
|
142
|
+
No patent rights, trademark rights, or branding rights are provided or implied by this license.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 10. Patent Rights and Restrictions
|
|
147
|
+
|
|
148
|
+
### 10.1 No Implied Patent License
|
|
149
|
+
|
|
150
|
+
Except as expressly stated in this Section, the “Licensor” grants no license, covenant, immunity, or right under any patent or patent application owned, controlled, or licensable by the “Licensor”. All such rights are expressly reserved.
|
|
151
|
+
|
|
152
|
+
### 10.2 Patent Grant for Non-Competitive Use
|
|
153
|
+
|
|
154
|
+
Subject to full compliance with this Agreement, the “Licensor” grants the “Licensee” a limited, non-exclusive, non-transferable, revocable, royalty-free patent license to use any patent claims embodied in the “Package” solely to the extent necessary to use the unmodified “Package” as permitted under Section 3.
|
|
155
|
+
|
|
156
|
+
This grant does not extend to:
|
|
157
|
+
|
|
158
|
+
- derivative works
|
|
159
|
+
|
|
160
|
+
- competing software
|
|
161
|
+
|
|
162
|
+
- re-implementations
|
|
163
|
+
|
|
164
|
+
- architectural replications
|
|
165
|
+
|
|
166
|
+
- alternative implementations of patented methods
|
|
167
|
+
|
|
168
|
+
- any use not directly involving the unmodified “Package”
|
|
169
|
+
|
|
170
|
+
### 10.3 Patent Restriction for Competing Systems
|
|
171
|
+
|
|
172
|
+
No patent license is granted for any software, system, service, or model that:
|
|
173
|
+
|
|
174
|
+
- competes with the “Package”,
|
|
175
|
+
|
|
176
|
+
- provides substantially similar core functionality,
|
|
177
|
+
|
|
178
|
+
- implements any patented algorithm, method, design, architecture, or process used by the Package, or
|
|
179
|
+
|
|
180
|
+
- is a re-implementation or functional substitute of the “Package”.
|
|
181
|
+
|
|
182
|
+
Any such use constitutes patent infringement and is prohibited.
|
|
183
|
+
|
|
184
|
+
### 10.4 Termination of Patent Rights
|
|
185
|
+
|
|
186
|
+
Any violation of this Agreement immediately terminates all patent licenses granted herein. Upon termination, Licensee must cease all uses of the patented subject matter and destroy any implementations utilizing such technology.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 11. Indemnification
|
|
191
|
+
|
|
192
|
+
The “Licensee” agrees to indemnify and hold harmless the “Licensor” from any claims, damages, liabilities, losses, or expenses arising from:
|
|
193
|
+
|
|
194
|
+
- violation of this Agreement
|
|
195
|
+
- misuse of the “Package”
|
|
196
|
+
- unlawful or infringing use
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 12. Governing Law & Dispute Resolution
|
|
201
|
+
|
|
202
|
+
This Agreement is governed by the laws of **Georgia, United States**, without regard to conflict-of-law principles.
|
|
203
|
+
|
|
204
|
+
All disputes shall be resolved exclusively through binding arbitration in **Georgia, United States**.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## 13. Amendments
|
|
209
|
+
|
|
210
|
+
The “Licensor” may modify this Agreement at any time.
|
|
211
|
+
|
|
212
|
+
Changes take effect 30 days after posting at:
|
|
213
|
+
|
|
214
|
+
**https://www.npmjs.com/package/@trap_stevo/filetide**
|
|
215
|
+
|
|
216
|
+
Continued use of the “Package” constitutes acceptance of the updated terms.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 14. Applicability to All Versions
|
|
221
|
+
|
|
222
|
+
This Agreement applies to **all versions** of the “Package” downloaded, installed, or used on or after the Effective Date.
|
|
223
|
+
|
|
224
|
+
Use of any version after this date constitutes acceptance of this License unless explicitly overridden by the “Licensor”.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
**SPDX-License-Identifier: SCL-1.0-Universal**
|
|
@@ -6,6 +6,7 @@ function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.h
|
|
|
6
6
|
const {
|
|
7
7
|
HUDIoTide
|
|
8
8
|
} = require("@trap_stevo/iotide-client");
|
|
9
|
+
const LogicTide = require("@trap_stevo/logictide");
|
|
9
10
|
const chalk = require("chalk");
|
|
10
11
|
const path = require("path");
|
|
11
12
|
const fs = require("fs");
|
|
@@ -14,6 +15,9 @@ const {
|
|
|
14
15
|
significantMessageColors,
|
|
15
16
|
errorMessageColors
|
|
16
17
|
} = require("./HUDManagers/FileTideDebugUtilityManager");
|
|
18
|
+
const {
|
|
19
|
+
STATES: NETWORK_TRAFFIC_STATES
|
|
20
|
+
} = require("./HUDManagers/FileTideNetworkTrafficManager.js");
|
|
17
21
|
const {
|
|
18
22
|
FileTransferTrackingManager
|
|
19
23
|
} = require("./HUDManagers/FileTransferTrackingManager.js");
|
|
@@ -41,25 +45,39 @@ class FileMessagerClient {
|
|
|
41
45
|
maxReconnectionAttempts = 15,
|
|
42
46
|
reconnectionAttempts = 15,
|
|
43
47
|
maxReconnectionDelay = 10000,
|
|
48
|
+
tideDurationMs: _tideDurationMs = 125,
|
|
49
|
+
minTideBytes = 512 * 1024,
|
|
50
|
+
maxTideBytes = 8 * 1024 * 1024,
|
|
44
51
|
...messagerConfigurations
|
|
45
52
|
} = messagerSettings;
|
|
46
53
|
this.clientOptions = FileMessagerConfigManager.getClientOptions(_options);
|
|
47
54
|
this.transporter = new FileTransferManager(transportOptions);
|
|
55
|
+
this.tideDurationMs = Math.max(25, _tideDurationMs);
|
|
56
|
+
this.minTideBytes = Math.max(512 * 1024, minTideBytes);
|
|
57
|
+
this.maxTideBytes = Math.max(this.minTideBytes, maxTideBytes);
|
|
48
58
|
this.activeTransferTypes = new Map();
|
|
49
59
|
this.clientTide = new HUDIoTide(maxReconnectionAttempts, reconnectionAttempts, maxReconnectionDelay, {
|
|
50
60
|
persistentTideIDs: true,
|
|
51
61
|
persistentTideID: true,
|
|
52
|
-
...messagerConfigurations
|
|
62
|
+
...messagerConfigurations,
|
|
63
|
+
tideIDsPath: LogicTide.runSync("tide-session-ids-path"),
|
|
64
|
+
tideIDPath: LogicTide.runSync("tide-session-id-path")
|
|
53
65
|
});
|
|
54
66
|
this.clients = new Map();
|
|
55
67
|
}
|
|
68
|
+
recordNetworkThroughput(throughputBps) {
|
|
69
|
+
return this.transporter.recordNetworkThroughput(throughputBps);
|
|
70
|
+
}
|
|
71
|
+
getNetworkTrafficStatus() {
|
|
72
|
+
return this.transporter.getNetworkTrafficStatus();
|
|
73
|
+
}
|
|
56
74
|
joinRoom(userID, roomName, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
|
|
57
75
|
const socketName = _assertClassBrand(_FileMessagerClient_brand, this, _createClientInstance).call(this, userID, {
|
|
58
76
|
url: this.clientOptions.url
|
|
59
77
|
}, options, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
|
|
60
78
|
return () => {
|
|
61
79
|
this.clientTide.joinChannel(socketName, roomName, userID, () => {
|
|
62
|
-
FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~
|
|
80
|
+
FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ Tider] ~ Client ~ ${userID} joined room ${roomName} successfully!`, significantMessageColors);
|
|
63
81
|
this.clients.set(userID, {
|
|
64
82
|
roomName
|
|
65
83
|
});
|
|
@@ -108,18 +126,18 @@ class FileMessagerClient {
|
|
|
108
126
|
transferType
|
|
109
127
|
}, transferExpirationTime);
|
|
110
128
|
if (!transferAccepted) {
|
|
111
|
-
FileTideDebugUtilityManager.outputGradient(`[FileTide ~
|
|
129
|
+
FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ${recipientID} denied your transfer.`, errorMessageColors);
|
|
112
130
|
return false;
|
|
113
131
|
} else if (transferAccepted) {
|
|
114
|
-
FileTideDebugUtilityManager.outputGradient(`[FileTide ~
|
|
132
|
+
FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ${recipientID} accepted your transfer!`, significantMessageColors);
|
|
115
133
|
return true;
|
|
116
134
|
}
|
|
117
135
|
} catch (error) {
|
|
118
136
|
if (error.message.startsWith("Timeout: No response")) {
|
|
119
|
-
FileTideDebugUtilityManager.outputGradient("[FileTide ~
|
|
137
|
+
FileTideDebugUtilityManager.outputGradient("[FileTide ~ Tider] Transfer approval timed out.", errorMessageColors);
|
|
120
138
|
return false;
|
|
121
139
|
}
|
|
122
|
-
FileTideDebugUtilityManager.outputGradient(`[FileTide ~
|
|
140
|
+
FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] Transfer approval refused.\n${error}`, errorMessageColors);
|
|
123
141
|
return false;
|
|
124
142
|
}
|
|
125
143
|
}
|
|
@@ -163,7 +181,7 @@ class FileMessagerClient {
|
|
|
163
181
|
});
|
|
164
182
|
Promise.all(sendFilePromises).then(() => console.log("\nAll files in directory transferred successfully!")).catch(error => console.error("Did not transfer directory: ", error));
|
|
165
183
|
} catch (error) {
|
|
166
|
-
FileTideDebugUtilityManager.outputGradient(`[FileTide ~
|
|
184
|
+
FileTideDebugUtilityManager.outputGradient(`[FileTide ~ Tider] ~ Refused directory transfer: ${error}`, errorMessageColors);
|
|
167
185
|
}
|
|
168
186
|
}
|
|
169
187
|
async sendDirectoryLargeFile(clientID, recipientId, fileName, filePath = process.cwd(), destinationPath = null, fileSize, index = 0, tideSize = 500, minTideSize = 10, maxTideSize = 2000, transferRequestExpirationTime = 30000, metadata = {}) {
|
|
@@ -193,7 +211,7 @@ class FileMessagerClient {
|
|
|
193
211
|
}
|
|
194
212
|
async sendFile(clientID, recipientId, fileName, filePath = process.cwd(), destination = process.cwd(), fileSize, tideSize = 500, minTideSize = 10, maxTideSize = 2000, initiatingTransfer = true, inDirectory = false, largeFile = false, transferRequestExpirationTime = 30000, metadata = {}) {
|
|
195
213
|
const destinationPath = FileUtilityManager.normalizePath(path.join(destination, fileName));
|
|
196
|
-
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~
|
|
214
|
+
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Requesting to transfer large file ~ ${destinationPath} to ${recipientId}!` : `[FileTide ~ Tider] ~ Requesting to transfer ~ ${destinationPath} to ${recipientId}!`, significantMessageColors);
|
|
197
215
|
const incomingType = this.activeTransferTypes.get(filePath);
|
|
198
216
|
if (!inDirectory && initiatingTransfer) {
|
|
199
217
|
const transferAllowed = incomingType && incomingType === "requestedTransfer" ? true : await this.allowedTransfer(clientID, recipientId, destinationPath, filePath, fileSize, 1, "file", "send", transferRequestExpirationTime);
|
|
@@ -224,12 +242,39 @@ class FileMessagerClient {
|
|
|
224
242
|
size: fileSize
|
|
225
243
|
};
|
|
226
244
|
try {
|
|
227
|
-
let lastSendTime = Date.now();
|
|
228
|
-
const maxBatchSize = maxTideSize;
|
|
229
|
-
const minBatchSize = minTideSize;
|
|
230
|
-
let batchSize = tideSize > maxBatchSize || tideSize > minBatchSize ? tideSize : tideSize <= minBatchSize ? minBatchSize : 10;
|
|
231
245
|
let transferInitiated = false;
|
|
232
|
-
const
|
|
246
|
+
const currentTide = [];
|
|
247
|
+
const flushTide = () => {
|
|
248
|
+
if (currentTide.length <= 0) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const outgoingChunks = currentTide.splice(0, currentTide.length);
|
|
252
|
+
const firstChunk = outgoingChunks[0];
|
|
253
|
+
const lastChunk = outgoingChunks[outgoingChunks.length - 1];
|
|
254
|
+
const tideBytes = outgoingChunks.reduce((total, chunk) => total + chunk.chunkSize, 0);
|
|
255
|
+
this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
|
|
256
|
+
tide: {
|
|
257
|
+
transferId: firstChunk.transferId,
|
|
258
|
+
senderID: firstChunk.senderID,
|
|
259
|
+
recipientId: firstChunk.recipientId,
|
|
260
|
+
fileName: firstChunk.fileName,
|
|
261
|
+
filePath: firstChunk.filePath,
|
|
262
|
+
fileSize: firstChunk.fileSize,
|
|
263
|
+
totalChunks: firstChunk.totalChunks,
|
|
264
|
+
firstChunkIndex: firstChunk.chunkIndex,
|
|
265
|
+
lastChunkIndex: lastChunk.chunkIndex,
|
|
266
|
+
completedChunks: lastChunk.completedChunks,
|
|
267
|
+
tideChunkCount: outgoingChunks.length,
|
|
268
|
+
tideBytes,
|
|
269
|
+
chunks: outgoingChunks.map(chunk => ({
|
|
270
|
+
chunkIndex: chunk.chunkIndex,
|
|
271
|
+
chunkSize: chunk.chunkSize,
|
|
272
|
+
fileChunk: chunk.fileChunk
|
|
273
|
+
})),
|
|
274
|
+
metadata: firstChunk.metadata
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
};
|
|
233
278
|
await this.transporter.sendLargeFile(fileHandle, {
|
|
234
279
|
recipientID: recipientId,
|
|
235
280
|
originDetails: {
|
|
@@ -237,61 +282,48 @@ class FileMessagerClient {
|
|
|
237
282
|
senderID: clientID
|
|
238
283
|
},
|
|
239
284
|
fileDetails,
|
|
240
|
-
onSendChunk: (transferId, chunkIndex, chunkSize, chunkData, totalChunks, completedChunks) => {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
});
|
|
255
|
-
if (!transferInitiated) {
|
|
256
|
-
this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
|
|
257
|
-
chunkBatch
|
|
258
|
-
});
|
|
259
|
-
transferInitiated = true;
|
|
260
|
-
chunkBatch.length = 0;
|
|
261
|
-
}
|
|
262
|
-
if (chunkBatch.length >= batchSize) {
|
|
263
|
-
const now = Date.now();
|
|
264
|
-
const rtt = now - lastSendTime;
|
|
265
|
-
lastSendTime = now;
|
|
266
|
-
this.clientTide.emitEvent(clientID, "client-to-client-transfer", {
|
|
267
|
-
chunkBatch
|
|
268
|
-
});
|
|
269
|
-
chunkBatch.length = 0;
|
|
270
|
-
if (rtt >= 200 && batchSize < maxBatchSize) {
|
|
271
|
-
batchSize = Math.min(batchSize + 50, maxBatchSize);
|
|
272
|
-
} else if (rtt < 200 && batchSize > minBatchSize) {
|
|
273
|
-
batchSize = Math.max(batchSize - 50, minBatchSize);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
resolve();
|
|
285
|
+
onSendChunk: async (transferId, chunkIndex, chunkSize, chunkData, totalChunks, completedChunks) => {
|
|
286
|
+
currentTide.push({
|
|
287
|
+
transferId,
|
|
288
|
+
senderID: clientID,
|
|
289
|
+
recipientId,
|
|
290
|
+
fileName,
|
|
291
|
+
fileChunk: chunkData,
|
|
292
|
+
completedChunks,
|
|
293
|
+
totalChunks,
|
|
294
|
+
chunkIndex,
|
|
295
|
+
chunkSize,
|
|
296
|
+
filePath: destination,
|
|
297
|
+
fileSize,
|
|
298
|
+
metadata
|
|
277
299
|
});
|
|
300
|
+
if (!transferInitiated) {
|
|
301
|
+
flushTide();
|
|
302
|
+
transferInitiated = true;
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const adaptiveTideSize = _assertClassBrand(_FileMessagerClient_brand, this, _getAdaptiveTideSize).call(this, chunkSize, tideSize, minTideSize, maxTideSize);
|
|
306
|
+
if (currentTide.length >= adaptiveTideSize) {
|
|
307
|
+
flushTide();
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
onComplete: async () => {
|
|
311
|
+
flushTide();
|
|
278
312
|
},
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
});
|
|
294
|
-
resolve();
|
|
313
|
+
onFailure: async (transferId, error) => {
|
|
314
|
+
/*
|
|
315
|
+
* Do not flush an unfinished Tide after
|
|
316
|
+
* the transfer has already failed.
|
|
317
|
+
*/
|
|
318
|
+
currentTide.length = 0;
|
|
319
|
+
this.clientTide.emitEvent(clientID, "transfer-failed", {
|
|
320
|
+
transferId,
|
|
321
|
+
senderID: clientID,
|
|
322
|
+
recipientId,
|
|
323
|
+
fileName,
|
|
324
|
+
filePath: destination,
|
|
325
|
+
reason: error.message,
|
|
326
|
+
metadata
|
|
295
327
|
});
|
|
296
328
|
},
|
|
297
329
|
onTiding: () => {
|
|
@@ -301,9 +333,10 @@ class FileMessagerClient {
|
|
|
301
333
|
});
|
|
302
334
|
}
|
|
303
335
|
}, this.clientTide);
|
|
304
|
-
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~
|
|
336
|
+
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Large file ~ ${fileName} transfer complete!` : `[FileTide ~ Tider] ~ File ~ ${fileName} transfer complete!`, significantMessageColors);
|
|
305
337
|
} catch (error) {
|
|
306
|
-
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~
|
|
338
|
+
FileTideDebugUtilityManager.outputGradient(largeFile ? `[FileTide ~ Tider] ~ Error transferring large file: ${error.message}` : `[FileTide ~ Tider] ~ Error transferring file ~ ${error.message}`, errorMessageColors);
|
|
339
|
+
throw error;
|
|
307
340
|
} finally {
|
|
308
341
|
await fileHandle.close();
|
|
309
342
|
}
|
|
@@ -313,14 +346,48 @@ function _createClientInstance(clientID, clientOptions, options = {}, headers =
|
|
|
313
346
|
this.clientTide.createIO(clientID, clientOptions.url, {
|
|
314
347
|
transports: ["websocket"],
|
|
315
348
|
...options
|
|
316
|
-
}, headers, authURL, authHeaders, useAuthentication, queryAuthToken,
|
|
349
|
+
}, headers, authURL, authHeaders, useAuthentication, queryAuthToken, (...connectionArguments) => {
|
|
350
|
+
this.transporter.updateNetworkTraffic({
|
|
351
|
+
online: true,
|
|
352
|
+
success: true
|
|
353
|
+
});
|
|
354
|
+
if (onConnect) {
|
|
355
|
+
return onConnect(...connectionArguments);
|
|
356
|
+
}
|
|
357
|
+
}, async (...disconnectArguments) => {
|
|
358
|
+
this.transporter.updateNetworkTraffic({
|
|
359
|
+
online: false
|
|
360
|
+
});
|
|
317
361
|
FileTransferTrackingManager.outputCurrentTransfers();
|
|
318
362
|
if (onDisconnect) {
|
|
319
|
-
await onDisconnect();
|
|
363
|
+
await onDisconnect(...disconnectArguments);
|
|
320
364
|
}
|
|
321
365
|
});
|
|
322
|
-
FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~
|
|
366
|
+
FileTideDebugUtilityManager.outputGradient(`\n[FileTide ~ Tider] ~ Created client with ID ${clientID} and socket ${clientID}!`, significantMessageColors);
|
|
323
367
|
return clientID;
|
|
324
368
|
}
|
|
369
|
+
function _getAdaptiveTideSize(chunkSize, tideSize = 500, minTideSize = 10, maxTideSize = 2000) {
|
|
370
|
+
const networkStatus = this.transporter.getNetworkTrafficStatus();
|
|
371
|
+
const sendRateBps = Math.max(networkStatus.sendRateBps || chunkSize, chunkSize);
|
|
372
|
+
let tideDurationMs = this.tideDurationMs;
|
|
373
|
+
if (networkStatus.state === NETWORK_TRAFFIC_STATES.CONGESTED) {
|
|
374
|
+
tideDurationMs *= 0.50;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/*
|
|
378
|
+
* Determine how many chunks current network conditions
|
|
379
|
+
* can reasonably support during one Tide duration.
|
|
380
|
+
*/
|
|
381
|
+
const networkTideBytes = Math.max(sendRateBps * (tideDurationMs / 1000), chunkSize);
|
|
382
|
+
const networkTideSize = Math.max(1, Math.floor(networkTideBytes / chunkSize));
|
|
383
|
+
const normalizedMinTideSize = Math.max(1, minTideSize);
|
|
384
|
+
const normalizedMaxTideSize = Math.max(normalizedMinTideSize, maxTideSize);
|
|
385
|
+
const preferredTideSize = Math.min(Math.max(tideSize, normalizedMinTideSize), normalizedMaxTideSize);
|
|
386
|
+
const adaptiveTideSize = Math.min(networkTideSize, preferredTideSize);
|
|
387
|
+
const minTideChunkSize = Math.max(1, Math.floor(this.minTideBytes / chunkSize));
|
|
388
|
+
const maxTideChunkSize = Math.max(1, Math.floor(this.maxTideBytes / chunkSize));
|
|
389
|
+
const optimizedTideSize = adaptiveTideSize >= minTideChunkSize ? adaptiveTideSize : Math.min(networkTideSize, preferredTideSize);
|
|
390
|
+
return Math.max(1, Math.min(optimizedTideSize, maxTideChunkSize, normalizedMaxTideSize));
|
|
391
|
+
}
|
|
325
392
|
;
|
|
326
393
|
module.exports = FileMessagerClient;
|