refactor to use regular es5 js, no need to make socket a component

This commit is contained in:
Mark Vayngrib 2015-05-10 20:41:43 -04:00
parent dea64e5b7a
commit cacff29bab
2 changed files with 161 additions and 179 deletions

View File

@ -13,14 +13,9 @@
'use strict'; 'use strict';
var React = require('react-native') var React = require('react-native')
var {
Component
} = React
var mixInEventEmitter = require('mixInEventEmitter') var mixInEventEmitter = require('mixInEventEmitter')
var DeviceEventEmitter = require('RCTDeviceEventEmitter') var DeviceEventEmitter = require('RCTDeviceEventEmitter')
var NativeModules = require('NativeModules') var Sockets = require('NativeModules').UdpSockets
var sockets = NativeModules.UdpSockets
var noop = function () {} var noop = function () {}
var instances = 0 var instances = 0
var STATE = { var STATE = {
@ -29,204 +24,191 @@ var STATE = {
BOUND: 2 BOUND: 2
} }
class RCTSocket extends Component { function UdpSocket(type) {
id: String; this._id = instances++
_state: Integer; this._state = STATE.UNBOUND
_address: String; this._subscriptiom = DeviceEventEmitter.addListener(
_port: Integer; 'udp-' + this._id + '-data', this._onReceive.bind(this)
);
constructor(props) { // ensure compatibility with node's EventEmitter
super(props) if (!this.on) this.on = this.addListener.bind(this)
this.id = instances++
this.subscriptiom = DeviceEventEmitter.addListener(
'udp-' + this.id + '-data', this._onReceive.bind(this)
);
// ensure compatibility with node's EventEmitter Sockets.createSocket(this._id, {
if (!this.on) this.on = this.addListener.bind(this) type: type || 'udp4'
}) // later
}
this._state = STATE.UNBOUND UdpSocket.prototype._debug = function() {
sockets.createSocket(this.id, { // for now
type: props.type || 'udp4' var args = [].slice.call(arguments)
}) // later args.unshift(this._id)
console.log.apply(console, args)
}
UdpSocket.prototype.bind = function(port, address, callback) {
var self = this
if (this._state !== STATE.UNBOUND) throw new Error('Socket is already bound')
if (typeof address === 'function') {
callback = address
address = undefined
} }
_debug() { if (!address) address = '0.0.0.0'
var args = [].slice.call(arguments)
args.unshift(this.id)
console.log.apply(console, args)
}
bind(port, address, callback) { if (!port) port = 0
var self = this
if (this._state !== STATE.UNBOUND) throw new Error('Socket is already bound') if (callback) this.once('listening', callback.bind(this))
if (typeof address === 'function') { this._state = STATE.BINDING
callback = address this._debug('binding, address:', address, 'port:', port)
address = undefined Sockets.bind(this._id, port, address, function(err, addr) {
if (err) {
// questionable: may want to self-destruct and
// force user to create a new socket
self._state = STATE.UNBOUND
self._debug('failed to bind', err)
return self.emit('error', err)
} }
if (!address) address = '0.0.0.0' self._debug('bound to address:', addr.address, 'port:', addr.port)
self._address = addr.address
self._port = addr.port
self._state = STATE.BOUND
self.emit('listening')
})
}
if (!port) port = 0 UdpSocket.prototype.close = function() {
if (this._destroyed) return
if (callback) this.once('listening', callback.bind(this)) this._destroyed = true
this._debug('closing')
this._subscription.remove();
this._state = STATE.BINDING Sockets.close(this._id, this._debug.bind(this, 'closed'))
this._debug('binding, address:', address, 'port:', port) this.emit('close')
sockets.bind(this.id, port, address, function(err, addr) { }
if (err) {
// questionable: may want to self-destruct and
// force user to create a new socket
self._state = STATE.UNBOUND
self._debug('failed to bind', err)
return self.emit('error', err)
}
self._debug('bound to address:', addr.address, 'port:', addr.port) UdpSocket.prototype._onReceive = function(info) {
self._address = addr.address this._debug('received', info)
self._port = addr.port
self._state = STATE.BOUND var buf = toByteArray(info.data)
self.emit('listening') var rinfo = {
}) address: info.address,
port: info.port,
family: 'IPv4', // not necessarily
size: buf.length
} }
componentWillUnmount() { if (typeof Buffer !== 'undefined') buf = new Buffer(buf)
this.subscription.remove();
this.emit('message', buf, rinfo)
}
/**
* socket.send(buf, offset, length, port, address, [callback])
*
* For UDP sockets, the destination port and IP address must be
* specified. A string may be supplied for the address parameter, and it will
* be resolved with DNS. An optional callback may be specified to detect any
* DNS errors and when buf may be re-used. Note that DNS lookups will delay
* the time that a send takes place, at least until the next tick. The only
* way to know for sure that a send has taken place is to use the callback.
*
* If the socket has not been previously bound with a call to bind, it's
* assigned a random port number and bound to the "all interfaces" address
* (0.0.0.0 for udp4 sockets, ::0 for udp6 sockets).
*
* @param {Array|string} message to be sent
* @param {number} offset Offset in the buffer where the message starts.
* @param {number} length Number of bytes in the message.
* @param {number} port destination port
* @param {string} address destination IP
* @param {function} callback Callback when message is done being delivered.
* Optional.
*/
// UdpSocket.prototype.send = function (buf, host, port, cb) {
UdpSocket.prototype.send = function(buffer, offset, length, port, address, callback) {
var self = this
if (offset !== 0) throw new Error('Non-zero offset not supported yet')
if (this._state === STATE.UNBOUND) {
throw new Error('bind before sending, seriously dude')
}
else if (this._state === STATE.BINDING) {
// we're ok, GCDAsync(Udp)Socket handles queueing internally
} }
_onReceive(info) { callback = callback || noop
this._debug('received', info) if (typeof buffer === 'string') {
buffer = toByteArray(buffer)
}
else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(buffer)) {
buffer = buffer.toJSON().data
}
var buf = toByteArray(info.data) self._debug('sending', buffer)
var rinfo = { Sockets.send(this._id, buffer, +port, address, function(err) {
address: info.address, if (err) {
port: info.port, self._debug('send failed', err)
family: 'IPv4', // not necessarily return callback(err)
size: buf.length
} }
if (typeof Buffer !== 'undefined') buf = new Buffer(buf) self._debug('sent')
callback()
})
}
this.emit('message', buf, rinfo) UdpSocket.prototype.address = function() {
if (this._state !== STATE.BOUND) {
throw new Error('socket is not bound yet')
} }
return {
/** address: this._address,
* socket.send(buf, offset, length, port, address, [callback]) port: this._port,
* family: 'IPv4'
* For UDP sockets, the destination port and IP address must be
* specified. A string may be supplied for the address parameter, and it will
* be resolved with DNS. An optional callback may be specified to detect any
* DNS errors and when buf may be re-used. Note that DNS lookups will delay
* the time that a send takes place, at least until the next tick. The only
* way to know for sure that a send has taken place is to use the callback.
*
* If the socket has not been previously bound with a call to bind, it's
* assigned a random port number and bound to the "all interfaces" address
* (0.0.0.0 for udp4 sockets, ::0 for udp6 sockets).
*
* @param {Array|string} message to be sent
* @param {number} offset Offset in the buffer where the message starts.
* @param {number} length Number of bytes in the message.
* @param {number} port destination port
* @param {string} address destination IP
* @param {function} callback Callback when message is done being delivered.
* Optional.
*/
// Socket.prototype.send = function (buf, host, port, cb) {
send(buffer, offset, length, port, address, callback) {
var self = this
if (offset !== 0) throw new Error('Non-zero offset not supported yet')
if (this._state === STATE.UNBOUND) {
throw new Error('bind before sending, seriously dude')
}
else if (this._state === STATE.BINDING) {
// we're ok, GCDAsync(Udp)Socket handles queueing internally
}
callback = callback || noop
if (typeof buffer === 'string') {
buffer = toByteArray(buffer)
}
else if (typeof Buffer !== 'undefined' && Buffer.isBuffer(buffer)) {
buffer = buffer.toJSON().data
}
self._debug('sending', buffer)
sockets.send(this.id, buffer, +port, address, function(err) {
if (err) {
self._debug('send failed', err)
return callback(err)
}
self._debug('sent')
callback()
})
}
address() {
if (this._state !== STATE.BOUND) {
throw new Error('socket is not bound yet')
}
return {
address: this._address,
port: this._port,
family: 'IPv4'
}
}
close() {
var self = this
if (this._destroyed) return
this._destroyed = true
this._debug('closing')
sockets.close(this.id, function() {
self._debug('closed')
})
this.emit('close')
}
setBroadcast(flag) {
// nothing yet
}
setTTL(ttl) {
// nothing yet
}
setMulticastTTL(ttl, callback) {
// nothing yet
}
setMulticastLoopback(flag, callback) {
// nothing yet
}
addMembership(multicastAddress, multicastInterface, callback) {
// nothing yet
}
dropMembership(multicastAddress, multicastInterface, callback) {
// nothing yet
}
ref() {
// anything?
}
unref() {
// anything?
} }
} }
mixInEventEmitter(RCTSocket, { UdpSocket.prototype.setBroadcast = function(flag) {
// nothing yet
}
UdpSocket.prototype.setTTL = function(ttl) {
// nothing yet
}
UdpSocket.prototype.setMulticastTTL = function(ttl, callback) {
// nothing yet
}
UdpSocket.prototype.setMulticastLoopback = function(flag, callback) {
// nothing yet
}
UdpSocket.prototype.addMembership = function(multicastAddress, multicastInterface, callback) {
// nothing yet
}
UdpSocket.prototype.dropMembership = function(multicastAddress, multicastInterface, callback) {
// nothing yet
}
UdpSocket.prototype.ref = function() {
// anything?
}
UdpSocket.prototype.unref = function() {
// anything?
}
mixInEventEmitter(UdpSocket, {
'listening': true, 'listening': true,
'message': true, 'message': true,
'close': true, 'close': true,
@ -258,4 +240,4 @@ function toByteArray(obj) {
return new Uint8Array(uint); return new Uint8Array(uint);
} }
module.exports = RCTSocket module.exports = UdpSocket

View File

@ -4,7 +4,7 @@
* @flow * @flow
*/ */
var UdpSocket = require('UdpSocket') var UdpSocket = require('./UdpSocket.ios')
module.exports = { module.exports = {
createSocket: function(type) { createSocket: function(type) {