-
Notifications
You must be signed in to change notification settings - Fork 109
/
node-ptrack.js
153 lines (115 loc) · 5.23 KB
/
node-ptrack.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/** PTRACK CONNECTION ********************************************************\
This code fragment can be incorporated within a NodeJS-based server
instance. It reads from a UDP broadcast address and then writes to
a TCP socket. A client browser using a websocket connection can then
receive data as it arrives.
This code will likely not run stand-alone, but is provided as a template
for adding it to your own server code as a module.
HOW UDP WORKS
Multicast is one computer sending a UDP package to a special IP address,
in the range 224.0.0.1 through 239.255.255.255. These "groups" are
assigned by IANA:
http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
The magic of multicast is that the network hardware propagates packets
across routers, and anyone can listen. To listen, you specify a host and a
group address. If you want to listen to all UDP traffic, don't specify a
host, and just use the group address.
GENERAL APPROACH
1. create socket for udp4
2. enable multicast reception
3. set multicast TTL (not necessary I suspect for a client)
4. join a channel/group (224.0.0.1). Add originating host if necessary
5. bind 'message' event to handler to receive packets
From what I understand:
The UDP source has a host_address and a port. Together this identifies
the source, which then puts all its traffic on a multicast_group_address.
A listener would bind to the port, and instead of selecting host_address
it would bind to the multicast_group_address (done by adding membership).
If the multicast_address is a regular one, then one must also designate
the host_address to receive packets from it even if a member of the
multicast_group_address.
references:
http://stackoverflow.com/questions/14130560/nodejs-udp-multicast-how-to
developed as part of REMAP/STEP
- report bugs to [email protected] or [email protected]
///////////////////////////////////////////////////////////////////////////////
/** MODULE-WIDE VARIABLES ****************************************************/
// required node modules
var dgram = require('dgram');
var WebSocketServer = require('ws').Server;
// udp socket connection
var udp_socket;
// web socket connection
var wss; // web socket server
var web_socket; // web socket
// connection parameters for multicast (UDP)
var mc = {
port: 21234, // ptrack port
group: '224.0.0.1', // standard LAN multicast address
host: undefined // undefined so node listens to all hosts
}
///////////////////////////////////////////////////////////////////////////////
/** MODULE FUNCTIONS *********************************************************/
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ Main exported function to effect UDP listening and TCP forwarding on
websocket.
/*/ function API_ConnectTracker () {
/** 1. create UDP listener to remote camera tracker **********************/
udp_socket = dgram.createSocket('udp4');
// connect to UDP group/host (host is optional)
udp_socket.bind ( mc.port, mc.host, function () {
var address = udp_socket.address();
console.log("*** LISTENING TO "+address.address+" PORT "+address.port+" ("+address.family+") ***")
// enable receiving multicast packets
udp_socket.setMulticastLoopback ( true);
// join multicast group
udp_socket.addMembership( mc.group, mc.host );
});
// set up event handler for receving UDP data
// NOTE:
// msg is a buffer object: http://nodejs.org/api/buffer.html
// The conversion below is a little hacky, but works to
// extract the JSON-encoded string.
// msg.toString() grabs all the garbage after the end of the json
// msg.toJSON() doesn't work because it grabs each byte as a number
udp_socket.once('message',function( msg, rinfo ) {
// convert msg to string, hack-style!
var s = msg.toString();
s = s.substr(0,s.indexOf(']}')+2);
// if TCP socket is available, forward string
if (web_socket) {
web_socket.send(s);
}
});
/** 2. create TCP server on port 3030 for browser-based web app **********/
// create a websocket server to listen to...
// NOTE: TCP Port 3030 is an arbitrary port.
wss = new WebSocketServer( { port: 3030 } );
// connect to TCP port
wss.on('connection', function ( wsocket ) {
console.log("*** 3030 Browser Client Connect");
web_socket = wsocket;
web_socket.once('close',function() {
console.log('remote socket BROWSER 3030 closed');
web_socket = null;
});
});
// report errors
wss.on('error', function (err) {
console.log("connectTracker socket server error: "+err);
web_socket = null;
});
} // API_ConnectTracker
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/ Brute-force close all open sockets. This might not be the right way to
do this.
/*/ function API_CloseTracker () {
if (web_socket) web_socket.close();
if (wss) wss.close();
if (udp_socket) udp_socket.close();
console.log("\n*** closing connections\n");
} // API_ConnectTracker
///////////////////////////////////////////////////////////////////////////////
/** EXPORT MODULE API ********************************************************/
exports.connectTracker = API_ConnectTracker;
exports.closeTracker = API_CloseTracker;