11const express = require ( "express" )
22const wss = require ( "./wss" )
3+ const WebSocket = require ( "ws" )
34
45const { logger } = require ( "./utils/logger" )
56const { ENV } = require ( "./env" )
@@ -101,30 +102,29 @@ function getDataByHostname(hostname) {
101102 }
102103}
103104
104- async function trySendWakeupPackets ( hosts , wolUrl ) {
105- if ( ! hosts ?. length ) return null
106- if ( typeof wolUrl !== "string" || wolUrl . trim ( ) === "" ) return null
105+ async function trySendWakeupPackets ( client , hosts , wolUrl ) {
106+ if ( ! hosts ?. length ) return { err : true }
107+ if ( ! client ) return { err : true }
108+ if ( ! wolUrl ) return { err : true }
107109
108- let output = ""
109110 let err = false
110111
112+ const baseURL = new URL ( wolUrl )
113+ const protocol = baseURL . protocol === "https:" ? "wss" : "ws"
114+
111115 const virtualPort =
112116 ENV . virtualPort && `${ ENV . virtualPort } ` . trim ( ) !== ""
113117 ? ENV . virtualPort
114118 : null
115119
116120 for ( const host of hosts ) {
117- const ip = host . ip
118-
119121 let targetUrl = wolUrl
120122 let payload
121123
122124 if ( host . isVirtual ) {
123- if ( ! virtualPort ) {
124- continue
125- }
125+ if ( ! virtualPort ) continue
126126
127- targetUrl = `http://${ ip } :${ virtualPort } `
127+ targetUrl = `http://${ host . ip } :${ virtualPort } `
128128 payload = {
129129 id : host . id ,
130130 startupTime : host . startupTime ,
@@ -142,26 +142,90 @@ async function trySendWakeupPackets(hosts, wolUrl) {
142142 )
143143
144144 const response = await post ( targetUrl , payload )
145- if ( ! response ?. message ) {
145+ if ( ! response ?. client_id ) {
146146 err = true
147+
148+ sendToClient ( client , {
149+ success : false ,
150+ error : true ,
151+ message : `WoL request failed` ,
152+ } )
153+
154+ errorClient ( client , err )
155+
147156 break
148157 }
149158
150- const msg = response . message
159+ const hostClientId = response . client_id
151160
152- if ( msg . output && ! host . isVirtual ) {
153- output += msg . output
154- }
161+ const wsURL = `${ protocol } ://${ baseURL . host } /ws?client_id=${ hostClientId } `
162+ const ws = new WebSocket ( wsURL )
163+
164+ let finished = false
165+
166+ ws . on ( "message" , ( msg ) => {
167+ let data
168+ try {
169+ data = JSON . parse ( msg )
170+ } catch {
171+ return
172+ }
173+
174+ if ( data . error === true ) {
175+ err = true
176+ }
177+
178+ sendToClient ( client , {
179+ success : false ,
180+ error : err ,
181+ message : data . message ,
182+ } )
183+
184+ errorClient ( client , err )
185+
186+ if ( data . success === true ) {
187+ finished = true
188+ ws . close ( )
189+ } else if ( err ) {
190+ ws . close ( )
191+ }
192+ } )
193+
194+ ws . on ( "close" , ( ) => {
195+ if ( ! finished && ! err ) {
196+ err = true
197+
198+ sendToClient ( client , {
199+ error : true ,
200+ message : `WoL WebSocket closed unexpectedly` ,
201+ } )
202+
203+ errorClient ( client , err )
204+ }
205+ } )
155206
156- if ( msg . success === false ) {
207+ ws . on ( "error" , ( ) => {
157208 err = true
158- break
159- }
209+
210+ logger . error ( "Error during WebSocket connection: " , err . message )
211+
212+ sendToClient ( client , {
213+ success : false ,
214+ error : true ,
215+ message : `WoL WebSocket error for host` ,
216+ } )
217+ } )
218+
219+ await new Promise ( ( resolve ) => {
220+ ws . on ( "close" , resolve )
221+ ws . on ( "error" , resolve )
222+ } )
223+
224+ if ( err ) break
160225 }
161226
162- return { output , err }
227+ return { err }
163228}
164-
165229async function waitForHostUp ( url , options = { } ) {
166230 const { interval = 3000 , timeout = 60000 } = options
167231 const start = Date . now ( )
@@ -209,9 +273,11 @@ async function startProcessing(req, res) {
209273 return res . json ( { error : true , message : "No route for hostname" } )
210274 }
211275
212- const requestId = wss . createRequestId ( )
276+ const clientID = wss . createClientID ( )
213277
214- res . json ( { error : false , message : "Start request received" , requestId } )
278+ res . json ( {
279+ client_id : clientID ,
280+ } )
215281
216282 const { hosts, routeAttributes } = resolved
217283
@@ -221,23 +287,18 @@ async function startProcessing(req, res) {
221287
222288 let wolResult = null
223289
224- if ( wolEnabled && hosts . length > 0 ) {
225- wolResult = await trySendWakeupPackets ( hosts , ENV . wolURL )
226- }
227-
228- const ws = wss . getClient ( requestId )
290+ const ws = wss . getClient ( clientID )
229291
230292 if ( ! ws ) {
231293 return
232294 }
233295
296+ if ( wolEnabled && hosts . length > 0 ) {
297+ wolResult = await trySendWakeupPackets ( ws , hosts , ENV . wolURL )
298+ }
299+
234300 if ( wolResult ) {
235301 err = wolResult . err
236-
237- sendToClient ( ws , {
238- error : err ,
239- message : wolResult . output ,
240- } )
241302 }
242303
243304 errorClient ( ws , err )
@@ -295,7 +356,6 @@ async function startProcessing(req, res) {
295356 message : "" ,
296357 error : err ,
297358 host : serviceURL . hostname ,
298- requestId,
299359 } )
300360}
301361
0 commit comments