blinksocks
provides several useful APIs to help you to integrate your own magic to the framework.
Install blinksocks
globally, it's usually already done:
$ npm install -g blinksocks
Then you can require
it in your code:
const blinksocks = require('blinksocks');
The Hub
class can be used to create a blinksocks client/server instance with different configurations.
config
a configuration in plain object.
- Returns a
<Promise>
.
const { Hub } = require('blinksocks');
const hub = new Hub(clientConfig);
hub.run()
.then(() => {
console.log('blinksocks client is running now');
})
.catch((err) => {
console.error(err);
});
Or use async/await for convenience:
const { Hub } = require('blinksocks');
const hub = new Hub(clientConfig);
try {
await hub.run();
console.log('blinksocks client is running now');
} catch (err) {
console.error(err);
}
- Returns a
<Promise>
.
Close all living connections and destroy the hub instance.
- Returns connection number associate with the hub.
- Returns total download bytes from server/client.
- Returns total upload bytes to server/client.
- Returns upload bytes per second.
- Returns download bytes per second.
- Returns current status of all connections.
Results for example:
[
{
"id": "conn_1",
"stage": 2,
"startTime": 1523344893955,
"sourceHost": "127.0.0.1",
"sourcePort": 56739,
"targetHost": "facebook.com",
"targetPort": 443,
"endTime": 1523344894457
},
{
"id": "conn_2",
"stage": 1,
"startTime": 1523344894134,
"sourceHost": "127.0.0.1",
"sourcePort": 56742,
"targetHost": "cx.atdmt.com",
"targetPort": 443
}
]
CONN_STAGE_INIT
: 0CONN_STAGE_TRANSFER
: 1CONN_STAGE_FINISH
: 2CONN_STAGE_ERROR
: 3
The IPreset
class defines a specific protocol, acting as data stream interpreter.
Export a class that extends from IPreset interface:
class MyCustomPreset extends blinksocks.IPreset {
constructor(props) {
super(props);
console.log('hello from my custom preset');
}
// implement some of the methods you need
}
// implement static methods
MyCustomPreset.onCheckParams = function onCheckParams(params) {
};
MyCustomPreset.onCache = function onCache(params, store) {
};
module.exports = MyCustomPreset;
You can implement some of the following methods to interact with data stream:
METHODS | DESCRIPTION |
---|---|
clientOut | client received data from application, and ready to forward data to server. |
serverIn | server received data from client, and ready to forward data to real destination. |
serverOut | server received data from real destination, and ready to backward data to client. |
clientIn | client received data from server, and ready to backward data to application. |
beforeOut | before calling clientOut() or serverOut(). |
beforeIn | before calling clientIn() or serverIn(). |
Hint:
server*()
are running on the server side whileclient*()
are running on the client side.before*()
are running on both sides.
Hint: To transfer UDP packets, just postfix "Udp" to each methods and implement UDP specific protocol in them, e.g,
clientOutUdp()
.
Each method gets an object which contains several parameters and callbacks you may need:
clientOut({ buffer, next, fail }) {
// your magic here
// return a buffer or next(a buffer)
}
PARAM | DESCRIPTION |
---|---|
buffer | output from the previous preset. |
next(buffer, isReverse) | transmit processed buffer to the next preset. If isReverse is true, send data back to the previous preset. |
fail(message) | report an error message when the preset fail to process. |
You probably want to know the target host and port when write your own preset on client
side, IPresetAddressing::onInitTargetAddress()
will be called with target host
and port
:
const { IPresetAddressing } = require('blinksocks');
class MyCustomPreset extends IPresetAddressing {
onInitTargetAddress({ host, port }) {
// got target host and port here
}
}
After target address resolved on server
side, you should call this.resolveTargetAddress()
explicit:
const { IPresetAddressing } = require('blinksocks');
class MyCustomPreset extends IPresetAddressing {
serverIn() {
this.resolveTargetAddress({ host, port }, () => {
// successfully connected to the target address
});
}
}
module.exports = MyCustomPreset;
Your presets may require several parameters, and you can validate them in:
constructor({ config, params })
(every time a connection created)static onCheckParams(params)
(only once, recommended)
class MyCustomPreset extends blinksocks.IPreset {
constructor(props) {
super(props);
// check props.params
}
}
// check params passed to the preset, if any errors, should throw directly
MyCustomPreset.onCheckParams = function onCheckParams(params) {
// or here (recommended)
};
module.exports = MyCustomPreset;
You can initialize some shared/immutable data among connections in onCache(params)
to improve performance:
class MyCustomPreset extends blinksocks.IPreset {
}
/**
* you can make some cache in store or just return something
* you want to put in store, then access store later in other
* hook functions via this.getStore()
* @param params
* @param store
*/
MyCustomPreset.onCache = function onCache(params, store) {
// or return something
};
module.exports = MyCustomPreset;
You can access user configuration anywhere via this._config
in your preset:
class MyCustomPreset extends blinksocks.IPreset {
constructor(props) {
super(props);
console.log(this._config.key);
}
}
module.exports = MyCustomPreset;
For full items you can access to, please read Config.
The following functions are auto-generated to your preset, DO NOT overwrite them:
this.next(type, buffer)
The same as next
parameter in each hook function, but here you should provide type
to tell which pipe direction the data should transfer to.
this.readProperty(presetName, propertyName)
Directly read a property from other presets, this is useful when your logic have to depend on other presets.
this.getStore()
Returns the store you modified in or returned from onCache(params, store)
.