New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

nats

Package Overview
Dependencies
Maintainers
3
Versions
198
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nats - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

15

index.d.ts

@@ -88,19 +88,4 @@ /*

useOldRequestStyle?: boolean
authHandler?: AuthHandler
}
export interface NKeyAuthChallenge {
sig: Buffer;
nkey: string;
}
export interface ChallengeSigner {
(data: Buffer): Buffer
}
export interface AuthHandler {
sign: ChallengeSigner;
id: string
}
export interface SubscribeOptions {

@@ -107,0 +92,0 @@ queue?: string,

425

lib/nats.js

@@ -1,2 +0,1 @@

/* eslint-disable no-await-in-loop */
/*

@@ -28,3 +27,5 @@ * Copyright 2013-2018 The NATS Authors

events = require('events'),
nuid = require('nuid');
nuid = require('nuid'),
nkeys = require('ts-nkeys'),
fs = require('fs');

@@ -34,3 +35,3 @@ /**

*/
var VERSION = '1.1.0',
var VERSION = '1.2.0',

@@ -56,4 +57,2 @@ DEFAULT_PORT = 4222,

// Protocol
//CONTROL_LINE = /^(.*)\r\n/, // TODO: remove / never used
MSG = /^MSG\s+([^\s\r\n]+)\s+([^\s\r\n]+)\s+(([^\s\r\n]+)[^\S\r\n]+)?(\d+)\r\n/i,

@@ -66,2 +65,3 @@ OK = /^\+OK\s*\r\n/i,

SUBRE = /^SUB\s+([^\r\n]+)\r\n/i,
CREDS = /\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))/i,

@@ -74,3 +74,2 @@ CR_LF = '\r\n',

// Protocol
//PUB = 'PUB', // TODO: remove / never used
SUB = 'SUB',

@@ -85,3 +84,2 @@ UNSUB = 'UNSUB',

// Errors
API_ERR = "API_ERROR",
BAD_AUTHENTICATION = 'BAD_AUTHENTICATION',

@@ -113,8 +111,18 @@ BAD_AUTHENTICATION_MSG = 'User and Token can not both be provided',

SECURE_CONN_REQ_MSG = 'Server requires a secure connection.',
STALE_CONNECTION_ERR = "stale connection",
STALE_CONNECTION_ERR = 'stale connection',
SIGNATURE_REQUIRED = 'SIG_REQ',
SIGNATURE_REQUIRED_MSG = 'Server requires an Nkey signature.',
SIGCB_NOTFUNC = 'SIG_NOT_FUNC',
SIGCB_NOTFUNC_MSG = 'Signature callback is not a function.',
NKEY_OR_JWT_REQ = 'NKEY_OR_JWT_REQ',
NKEY_OR_JWT_REQ_MSG = 'An Nkey or User JWT callback needs to be defined.',
BAD_CREDS = 'BAD_CREDENTIALS',
BAD_CREDS_MSG = 'Bad user credentials',
NO_SEED_IN_CREDS = 'NO_SEED_IN_CREDS',
NO_SEED_IN_CREDS_MSG = 'Can not locate signing key in credentials',
NO_USER_JWT_IN_CREDS = 'NO_USER_JWT_IN_CREDS',
NO_USER_JWT_IN_CREDS_MSG = 'Can not locate user jwt in credentials.',
BAD_OPTIONS = 'BAD_OPTIONS',
BAD_OPTIONS_MSG = 'Options should be an object as second paramater.',
// Pedantic Mode support
//Q_SUB = /^([^\.\*>\s]+|>$|\*)(\.([^\.\*>\s]+|>$|\*))*$/, // TODO: remove / never used
//Q_SUB_NO_WC = /^([^\.\*>\s]+)(\.([^\.\*>\s]+))*$/, // TODO: remove / never used
FLUSH_THRESHOLD = 65536;

@@ -161,3 +169,2 @@

exports.REQ_TIMEOUT = REQ_TIMEOUT;
exports.API_ERR = API_ERR;

@@ -192,7 +199,20 @@

