Merge branch 'dtrace'

This commit is contained in:
Mark Cavage 2011-09-02 22:10:01 -04:00
commit 5fe70eb739
6 changed files with 217 additions and 35 deletions

View File

@ -21,7 +21,17 @@ function isWhitespace(c) {
return re.test(c);
}
function RDN() {}
function RDN(obj) {
var self = this;
if (obj) {
Object.keys(obj).forEach(function(k) {
self[k] = obj[k];
});
}
}
RDN.prototype.toString = function() {
var self = this;

72
lib/dtrace.js Normal file
View File

@ -0,0 +1,72 @@
// Copyright 2011 Mark Cavage, Inc. All rights reserved.
var dtrace = require('dtrace-provider');
///--- Globals
var SERVER_PROVIDER;
/* Args:
* 0 -> RequestId (<ip>:<src port>:<msgID>)
* 1 -> remoteIP
* 2 -> bindDN
* 3 -> req.dn
* 4,5 -> op specific
*/
var SERVER_PROBES = {
// 4: attributes.length
add: ['char *', 'char *', 'char *', 'char *', 'int'],
bind: ['char *', 'char *', 'char *', 'char *'],
// 4: attribute, 5: value
compare: ['char *', 'char *', 'char *', 'char *', 'char *', 'char *'],
'delete': ['char *', 'char *', 'char *', 'char *'],
// 4: requestName, 5: requestValue
exop: ['char *', 'char *', 'char *', 'char *', 'char *', 'char *'],
// 4: changes.length
modify: ['char *', 'char *', 'char *', 'char *', 'int'],
// 4: newRdn, 5: newSuperior
modifyDN: ['char *', 'char *', 'char *', 'char *', 'char *', 'char *'],
// 4: filter, 5: scope
search: ['char *', 'char *', 'char *', 'char *', 'char *', 'char *'],
unbind: ['char *', 'char *', 'char *', 'char *'],
// remote IP
connection: ['char *'],
request: ['char *', 'char *', 'char *', 'char *'],
// requestId, remoteIp, bindDN, request.dn, statusCode, errorMessage
response: ['char *', 'char *', 'char *', 'char *', 'int', 'char *']
};
///--- API
module.exports = function() {
if (!SERVER_PROVIDER) {
SERVER_PROVIDER = dtrace.createDTraceProvider('ldapjs');
Object.keys(SERVER_PROBES).forEach(function(p) {
var args = SERVER_PROBES[p].splice(0);
args.unshift(p);
dtrace.DTraceProvider.prototype.addProbe.apply(SERVER_PROVIDER, args);
});
SERVER_PROVIDER.enable();
}
return SERVER_PROVIDER;
}();

View File

@ -8,7 +8,7 @@ var asn1 = require('asn1');
var LDAPMessage = require('./message');
var Protocol = require('../protocol');
var dtrace = require('../dtrace');
///--- Globals
@ -17,6 +17,7 @@ var Ber = asn1.Ber;
var BerWriter = asn1.BerWriter;
///--- API
function LDAPResult(options) {
@ -66,11 +67,25 @@ LDAPResult.prototype.end = function(status) {
this.log.debug('%s: sending: %j', this.connection.ldap.id, this.json);
try {
var self = this;
this.connection.write(ber);
dtrace.fire('response', function() {
var c = self.connection || {ldap: {bindDN: ''}};
return [
(self.logId || ''),
(c.remoteAddress || ''),
c.ldap.bindDN.toString(),
(self.requestDN ? self.requestDN.toString() : ''),
self.status,
self.errorMessage
];
});
} catch (e) {
this.log.warn('%s failure to write message %j: %s',
this.connection.ldap.id, this.json, e.toString());
}
};

View File

@ -8,7 +8,7 @@ var asn1 = require('asn1');
var LDAPMessage = require('./message');
var LDAPResult = require('./result');
var DN = require('../dn').DN;
var dn = require('../dn');
var Protocol = require('../protocol');
@ -17,6 +17,8 @@ var Protocol = require('../protocol');
var Ber = asn1.Ber;
var DN = dn.DN;
var RDN = dn.RDN;
///--- API
@ -32,8 +34,14 @@ function UnbindRequest(options) {
options.protocolOp = Protocol.LDAP_REQ_UNBIND;
LDAPMessage.call(this, options);
var self = this;
this.__defineGetter__('type', function() { return 'UnbindRequest'; });
this.__defineGetter__('_dn', function() { return new DN([{}]); });
this.__defineGetter__('_dn', function() {
if (self.connection)
return self.connection.ldap.bindDN;
return new DN([new RDN({cn: 'anonymous'})]);
});
}
util.inherits(UnbindRequest, LDAPMessage);
module.exports = UnbindRequest;

View File

@ -10,6 +10,7 @@ var asn1 = require('asn1');
var sprintf = require('sprintf').sprintf;
var dn = require('./dn');
var dtrace = require('./dtrace');
var errors = require('./errors');
var Protocol = require('./protocol');
var logStub = require('./log_stub');
@ -173,6 +174,25 @@ function noExOpHandler(req, res, next) {
}
function getDTraceHander(op, cb1, cb2) {
assert.ok(op);
return function(req, res, next) {
dtrace.fire(op, function() {
var c = req.connection;
return [
req.logId,
c.remoteAddress,
c.ldap.bindDN.toString(),
req.dn.toString(),
cb1 ? cb1(req, res) : undefined,
cb2 ? cb2(req, res) : undefined
];
});
return next();
};
}
///--- API
@ -226,9 +246,12 @@ function Server(options) {
c.remotePort = c.fd;
}
var rdn = new dn.RDN({cn: 'anonymous'});
c.ldap = {
id: c.remoteAddress + ':' + c.remotePort,
config: options
config: options,
_bindDN: new DN([rdn])
};
c.addListener('timeout', function() {
log.trace('%s timed out', c.ldap.id);
@ -247,7 +270,7 @@ function Server(options) {
});
c.ldap.__defineGetter__('bindDN', function() {
return c.ldap._bindDN || new DN([{cn: 'anonymous'}]);
return c.ldap._bindDN;
});
c.ldap.__defineSetter__('bindDN', function(val) {
if (!(val instanceof DN))
@ -264,6 +287,8 @@ function Server(options) {
if (log.isTraceEnabled())
log.trace('new connection from %s', c.ldap.id);
dtrace.fire('connection', function() { return [c.remoteAddress]; });
c.parser = new Parser({
log4js: options.log4js
});
@ -274,6 +299,15 @@ function Server(options) {
if (log.isDebugEnabled())
log.debug('%s: message received: req=%j', c.ldap.id, req.json);
dtrace.fire('request', function() {
return [
req.logId,
c.remoteAddress,
c.ldap.bindDN.toString(),
req.dn.toString()
];
});
var res = getResponse(req);
if (!res) {
log.warn('Unimplemented server method: %s', req.type);
@ -281,6 +315,10 @@ function Server(options) {
return;
}
res.connection = c;
res.logId = req.logId;
res.requestDN = req.dn;
var chain = self._getHandlerChain(req);
var i = 0;
@ -387,9 +425,13 @@ module.exports = Server;
* @throws {TypeError} on bad input
*/
Server.prototype.add = function(name) {
return this._mount(Protocol.LDAP_REQ_ADD,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('add',
function(req, res) {
return req.attributes.length;
}));
return this._mount(Protocol.LDAP_REQ_ADD, name, args);
};
@ -404,9 +446,10 @@ Server.prototype.add = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.bind = function(name) {
return this._mount(Protocol.LDAP_REQ_BIND,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('bind'));
return this._mount(Protocol.LDAP_REQ_BIND, name, args);
};
@ -421,9 +464,16 @@ Server.prototype.bind = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.compare = function(name) {
return this._mount(Protocol.LDAP_REQ_COMPARE,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('compare',
function(req, res) {
return req.attribute;
},
function(req, res) {
return req.value;
}));
return this._mount(Protocol.LDAP_REQ_COMPARE, name, args);
};
@ -438,9 +488,10 @@ Server.prototype.compare = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.del = function(name) {
return this._mount(Protocol.LDAP_REQ_DELETE,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('delete'));
return this._mount(Protocol.LDAP_REQ_DELETE, name, args);
};
@ -455,10 +506,16 @@ Server.prototype.del = function(name) {
* @throws {TypeError} on bad input.
*/
Server.prototype.exop = function(name) {
return this._mount(Protocol.LDAP_REQ_EXTENSION,
name,
Array.prototype.slice.call(arguments, 1),
true);
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('exop',
function(req, res) {
return req.name;
},
function(req, res) {
return req.value;
}));
return this._mount(Protocol.LDAP_REQ_EXTENSION, name, args, true);
};
@ -473,9 +530,13 @@ Server.prototype.exop = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.modify = function(name) {
return this._mount(Protocol.LDAP_REQ_MODIFY,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('modify',
function(req, res) {
return req.changes.length;
}));
return this._mount(Protocol.LDAP_REQ_MODIFY, name, args);
};
@ -490,9 +551,17 @@ Server.prototype.modify = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.modifyDN = function(name) {
return this._mount(Protocol.LDAP_REQ_MODRDN,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('modifyDN',
function(req, res) {
return req.newRdn.toString();
},
function(req, res) {
return (req.newSuperior ?
req.newSuperior.toString() : '');
}));
return this._mount(Protocol.LDAP_REQ_MODRDN, name, args);
};
@ -507,9 +576,16 @@ Server.prototype.modifyDN = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.search = function(name) {
return this._mount(Protocol.LDAP_REQ_SEARCH,
name,
Array.prototype.slice.call(arguments, 1));
var args = Array.prototype.slice.call(arguments, 1);
args.unshift(getDTraceHander('search',
function(req, res) {
return req.scope;
},
function(req, res) {
return req.filter.toString();
}));
return this._mount(Protocol.LDAP_REQ_SEARCH, name, args);
};
@ -523,10 +599,10 @@ Server.prototype.search = function(name) {
* @throws {TypeError} on bad input
*/
Server.prototype.unbind = function() {
return this._mount(Protocol.LDAP_REQ_UNBIND,
'unbind',
Array.prototype.slice.call(arguments, 0),
true);
var args = Array.prototype.slice.call(arguments, 0);
args.unshift(getDTraceHander('unbind'));
return this._mount(Protocol.LDAP_REQ_UNBIND, 'unbind', args, true);
};

View File

@ -15,6 +15,7 @@
"dependencies": {
"asn1": "~0.1.5",
"buffertools": "~1.0.3",
"dtrace-provider": "~0.0.2",
"sprintf": "~0.1.1"
},
"devDependencies": {