swifter icon indicating copy to clipboard operation
swifter copied to clipboard

allow public access to socket and keep it open when requested

Open Bersaelor opened this issue 5 years ago • 3 comments

Hey there, I've been using swifter for a while, but in my case I was always keeping the sockets open, to allow for stateful connections. In my case communication is bidirectional, the phone acts as a sort of remote for the browser window.

The below are all the changes I needed from this project, would this be something worth merging into the main branch?

Bersaelor avatar Oct 26 '20 14:10 Bersaelor

Hey @Bersaelor, could you give me an example of how you're using this?

Also, could you fix the merge conflict while you're at it?

michaelenger avatar Sep 28 '21 22:09 michaelenger

hey @michaelenger ,

from a UX perspective the user only opens the page in their browser and then never interacts with the desktop pc/mac anymore, instead going across the room and controlling the website with their phone.

First I save the socket that is currently open when the website loads, like this:

    // during init
            do {
            try httpServer.start()
        }
        catch {
            log.error("While starting httpserver: \(error)")
        }
        
        httpServer["/"] = htmlHandler(filePathComponent: "/Web/index.html", context: rootContext)
        httpServer["/websocket-echo"] = websocket(
            text: webSocket(session:text:),
            binary: nil, pong: nil, connected: nil, disconnected: nil
        )
    }
  
    fileprivate func webSocket(session: WebSocketSession, text: String) {
        guard text.hasPrefix("BTI$") else {
            // if text doesn't start with 'Browser To Iphone', then it's not a socket message
            session.writeText(text)
            return
        }
        
        log.debug("message: \(text)")

        if self.currentSocket == nil {
            self.socketDidOpen()
            currentSocket = session.socket
            session.socket.didClose = { [weak self] in
                self?.socketDidClose()
                self?.currentSocket = nil
            }
        }
        
        guard let message = RemoteScreenMessage(message: text) else {
            log.error("text couldn't be parsed: \( text )")
            return
        }
        
        log.debug("Message: \(message)")
        
        DispatchQueue.main.async {
            self.received(message)
        }
    }

and then when I want to make the currently presented desktop page change I do:

    fileprivate func sendToClient(_ message: MessageToBrowser) {
        let msgString = "....."
        
        log.debug("Attempting to send msg: \(msgString)")
        
        networkingQueue.async {
            guard let socket = self.currentSocket else { return }
            let session = WebSocketSession(socket)
            session.shouldCloseSocket = false
            if message.type.shouldBeRepeated { self.lastMessage = message }
            session.writeText(msgString)
        }
    }

Bersaelor avatar Sep 29 '21 08:09 Bersaelor

This is a cool idea, what do you think @Vkt0r?

michaelenger avatar Sep 29 '21 16:09 michaelenger