Skip to content

Instantly share code, notes, and snippets.

@rgarcia
Created November 21, 2012 21:13
Show Gist options
  • Save rgarcia/4127760 to your computer and use it in GitHub Desktop.
Save rgarcia/4127760 to your computer and use it in GitHub Desktop.
node tcp proxy
net = require 'net'
assert = require 'assert'
settings =
# listen on this port
proxy_server:
host: 'localhost'
port: 4731
# and proxy this guy
gearman_server:
host: 'localhost'
port: 4730
console.log settings
# every time we initiate (receive) an outbound (inbound) connection, assign a unique id to it
ob_conn_next_id = 1
ib_conn_next_id = 1
# keep track of how many outbound (inbound) connections we have outstanding
ob_conns = 0
ib_conns = 0
# open server to receive inbound connections
server = new net.Server()
server.on 'listening', () -> console.log "SERVER listening: #{JSON.stringify server.address()}"
server.on 'close', () -> console.log "SERVER close"
server.on 'error', (err) -> console.log "SERVER error: #{JSON.stringify err}"
server.on 'connection', (ib_conn) ->
console.log 'SERVER connection'
# open a connection to gearman
# if gearman sends us data, relay it on to the inbound connection
# if gearman closes our connection (it shutdown/crashed), times out, or otherwise throws an
# error, close the inbound connection
# TODO: to be a full proxy we should refuse connections when gearman is unavailable...not sure if we can do this
ob_conn_id = null
ob_conn = net.connect settings.gearman_server
ob_conn.on 'connect', () ->
ob_conn_id = ob_conn_next_id
ob_conn_next_id += 1
ob_conns += 1
console.log "OUTBOUND id=#{ob_conn_id} connected. total outbound connections=#{ob_conns}"
ob_conn.on 'data', (data) ->
console.log "OUTBOUND id=#{ob_conn_id} data", data
ib_conn.write data # relay gearman data back to inbound
ob_conn.on 'drain', () ->
console.log "OUTBOUND id=#{ob_conn_id} drain"
ob_conn.on 'error', (err) ->
console.log "OUTBOUND id=#{ob_conn_id} error", err
ib_conn.end()
ob_conn.on 'end', () ->
ob_conns -= 1
console.log "OUTBOUND id=#{ob_conn_id} end. total outbound connections=#{ob_conns}"
ib_conn.end()
ob_conn.on 'timeout', () ->
console.log "OUTBOUND id=#{ob_conn_id} timeout"
ib_conn.end()
ob_conn.on 'close', () ->
console.log "OUTBOUND id=#{ob_conn_id} close"
# if the inbound connection sends data, relay it to gearman
# if the inbound connection ends, kill our gearman connection
ib_conn_id = null
ib_conn.on 'connect', () ->
ib_conn_id = ib_conn_next_id
ib_conn_next_id += 1
ib_conns += 1
assert.equal ib_conns, server.connections
console.log "INBOUND id=#{ib_conn_id} connected. total inbound connections=#{ib_conns}"
ib_conn.on 'data', (data) ->
console.log "INBOUND id=#{ib_conn_id} data", data
ob_conn.write data # relay inbound data to gearman
ib_conn.on 'drain', () ->
console.log "INBOUND id=#{ib_conn_id} drain"
ib_conn.on 'error', (err) ->
console.log "INBOUND id=#{ib_conn_id} error", err
ib_conn.on 'end', () ->
ib_conns -= 1
console.log "INBOUND id=#{ib_conn_id} end. total inbound connections=#{ib_conns}"
assert.equal ib_conns, server.connections, "expected there to be #{ib_conns} inbound server connections, but server reports #{server.connections}"
ob_conn.end()
ib_conn.on 'timeout', () ->
console.log "INBOUND id=#{ib_conn_id} timeout"
ib_conn.on 'close', () ->
console.log "INBOUND id=#{ib_conn_id} close"
assert.equal ib_conns, server.connections
server.listen settings.proxy_server.port, settings.proxy_server.host
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment