WebSockets working
This commit is contained in:
		
							
								
								
									
										149
									
								
								src/usimp.ts
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								src/usimp.ts
									
									
									
									
									
								
							| @@ -162,20 +162,23 @@ export class Session { | ||||
|             const host = this.server.host; | ||||
|             const protocols = this.server.protocols; | ||||
|  | ||||
|             /* | ||||
|             if ("ws" in protocols) { | ||||
|                 this.websocket = new WebSocket(`ws://${host}:${protocols.ws}/_usimp/websocket`, ["usimp"]); | ||||
|             if ("wss" in protocols) { | ||||
|                 this.websocket = new WebSocket(`wss://${host}:${protocols.wss}/_usimp/websocket`, ["usimp"]); | ||||
|                 this.websocket.addEventListener("error", (error) => { | ||||
|                     console.error(error); | ||||
|                     this.websocket = null; | ||||
|                 }); | ||||
|             } | ||||
|             */ | ||||
|  | ||||
|             // TODO http -> https | ||||
|             if (protocols) { | ||||
|                 this.httpBaseUrl = `http://${host}:${protocols.http}/_usimp`; | ||||
|             if ("https" in protocols) { | ||||
|                 this.httpBaseUrl = `https://${host}:${protocols.https}/_usimp`; | ||||
|                 try { | ||||
|                     return await this.ping(); | ||||
|                 } catch { | ||||
|                     this.domain.invalidServers.push(this.server); | ||||
|                     this.server = null; | ||||
|                     if (this.server !== null) { | ||||
|                         this.domain.invalidServers.push(this.server); | ||||
|                         this.server = null; | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 console.warn(`Domain server ${this.server} does not support 'https' transport protocol`); | ||||
| @@ -186,39 +189,111 @@ export class Session { | ||||
|         return undefined; | ||||
|     } | ||||
|  | ||||
|     waitForWebSocket() { | ||||
|         if (this.websocket === null) throw Error("websocket not initialized"); | ||||
|         return new Promise<void>((resolve, reject) => { | ||||
|             if (this.websocket?.readyState === this.websocket?.OPEN) { | ||||
|                 resolve(); | ||||
|             } else { | ||||
|                 const handlerOpen = () => { | ||||
|                     this.websocket?.removeEventListener("open", handlerOpen); | ||||
|                     resolve(); | ||||
|                 }; | ||||
|                 const handlerError = (error: any) => { | ||||
|                     this.websocket?.removeEventListener("error", handlerError); | ||||
|                     reject(error); | ||||
|                 } | ||||
|                 this.websocket?.addEventListener("open", handlerOpen); | ||||
|                 this.websocket?.addEventListener("error", handlerError); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     waitForWebSocketResponse(req_nr: number, timeout: number) { | ||||
|         if (this.websocket === null) throw Error("websocket not initialized"); | ||||
|         return new Promise<any>((resolve, reject) => { | ||||
|             const handlerMsg = (msg: any) => { | ||||
|                 const data = JSON.parse(msg.data); | ||||
|                 if (data['request_nr'] === req_nr) { | ||||
|                     clearTimeout(timer); | ||||
|                     this.websocket?.removeEventListener("message", handlerMsg); | ||||
|                     this.websocket?.removeEventListener("error", handlerError); | ||||
|                     resolve(data); | ||||
|                 } | ||||
|             } | ||||
|             const handlerError = (error: any) => { | ||||
|                 clearTimeout(timer); | ||||
|                 this.websocket?.removeEventListener("message", handlerMsg); | ||||
|                 this.websocket?.removeEventListener("error", handlerError); | ||||
|                 reject(error); | ||||
|             } | ||||
|             const handlerTimeout = () => { | ||||
|                 this.websocket?.removeEventListener("message", handlerMsg); | ||||
|                 this.websocket?.removeEventListener("error", handlerError); | ||||
|                 reject(Error("timeout")); | ||||
|             } | ||||
|             const timer = setTimeout(handlerTimeout, timeout); | ||||
|             this.websocket?.addEventListener("message", handlerMsg); | ||||
|             this.websocket?.addEventListener("error", handlerError); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     async send(endpoint: string, data: object, timeout: number = 2000, forceHttp: boolean = false) { | ||||
|         this.numRequests++; | ||||
|  | ||||
|         if (!forceHttp && this.websocket) { | ||||
|             this.websocket.send(JSON.stringify({ | ||||
|                 'request_num': this.numRequests, | ||||
|                 'data': data | ||||
|             })); | ||||
|         } else { | ||||
|             const controller = new AbortController(); | ||||
|             const timer = setTimeout(() => controller.abort(), timeout); | ||||
|         while (true) { | ||||
|             try { | ||||
|                 if (!forceHttp && this.websocket) { | ||||
|                     const req_nr = this.numRequests; | ||||
|                     const response = this.waitForWebSocketResponse(req_nr, timeout); | ||||
|  | ||||
|             let headers: Record<string, string> = { | ||||
|                 'Content-Type': 'application/json', | ||||
|                 'To-Domain': this.domain.id, | ||||
|             }; | ||||
|             if (this.token) { | ||||
|                 headers['Authorization'] = `usimp ${this.token}`; | ||||
|                     const startTime = performance.now(); | ||||
|                     await this.waitForWebSocket(); | ||||
|                     await this.websocket.send(JSON.stringify({ | ||||
|                         'request_nr': req_nr, | ||||
|                         'endpoint': endpoint, | ||||
|                         'to_domain': this.domain.id, | ||||
|                         'data': data | ||||
|                     })); | ||||
|                     const responseData = await response; | ||||
|  | ||||
|                     const endTime = performance.now(); | ||||
|                     responseData.duration = endTime - startTime; | ||||
|                     return responseData; | ||||
|                 } else { | ||||
|                     const controller = new AbortController(); | ||||
|                     const timer = setTimeout(() => controller.abort(), timeout); | ||||
|  | ||||
|                     let headers: Record<string, string> = { | ||||
|                         'Content-Type': 'application/json', | ||||
|                         'To-Domain': this.domain.id, | ||||
|                     }; | ||||
|                     if (this.token) { | ||||
|                         headers['Authorization'] = `usimp ${this.token}`; | ||||
|                     } | ||||
|  | ||||
|                     const startTime = performance.now(); | ||||
|                     const response = await fetch(`${this.httpBaseUrl}/${endpoint}`, { | ||||
|                         method: "POST", | ||||
|                         headers: headers, | ||||
|                         body: JSON.stringify(data), | ||||
|                         signal: controller.signal, | ||||
|                     }); | ||||
|                     clearTimeout(timer); | ||||
|                     const responseData = await response.json(); | ||||
|  | ||||
|                     const endTime = performance.now(); | ||||
|                     responseData.duration = endTime - startTime; | ||||
|                     return responseData; | ||||
|                 } | ||||
|             } catch (error) { | ||||
|                 console.error(error); | ||||
|                 if (this.server !== null) { | ||||
|                     this.domain.invalidServers.push(this.server); | ||||
|                     this.server = null; | ||||
|                 } | ||||
|                 await this.chooseDomainServer(); | ||||
|             } | ||||
|  | ||||
|             const startTime = new Date(); | ||||
|             const response = await fetch(`${this.httpBaseUrl}/${endpoint}`, { | ||||
|                 method: "POST", | ||||
|                 headers: headers, | ||||
|                 body: JSON.stringify(data), | ||||
|                 signal: controller.signal, | ||||
|             }); | ||||
|             const endTime = new Date(); | ||||
|             clearTimeout(timer); | ||||
|  | ||||
|             const responseData = await response.json(); | ||||
|             responseData.duration = endTime.getUTCMilliseconds() - startTime.getUTCMilliseconds(); | ||||
|             return responseData; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -19,17 +19,17 @@ Distributed, end-to-end encrypted instant messaging."/> | ||||
|     <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||||
|     <link rel="icon" sizes="64x64" href="/favicon.ico" type="image/x-icon"/> | ||||
|     <link rel="stylesheet" href="/res/styles/styles.css?v=0.0.0+93" type="text/css"/> | ||||
|     <script type="module" src="/res/scripts/usimp.js?v=0.0.0+93"></script> | ||||
|     <script type="module" src="/res/scripts/locutus.js?v=0.0.0+93"></script> | ||||
|     <script type="module" src="/res/scripts/main.js?v=0.0.0+93"></script> | ||||
|     <meta http-equiv="Content-Security-Policy" content=" | ||||
|         default-src 'none'; | ||||
|         style-src 'unsafe-inline'; | ||||
|         style-src 'unsafe-inline' 'self'; | ||||
|         script-src 'self'; | ||||
|         img-src * blob: data:; | ||||
|         connect-src *; | ||||
|         media-src * blob: data:;"/> | ||||
|     <link rel="stylesheet" href="/res/styles/styles.css?v=0.0.0+123" type="text/css"/> | ||||
|     <script type="module" src="/res/scripts/usimp.js?v=0.0.0+123"></script> | ||||
|     <script type="module" src="/res/scripts/locutus.js?v=0.0.0+123"></script> | ||||
|     <script type="module" src="/res/scripts/main.js?v=0.0.0+123"></script> | ||||
| </head> | ||||
| <body> | ||||
|     <div id="wrapper"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user