*
* @params {Mixed} [opts]
*
* @params {Mixed} [url] - Url, port, or options object
* @params {Object} [opts] - Options
* @api public
*/
exports.connect = function(opts) {
exports.connect = function(url, opts) {
// If we receive one parameter, parser will
// figure out intent. If we provided opts, then
// first parameter should be url, and second an
// options object.
if (opts !== undefined) {
if ('object' !== typeof opts) {
this.emit('error', new NatsError(BAD_OPTIONS_MSG, BAD_OPTIONS));
return;
}
opts.url = sanitizeUrl(url);
} else {
opts = url;
}
return new Client(opts);

@@ -253,2 +273,3 @@ };

if (undefined === opts) {

@@ -259,3 +280,3 @@ options.url = DEFAULT_URI;

} else if ('string' === typeof opts) {
options.url = opts;
options.url = sanitizeUrl(opts);
} else if ('object' === typeof opts) {

@@ -294,4 +315,14 @@ if (opts.port !== undefined) {

this.assignOption(opts, 'useOldRequestStyle');
this.assignOption(opts, 'authHandler');
this.assignOption(opts, 'sigCB', 'sig');
this.assignOption(opts, 'sigcb', 'sig');
this.assignOption(opts, 'sigCallback', 'sig');
this.assignOption(opts, 'nkey', 'nkey');
this.assignOption(opts, 'nkeys', 'nkey');
this.assignOption(opts, 'userjwt', 'userjwt');
this.assignOption(opts, 'jwt', 'userjwt');
this.assignOption(opts, 'JWT', 'userjwt');
this.assignOption(opts, 'userJWT', 'userjwt');
this.assignOption(opts, 'usercreds', 'usercreds');
this.assignOption(opts, 'userCreds', 'usercreds');
this.assignOption(opts, 'credentials', 'usercreds');
}

@@ -326,12 +357,12 @@

});
// Randomize if needed
if (options.noRandomize !== true) {
shuffle(client.servers);
}
// Randomize if needed
if (options.noRandomize !== true) {
shuffle(client.servers);
}
// if they gave an URL we should add it if different
if(options.url !== undefined && client.servers.indexOf(options.url) === -1) {
//make url first element so it is attempted first
client.servers.unshift(new Server(url.parse(options.url)));
}
// if they gave an URL we should add it if different
if (options.url !== undefined && client.servers.indexOf(options.url) === -1) {
// Make url first element so it is attempted first
client.servers.unshift(new Server(url.parse(options.url)));
}
} else {

@@ -343,4 +374,25 @@ if (undefined === options.url) {

}
// If we are not setup for tls, but were handed a url with a tls:// prefix
// then upgrade to tls.
if (options.tls === false) {
client.servers.forEach(function(server) {
if (server.url.protocol === 'tls' || server.url.protocol === 'tls:') {
options.tls = true;
}
});
}
};
function sanitizeUrl(url) {
if ((/^.*:\/\/.*/).exec(url) === null) {
// Does not have a scheme.
url = 'nats://' + url;
}
var u = new URL(url);
if (u.port === '') {
u.port = DEFAULT_PORT;
}
return u.toString();
}
/**

@@ -361,3 +413,3 @@ * Create a new server.

Server.prototype.toString = function() {
return this.url.href;
return this.url.href;
};

@@ -404,2 +456,10 @@

Client.prototype.checkTLSMismatch = function() {
// Switch over to TLS as needed on the fly.
if (this.info.tls_required === true ||
(this.options.tls !== false && this.stream.encrypted !== true)) {
if (undefined === this.options.tls) {
this.options.tls = true;
}
}
if (this.info.tls_required === true &&

@@ -428,2 +488,106 @@ this.options.tls === false) {

/**
* Load a user jwt from a chained credential file.
*
* @api private
*/
Client.prototype.loadUserJWT = function() {
var contents = fs.readFileSync(this.options.usercreds);
var m = CREDS.exec(contents); // jwt
if (m === null) {
this.emit('error', new NatsError(NO_USER_JWT_IN_CREDS_MSG, NO_USER_JWT_IN_CREDS));
this.closeStream();
return;
}
return m[1];
};
/**
* Load a user nkey seed from a chained credential file
* and sign nonce.
*
* @api private
*/
Client.prototype.loadKeyAndSignNonce = function(nonce) {
var contents = fs.readFileSync(this.options.usercreds);
var re = new RegExp(CREDS, 'g');
re.exec(contents); // jwt
var m = re.exec(contents); // seed
if (m === null) {
this.emit('error', new NatsError(NO_SEED_IN_CREDS_MSG, NO_SEED_IN_CREDS));
this.closeStream();
return;
}
var sk = nkeys.fromSeed(Buffer.from(m[1]));
return sk.sign(nonce);
};
/**
* Helper that takes a user credentials file and
* generates the proper opts object with proper handlers
* filled in. e.g nats.connect(url, nats.creds("my_creds.ttx")
*
* @params {String} [filepath]
*
* @api public
*/
exports.creds = function(filepath) {
if (undefined === filepath) {
return undefined;
}
return {
usercreds: filepath
};
};
/**
* Check for Nkey mismatch.
*
* @api private
*/
Client.prototype.checkNkeyMismatch = function() {
if (undefined === this.info.nonce) {
return false;
}
// If this has been specified make sure we can open the file and parse it.
if (this.options.usercreds !== undefined) {
// Treat this as a filename.
// For now we will not capture an error on file not found etc.
var contents = fs.readFileSync(this.options.usercreds);
if (CREDS.exec(contents) === null) {
this.emit('error', new NatsError(BAD_CREDS_MSG, BAD_CREDS));
this.closeStream();
return true;
}
// We have a valid file, set up callback handlers.
var client = this;
this.options.sig = function(nonce) {
return client.loadKeyAndSignNonce(nonce);
};
this.options.userjwt = function() {
return client.loadUserJWT();
};
return false;
}
if (undefined === this.options.sig) {
this.emit('error', new NatsError(SIGNATURE_REQUIRED_MSG, SIGNATURE_REQUIRED));
this.closeStream();
return true;
}
if (typeof (this.options.sig) !== 'function') {
this.emit('error', new NatsError(SIGCB_NOTFUNC_MSG, SIGCB_NOTFUNC));
this.closeStream();
return true;
}
if (undefined === this.options.nkey && undefined === this.options.userjwt) {
this.emit('error', new NatsError(NKEY_OR_JWT_REQ_MSG, NKEY_OR_JWT_REQ));
this.closeStream();
return true;
}
return false;
};
/**
* Callback for first flush/connect.

@@ -560,3 +724,3 @@ *

*/
Client.prototype.sendConnect = function(challengeResponse) {
Client.prototype.sendConnect = function() {
// Queue the connect command.

@@ -570,2 +734,16 @@ var cs = {

};
if (this.info.nonce !== undefined && this.options.sig !== undefined) {
var sig = this.options.sig(Buffer.from(this.info.nonce));
cs.sig = sig.toString('base64');
}
if (this.options.userjwt !== undefined) {
if (typeof (this.options.userjwt) === 'function') {
cs.jwt = this.options.userjwt();
} else {
cs.jwt = this.options.userjwt;
}
}
if (this.options.nkey !== undefined) {
cs.nkey = this.options.nkey;
}
if (this.user !== undefined) {

@@ -581,6 +759,4 @@ cs.user = this.user;

}
if(challengeResponse && challengeResponse.nkey && Buffer.isBuffer(challengeResponse.sig)) {
cs.nkey = challengeResponse.nkey;
cs.sig = challengeResponse.sig.toString('base64');
if (this.options.nkey !== undefined) {
cs.nkey = this.options.nkey;
}

@@ -644,4 +820,5 @@

this.selectServer();
// See #45 if we have a stream release the listeners
// otherwise in addition to the leak events will fire fire
// See #45 if we have a stream release the listeners otherwise in addition
// to the leaking of events, the old events will still fire.
if (this.stream) {

@@ -682,3 +859,3 @@ this.stream.removeAllListeners();

Client.prototype.close = function() {
if(this.pingTimer) {
if (this.pingTimer) {
clearTimeout(this.pingTimer);

@@ -844,23 +1021,2 @@ delete this.pingTimer;

/**
* @api private
*/
Client.prototype.handlesChallenge = function() {
var ah = this.options.authHandler;
return ah && typeof ah.sign === 'function' && this.info.nonce != undefined;
};
/**
* @api private
*/
Client.prototype.handleChallenge = function() {
var ah = this.options.authHandler;
if(ah && this.info.nonce !== undefined) {
var sig = ah.sign(Buffer.from(this.info.nonce));
return {sig: sig, nkey: ah.id};
} else {
return undefined;
}
};
/**
* Process the inbound data queue.

@@ -925,16 +1081,2 @@ *

client.info = JSON.parse(m[1]);
// Check on TLS mismatch.
if (client.checkTLSMismatch() === true) {
return;
}
var challengeResponse;
if(client.handlesChallenge()) {
try {
challengeResponse = this.handleChallenge();
} catch(ex) {
client.emit('error', new NatsError("client code exception handleChallenge()", API_ERR, ex));
}
}
// Always try to read the connect_urls from info

@@ -945,5 +1087,12 @@ client.processServerUpdate();

if (client.infoReceived === false) {
// Check on TLS mismatch.
if (client.checkTLSMismatch() === true) {
return;
}
if (client.checkNkeyMismatch() === true) {
return;
}
// Switch over to TLS as needed.
if (client.options.tls !== false &&
client.stream.encrypted !== true) {
if (client.info.tls_required === true) {
var tlsOpts = {

@@ -968,3 +1117,3 @@ socket: client.stream

// Send the connect message and subscriptions immediately
client.sendConnect(challengeResponse);
client.sendConnect();
client.sendSubscriptions();

@@ -1074,46 +1223,48 @@

Client.prototype.processServerUpdate = function() {
var client = this;
if (client.info.connect_urls && client.info.connect_urls.length > 0) {
// parse the infos
var tmp = {};
client.info.connect_urls.forEach(function(server) {
var u = 'nats://' + server;
var s = new Server(url.parse(u));
// implicit servers are ones added via the info connect_urls
s.implicit = true;
tmp[s.url.href] = s;
});
var client = this;
if (client.info.connect_urls && client.info.connect_urls.length > 0) {
// parse the infos
var tmp = {};
client.info.connect_urls.forEach(function(server) {
var u = 'nats://' + server;
var s = new Server(url.parse(u));
// implicit servers are ones added via the info connect_urls
s.implicit = true;
tmp[s.url.href] = s;
});
// remove implicit servers that are no longer reported
var toDelete = [];
client.servers.forEach(function(s, index) {
var u = s.url.href;
if(s.implicit && client.currentServer.url.href !== u && tmp[u] === undefined) {
// server was removed
toDelete.push(index);
}
// remove this entry from reported
delete tmp[u];
});
// remove implicit servers that are no longer reported
var toDelete = [];
client.servers.forEach(function(s, index) {
var u = s.url.href;
if (s.implicit && client.currentServer.url.href !== u && tmp[u] === undefined) {
// server was removed
toDelete.push(index);
}
// remove this entry from reported
delete tmp[u];
});
// perform the deletion
toDelete.reverse();
toDelete.forEach(function(index) {
client.servers.splice(index, 1);
});
// perform the deletion
toDelete.reverse();
toDelete.forEach(function(index) {
client.servers.splice(index, 1);
});
// remaining servers are new
var newURLs = [];
for(var k in tmp) {
if(tmp.hasOwnProperty(k)) {
client.servers.push(tmp[k]);
newURLs.push(k);
}
}
// remaining servers are new
var newURLs = [];
for (var k in tmp) {
if (tmp.hasOwnProperty(k)) {
client.servers.push(tmp[k]);
newURLs.push(k);
}
}
if(newURLs.length) {
// new reported servers useful for tests
client.emit('serversDiscovered', newURLs);
if (newURLs.length) {
// new reported servers useful for tests
client.emit('serversDiscovered', newURLs);
// simpler version
client.emit('servers', newURLs);
}
}
}
};

@@ -1137,2 +1288,3 @@

}
// Check for auto-unsubscribe

@@ -1164,3 +1316,3 @@ if (sub.max !== undefined) {

sub.callback(msg, this.payload.reply, this.payload.subj, this.payload.sid);
} catch(error) {
} catch (error) {
this.emit('error', error);

@@ -1375,3 +1527,3 @@ }

// the request configuration. Mux requests are always negative numbers
if(sid < 0) {
if (sid < 0) {
this.cancelMuxRequest(sid);

@@ -1424,5 +1576,5 @@ return;

// check the sid is not a mux sid - which is always negative
if(sid < 0) {
if (sid < 0) {
var conf = this.getMuxRequestConfig(sid);
if(conf && conf.timeout) {
if (conf && conf.timeout) {
// clear auto-set timeout

@@ -1436,6 +1588,6 @@ clearTimeout(conf.timeout);

if(sub) {
if (sub) {
sub.expected = expected;
var that = this;
sub.timeout = setTimeout(function () {
sub.timeout = setTimeout(function() {
callback(sid);

@@ -1471,3 +1623,3 @@ // if callback fails unsubscribe will leak

Client.prototype.request = function(subject, opt_msg, opt_options, callback) {
if(this.options.useOldRequestStyle) {
if (this.options.useOldRequestStyle) {
return this.oldRequest(subject, opt_msg, opt_options, callback);

@@ -1489,6 +1641,6 @@ }

if(opt_options.timeout) {
if (opt_options.timeout) {
var client = this;
conf.timeout = setTimeout(function() {
if(conf.callback) {
if (conf.callback) {
conf.callback(new NatsError(REQ_TIMEOUT_MSG_PREFIX + conf.id, REQ_TIMEOUT));

@@ -1546,3 +1698,3 @@ }

Client.prototype.requestOne = function(subject, opt_msg, opt_options, timeout, callback) {
if(this.options.useOldRequestStyle) {
if (this.options.useOldRequestStyle) {
return this.oldRequestOne(subject, opt_msg, opt_options, timeout, callback);

@@ -1588,3 +1740,3 @@ }

Client.prototype.createResponseMux = function() {
if(!this.respmux) {
if (!this.respmux) {
var client = this;

@@ -1596,12 +1748,13 @@ var inbox = createInbox();

var conf = client.getMuxRequestConfig(token);
if(conf) {
if(conf.hasOwnProperty('expected')) {
if (conf) {
if (conf.callback) {
conf.callback(msg, reply);
}
if (conf.hasOwnProperty('expected')) {
conf.received++;
if (conf.received >= conf.expected) {
client.cancelMuxRequest(token);
client.emit('unsubscribe', sid, subject);
}
}
if(conf.callback) {
conf.callback(msg, reply);
}
}

@@ -1629,4 +1782,10 @@ });

var conf = {token: token, callback: callback, inbox: inbox, id: this.respmux.nextID--, received: 0};
if(expected > 0) {
var conf = {
token: token,
callback: callback,
inbox: inbox,
id: this.respmux.nextID--,
received: 0
};
if (expected > 0) {
conf.expected = expected;

@@ -1672,3 +1831,3 @@ }

if (conf) {
if(conf.timeout) {
if (conf.timeout) {
clearTimeout(conf.timeout);

@@ -1675,0 +1834,0 @@ }

{
"name": "nats",
"version": "1.1.0",
"version": "1.2.0",
"description": "Node.js client for NATS, a lightweight, high-performance cloud native messaging system",

@@ -37,28 +37,28 @@ "keywords": [

"cover": "istanbul cover _mocha",
"lint": "if-node-version '>=6' eslint ./lib ./examples/node-pub ./examples/node-sub ./benchmark ./test",
"lint": "if-node-version >=4 eslint ./lib ./examples ./benchmark ./test",
"fmt": "js-beautify -n --config crockford.jscsrc -r lib/* test/*.js test/support/*.js examples/* benchmark/*.js"
},
"engines": {
"node": ">= 6.0.0"
"node": ">= 4.5.0"
},
"dependencies": {
"nuid": "^1.0.0"
"nuid": "^1.0.0",
"ts-nkeys": "^1.0.8"
},
"devDependencies": {
"@types/node": "^10.12.0",
"coveralls": "^2.11.2",
"dependency-check": "2.5.x",
"eslint": "^5.7.0",
"minimist": "^1.2.0",
"coveralls": "^3.0.2",
"dependency-check": "^3.2.1",
"eslint": "^5.10.0",
"if-node-version": "^1.1.1",
"istanbul": "0.4.x",
"istanbul": "^0.4.5",
"js-beautify": "^1.6.12",
"jshint": "^2.9.6",
"jshint-stylish": "2.2.x",
"mocha": "2.5.x",
"mocha": "^5.2.0",
"mocha-lcov-reporter": "1.2.x",
"mocha-multi": "0.9.x",
"should": ">= 9.0.0",
"ts-nkeys": "^1.0.4"
"mocha-multi": "^1.0.1",
"should": ">= 9.0.0"
},
"typings": "./index.d.ts"
}

@@ -6,4 +6,4 @@ # NATS - Node.js Client

[![license](https://img.shields.io/github/license/nats-io/node-nats.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[![Travis branch](https://img.shields.io/travis/nats-io/node-nats/master.svg)]()
[![Coveralls github branch](https://img.shields.io/coveralls/github/nats-io/node-nats/master.svg)]()
[![Build Status](https://travis-ci.org/nats-io/node-nats.svg?branch=master)](https://travis-ci.org/nats-io/node-nats)
[![Coveralls](https://img.shields.io/coveralls/github/nats-io/node-nats/master.svg)](https://coveralls.io/r/nats-io/node-nats?branch=master)
[![npm](https://img.shields.io/npm/v/nats.svg)](https://www.npmjs.com/package/nats)

@@ -151,5 +151,42 @@ [![npm](https://img.shields.io/npm/dm/nats.svg)](https://www.npmjs.com/package/nats)

```
## Authentication
## New Authentication (Nkeys and User Credentials)
See examples for more usage.
```javascript
// Simple connect using credentials file. This loads JWT and signing key
// each time that NATS connects.
var nc = NATS.connect('connect.ngs.global', NATS.creds("./myid.creds");
// Setting nkey and signing callback directly.
var nc = NATS.connect(url, {
nkey: 'UAH42UG6PV552P5SWLWTBP3H3S5BHAVCO2IEKEXUANJXR75J63RQ5WM6',
sigCB: function(nonce) {
return sk.sign(nonce);
}
});
// Setting user JWT statically.
var nc = NATS.connect(url, {
userJWT: myJWT,
sigCB: function(nonce) {
return sk.sign(nonce);
}
});
// Having user JWT be a function that returns the JWT. Can be useful for
// loading a new JWT.
var nc = NATS.connect(url, {
userJWT: function() {
return myJWT;
},
sigCB: function(nonce) {
return sk.sign(nonce);
}
});
```
## Basic Authentication
```javascript
// Connect with username and password in the url

@@ -222,3 +259,3 @@ var nc = NATS.connect("nats://foo:bar@localhost:4222");

// To prevent payload conversion from a Buffer to a string, set the
// To prevent payload conversion from a Buffer to a string, set the
// preserveBuffers option to true. Message payload return will be a Buffer.

@@ -234,3 +271,3 @@

// To change the default behaviour specify the max number of connection
// attempts in `maxReconnectAttempts` (set to -1 to retry forever), and the
// attempts in `maxReconnectAttempts` (set to -1 to retry forever), and the
// time in milliseconds between reconnects in `reconnectTimeWait`.

@@ -294,14 +331,10 @@

| `waitOnFirstConnect` | | `false` | If `true` the server will fall back to a reconnect mode if it fails its first connection attempt.
| `yieldTime` | | | If set, processing will yield at least the specified number of milliseconds to IO callbacks before processing inbound messages
| `yieldTime` | | | If set, processing will yield at least the specified number of milliseconds to IO callbacks before processing inbound messages
## Supported Node Versions
## Supported Node Versions
Support policy for Nodejs versions follows
[Nodejs release support]( https://github.com/nodejs/Release).
We will support and build node-nats on even Nodejs versions that are current
or in maintenance.
Our support policy for Nodejs versions follows [Nodejs release support]( https://github.com/nodejs/Release).
We will support and build node-nats on even-numbered Nodejs versions that are current or in LTS.

@@ -308,0 +341,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc