|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // Copyright 2011 Mark Cavage, Inc. All rights reserved.
-
- var EventEmitter = require('events').EventEmitter;
- var util = require('util');
-
- var assert = require('assert-plus');
- var asn1 = require('asn1');
- var VError = require('verror').VError;
-
- var AbandonRequest = require('./abandon_request');
- var AddRequest = require('./add_request');
- var AddResponse = require('./add_response');
- var BindRequest = require('./bind_request');
- var BindResponse = require('./bind_response');
- var CompareRequest = require('./compare_request');
- var CompareResponse = require('./compare_response');
- var DeleteRequest = require('./del_request');
- var DeleteResponse = require('./del_response');
- var ExtendedRequest = require('./ext_request');
- var ExtendedResponse = require('./ext_response');
- var ModifyRequest = require('./modify_request');
- var ModifyResponse = require('./modify_response');
- var ModifyDNRequest = require('./moddn_request');
- var ModifyDNResponse = require('./moddn_response');
- var SearchRequest = require('./search_request');
- var SearchEntry = require('./search_entry');
- var SearchReference = require('./search_reference');
- var SearchResponse = require('./search_response');
- var UnbindRequest = require('./unbind_request');
- var UnbindResponse = require('./unbind_response');
-
- var LDAPResult = require('./result');
- var Message = require('./message');
-
- var Protocol = require('../protocol');
-
-
- ///--- Globals
-
- var Ber = asn1.Ber;
- var BerReader = asn1.BerReader;
-
-
- ///--- API
-
- function Parser(options) {
- assert.object(options);
- assert.object(options.log);
-
- EventEmitter.call(this);
-
- this.buffer = null;
- this.log = options.log;
- }
- util.inherits(Parser, EventEmitter);
-
- Parser.prototype.write = function (data) {
- if (!data || !Buffer.isBuffer(data))
- throw new TypeError('data (buffer) required');
-
- var nextMessage = null;
- var self = this;
-
- function end() {
- if (nextMessage)
- return self.write(nextMessage);
-
- return true;
- }
-
- self.buffer = (self.buffer ? Buffer.concat([self.buffer, data]) : data);
-
- var ber = new BerReader(self.buffer);
-
- var foundSeq = false;
- try {
- foundSeq = ber.readSequence();
- } catch (e) {
- this.emit('error', e);
- }
-
- if (!foundSeq || ber.remain < ber.length) {
- // ENOTENOUGH
- return false;
- } else if (ber.remain > ber.length) {
- // ETOOMUCH
- // This is sort of ugly, but allows us to make miminal copies
- nextMessage = self.buffer.slice(ber.offset + ber.length);
- ber._size = ber.offset + ber.length;
- assert.equal(ber.remain, ber.length);
- }
-
- // If we're here, ber holds the message, and nextMessage is temporarily
- // pointing at the next sequence of data (if it exists)
- self.buffer = null;
-
- var message;
- try {
- // Bail here if peer isn't speaking protocol at all
- message = this.getMessage(ber);
-
- if (!message) {
- return end();
- }
- message.parse(ber);
- } catch (e) {
- this.emit('error', e, message);
- return false;
- }
-
- this.emit('message', message);
- return end();
- };
-
- Parser.prototype.getMessage = function (ber) {
- assert.ok(ber);
-
- var self = this;
-
- var messageID = ber.readInt();
- var type = ber.readSequence();
-
- var Message;
- switch (type) {
-
- case Protocol.LDAP_REQ_ABANDON:
- Message = AbandonRequest;
- break;
-
- case Protocol.LDAP_REQ_ADD:
- Message = AddRequest;
- break;
-
- case Protocol.LDAP_REP_ADD:
- Message = AddResponse;
- break;
-
- case Protocol.LDAP_REQ_BIND:
- Message = BindRequest;
- break;
-
- case Protocol.LDAP_REP_BIND:
- Message = BindResponse;
- break;
-
- case Protocol.LDAP_REQ_COMPARE:
- Message = CompareRequest;
- break;
-
- case Protocol.LDAP_REP_COMPARE:
- Message = CompareResponse;
- break;
-
- case Protocol.LDAP_REQ_DELETE:
- Message = DeleteRequest;
- break;
-
- case Protocol.LDAP_REP_DELETE:
- Message = DeleteResponse;
- break;
-
- case Protocol.LDAP_REQ_EXTENSION:
- Message = ExtendedRequest;
- break;
-
- case Protocol.LDAP_REP_EXTENSION:
- Message = ExtendedResponse;
- break;
-
- case Protocol.LDAP_REQ_MODIFY:
- Message = ModifyRequest;
- break;
-
- case Protocol.LDAP_REP_MODIFY:
- Message = ModifyResponse;
- break;
-
- case Protocol.LDAP_REQ_MODRDN:
- Message = ModifyDNRequest;
- break;
-
- case Protocol.LDAP_REP_MODRDN:
- Message = ModifyDNResponse;
- break;
-
- case Protocol.LDAP_REQ_SEARCH:
- Message = SearchRequest;
- break;
-
- case Protocol.LDAP_REP_SEARCH_ENTRY:
- Message = SearchEntry;
- break;
-
- case Protocol.LDAP_REP_SEARCH_REF:
- Message = SearchReference;
- break;
-
- case Protocol.LDAP_REP_SEARCH:
- Message = SearchResponse;
- break;
-
- case Protocol.LDAP_REQ_UNBIND:
- Message = UnbindRequest;
- break;
-
- default:
- this.emit('error',
- new Error('Op 0x' + (type ? type.toString(16) : '??') +
- ' not supported'),
- new LDAPResult({
- messageID: messageID,
- protocolOp: type || Protocol.LDAP_REP_EXTENSION
- }));
-
- return false;
- }
-
-
- return new Message({
- messageID: messageID,
- log: self.log
- });
- };
-
-
- ///--- Exports
-
- module.exports = Parser;
|