Skip to content

[bug]: Socket.IO v4 sending EIO=3 instead of EIO=4 in Firecamp (v3.3.0-beta.3) #262

Open
@w20k

Description

@w20k

Socket.IO Connection Issue in Firecamp

Describe the Bug

When attempting to connect to a Socket.IO server (v4) using Firecamp, the connection fails with an "Unsupported protocol version" error. Firecamp is attempting to use Engine.IO protocol version 3 (EIO=3) while the server is expecting version 4 (EIO=4), resulting in a protocol version mismatch.

To Reproduce

Steps to reproduce the behavior:

  1. Set up a Socket.IO v4 server on localhost:5000 (added dummy server .js below)
  2. Open Firecamp and create a new Socket.IO connection
  3. Enter http://localhost:5000 as the connection URL
  4. Attempt to connect
  5. Connection fails with error: "Unsupported protocol version"

Expected Behavior

Firecamp should either:

  • Protocol version should be either EIO=3 for v2 and v3, or EIO=4 for v4 (would be great to see that in connection url)
  • Default to the latest protocol version (EIO=4) for Socket.IO connections

Screenshots

Error from server logs:

Engine.IO connection error: {
  "code": 5,
  "message": "Unsupported protocol version",
  "context": {
    "protocol": 3
  }
}

Request headers showing EIO=3:

url: "/socket.io/?EIO=3&transport=websocket"

Desktop Information

  • OS: macOS 10.15.7
  • Application: Firecamp v3.3.0-beta.3
  • Electron: 29.1.0
  • Chrome: 122.0.6261.70

Note:

Maybe, you need to add one more configuration or change something somewhere, but as a User I thought it should be done via dropdown where you chose version? No?;

Couldn't see exactly what's happening in the code, because part of it is not accessible as it seems: io: { v2: SocketIOv2, v3: SocketIOv3, v4: SocketIOv4 },

Test server

Click me

Socket.IO Server Javascript

const http = require('node:http')
const { Server } = require('socket.io')

// Create HTTP server
const server = http.createServer((req, res) => {
  console.log(`HTTP Request: ${req.method} ${req.url}`)

  // Add CORS headers to all responses
  res.setHeader('Access-Control-Allow-Origin', '*')
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type')

  if (req.method === 'OPTIONS') {
    res.writeHead(204)
    res.end()
    return
  }

  res.writeHead(200, { 'Content-Type': 'text/plain' })
  res.end('Socket.IO test server running. This is a plain HTTP endpoint.')
})

// Create Socket.IO server with compatibility for v3 and v4
const io = new Server(server, {
  // Allow both v3 and v4 clients
  allowEIO3: true,

  // Ping configuration
  pingTimeout: 60000, // How long to wait after a ping before considering the connection closed
  pingInterval: 25000, // How often to ping the client

  // Connection timeout
  connectTimeout: 60000, // How long to wait for a connection to establish

  // Transport configuration
  transports: ['polling', 'websocket'],
  upgradeTimeout: 30000, // How long to wait for transport upgrade

  // CORS configuration
  cors: {
    origin: '*',
    methods: ['GET', 'POST', 'OPTIONS'],
    credentials: true,
  },

  // Additional options
  maxHttpBufferSize: 1e8, // 100 MB
  path: '/socket.io/', // Default path
  serveClient: true, // Serve client files
})

// Debug middleware for all Socket.IO connections
io.use((socket, next) => {
  console.log('Connection attempt:')
  console.log('  IP:', socket.handshake.address)
  console.log('  Transport:', socket.conn.transport.name)
  console.log('  Headers:', JSON.stringify(socket.handshake.headers))
  console.log('  Query:', JSON.stringify(socket.handshake.query))
  next()
})

// Socket.IO connection handler
io.on('connection', (socket) => {
  console.log(`Client connected: ${socket.id}`)
  console.log(`Transport: ${socket.conn.transport.name}`)

  // Send immediate welcome message
  socket.emit('welcome', {
    message: 'Connected to Socket.IO server',
    socketId: socket.id,
    timestamp: new Date().toISOString(),
  })

  // Set up a ping interval for this specific socket
  const pingInterval = setInterval(() => {
    console.log(`Pinging client ${socket.id}...`)

    // Custom ping implementation only - don't use socket.conn.ping()
    socket.emit('ping_from_server', { timestamp: new Date().toISOString() })

    // The built-in ping is handled automatically by Socket.IO
    // No need to call socket.conn.ping() manually
  }, 20000)

  // Handle custom ping response
  socket.on('pong_from_client', (data) => {
    console.log(`Received pong from ${socket.id}:`, data)
  })

  // Handle message event
  socket.on('message', (data) => {
    console.log(`Message from ${socket.id}:`, data)
    socket.emit('response', {
      echo: data,
      timestamp: new Date().toISOString(),
    })
  })

  // Handle any event
  socket.onAny((event, ...args) => {
    if (event !== 'message' && event !== 'ping_from_server' && event !== 'pong_from_client') {
      console.log(`Event "${event}" from ${socket.id}:`, args)
      socket.emit(`${event}_response`, {
        received: args,
        timestamp: new Date().toISOString(),
      })
    }
  })

  // Handle errors
  socket.on('error', (error) => {
    console.error(`Socket error for ${socket.id}:`, error)
  })

  // Handle disconnection
  socket.on('disconnect', (reason) => {
    console.log(`Client disconnected: ${socket.id}, reason: ${reason}`)
    clearInterval(pingInterval) // Clean up ping interval
  })
})

// Engine.IO errors
io.engine.on('connection_error', (err) => {
  console.error('Engine.IO connection error:', err)
})

// Start the server
const PORT = 5000
server.listen(PORT, '0.0.0.0', () => {
  console.log(`Socket.IO server running on port ${PORT}`)
  console.log(`Server time: ${new Date().toISOString()}`)
  console.log('Supports both Socket.IO v3 and v4 clients')
  console.log('Enhanced ping configuration enabled')
  console.log('Connect with Socket.IO client using:')
  console.log(`  - URL: http://localhost:${PORT}`)
})

// Handle server shutdown
process.on('SIGINT', () => {
  console.log('Shutting down server...')
  io.close()
  server.close()
  process.exit(0)
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions