| var assert = require('assert'); | 
| var util = require('util'); | 
|   | 
| var Buffer = require('buffer').Buffer; | 
|   | 
| // Node.js version | 
| var mode = /^v0\.8\./.test(process.version) ? 'rusty' : | 
|            /^v0\.(9|10)\./.test(process.version) ? 'old' : | 
|            /^v0\.12\./.test(process.version) ? 'normal' : | 
|            'modern'; | 
|   | 
| var HTTPParser; | 
|   | 
| var methods; | 
| var reverseMethods; | 
|   | 
| var kOnHeaders; | 
| var kOnHeadersComplete; | 
| var kOnMessageComplete; | 
| var kOnBody; | 
| if (mode === 'normal' || mode === 'modern') { | 
|   HTTPParser = process.binding('http_parser').HTTPParser; | 
|   methods = HTTPParser.methods; | 
|   | 
|   // v6 | 
|   if (!methods) | 
|     methods = process.binding('http_parser').methods; | 
|   | 
|   reverseMethods = {}; | 
|   | 
|   methods.forEach(function(method, index) { | 
|     reverseMethods[method] = index; | 
|   }); | 
|   | 
|   kOnHeaders = HTTPParser.kOnHeaders | 0; | 
|   kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0; | 
|   kOnMessageComplete = HTTPParser.kOnMessageComplete | 0; | 
|   kOnBody = HTTPParser.kOnBody | 0; | 
| } else { | 
|   kOnHeaders = 'onHeaders'; | 
|   kOnHeadersComplete = 'onHeadersComplete'; | 
|   kOnMessageComplete = 'onMessageComplete'; | 
|   kOnBody = 'onBody'; | 
| } | 
|   | 
| function Deceiver(socket, options) { | 
|   this.socket = socket; | 
|   this.options = options || {}; | 
|   this.isClient = this.options.isClient; | 
| } | 
| module.exports = Deceiver; | 
|   | 
| Deceiver.create = function create(stream, options) { | 
|   return new Deceiver(stream, options); | 
| }; | 
|   | 
| Deceiver.prototype._toHeaderList = function _toHeaderList(object) { | 
|   var out = []; | 
|   var keys = Object.keys(object); | 
|   | 
|   for (var i = 0; i < keys.length; i++) | 
|     out.push(keys[i], object[keys[i]]); | 
|   | 
|   return out; | 
| }; | 
|   | 
| Deceiver.prototype._isUpgrade = function _isUpgrade(request) { | 
|   return request.method === 'CONNECT' || | 
|          request.headers.upgrade || | 
|          request.headers.connection && | 
|             /(^|\W)upgrade(\W|$)/i.test(request.headers.connection); | 
| }; | 
|   | 
| // TODO(indutny): support CONNECT | 
| if (mode === 'modern') { | 
|   /* | 
|   function parserOnHeadersComplete(versionMajor, versionMinor, headers, method, | 
|                                    url, statusCode, statusMessage, upgrade, | 
|                                    shouldKeepAlive) { | 
|    */ | 
|   Deceiver.prototype.emitRequest = function emitRequest(request) { | 
|     var parser = this.socket.parser; | 
|     assert(parser, 'No parser present'); | 
|   | 
|     parser.execute = null; | 
|   | 
|     var self = this; | 
|     var method = reverseMethods[request.method]; | 
|     parser.execute = function execute() { | 
|       self._skipExecute(this); | 
|       this[kOnHeadersComplete](1, | 
|                                1, | 
|                                self._toHeaderList(request.headers), | 
|                                method, | 
|                                request.path, | 
|                                0, | 
|                                '', | 
|                                self._isUpgrade(request), | 
|                                true); | 
|       return 0; | 
|     }; | 
|   | 
|     this._emitEmpty(); | 
|   }; | 
|   | 
|   Deceiver.prototype.emitResponse = function emitResponse(response) { | 
|     var parser = this.socket.parser; | 
|     assert(parser, 'No parser present'); | 
|   | 
|     parser.execute = null; | 
|   | 
|     var self = this; | 
|     parser.execute = function execute() { | 
|       self._skipExecute(this); | 
|       this[kOnHeadersComplete](1, | 
|                                1, | 
|                                self._toHeaderList(response.headers), | 
|                                response.path, | 
|                                response.code, | 
|                                response.status, | 
|                                response.reason || '', | 
|                                self._isUpgrade(response), | 
|                                true); | 
|       return 0; | 
|     }; | 
|   | 
|     this._emitEmpty(); | 
|   }; | 
| } else { | 
|   /* | 
|     `function parserOnHeadersComplete(info) {` | 
|   | 
|     info = { .versionMajor, .versionMinor, .url, .headers, .method, | 
|              .statusCode, .statusMessage, .upgrade, .shouldKeepAlive } | 
|    */ | 
|   Deceiver.prototype.emitRequest = function emitRequest(request) { | 
|     var parser = this.socket.parser; | 
|     assert(parser, 'No parser present'); | 
|   | 
|     var method = request.method; | 
|     if (reverseMethods) | 
|       method = reverseMethods[method]; | 
|   | 
|     var info = { | 
|       versionMajor: 1, | 
|       versionMinor: 1, | 
|       url: request.path, | 
|       headers: this._toHeaderList(request.headers), | 
|       method: method, | 
|       statusCode: 0, | 
|       statusMessage: '', | 
|       upgrade: this._isUpgrade(request), | 
|       shouldKeepAlive: true | 
|     }; | 
|   | 
|     var self = this; | 
|     parser.execute = function execute() { | 
|       self._skipExecute(this); | 
|       this[kOnHeadersComplete](info); | 
|       return 0; | 
|     }; | 
|   | 
|     this._emitEmpty(); | 
|   }; | 
|   | 
|   Deceiver.prototype.emitResponse = function emitResponse(response) { | 
|     var parser = this.socket.parser; | 
|     assert(parser, 'No parser present'); | 
|   | 
|     var info = { | 
|       versionMajor: 1, | 
|       versionMinor: 1, | 
|       url: response.path, | 
|       headers: this._toHeaderList(response.headers), | 
|       method: false, | 
|       statusCode: response.status, | 
|       statusMessage: response.reason || '', | 
|       upgrade: this._isUpgrade(response), | 
|       shouldKeepAlive: true | 
|     }; | 
|   | 
|     var self = this; | 
|     parser.execute = function execute() { | 
|       self._skipExecute(this); | 
|       this[kOnHeadersComplete](info); | 
|       return 0; | 
|     }; | 
|   | 
|     this._emitEmpty(); | 
|   }; | 
| } | 
|   | 
| Deceiver.prototype._skipExecute = function _skipExecute(parser) { | 
|   var self = this; | 
|   var oldExecute = parser.constructor.prototype.execute; | 
|   var oldFinish = parser.constructor.prototype.finish; | 
|   | 
|   parser.execute = null; | 
|   parser.finish = null; | 
|   | 
|   parser.execute = function execute(buffer, start, len) { | 
|     // Parser reuse | 
|     if (this.socket !== self.socket) { | 
|       this.execute = oldExecute; | 
|       this.finish = oldFinish; | 
|       return this.execute(buffer, start, len); | 
|     } | 
|   | 
|     if (start !== undefined) | 
|       buffer = buffer.slice(start, start + len); | 
|     self.emitBody(buffer); | 
|     return len; | 
|   }; | 
|   | 
|   parser.finish = function finish() { | 
|     // Parser reuse | 
|     if (this.socket !== self.socket) { | 
|       this.execute = oldExecute; | 
|       this.finish = oldFinish; | 
|       return this.finish(); | 
|     } | 
|   | 
|     this.execute = oldExecute; | 
|     this.finish = oldFinish; | 
|     self.emitMessageComplete(); | 
|   }; | 
| }; | 
|   | 
| Deceiver.prototype.emitBody = function emitBody(buffer) { | 
|   var parser = this.socket.parser; | 
|   assert(parser, 'No parser present'); | 
|   | 
|   parser[kOnBody](buffer, 0, buffer.length); | 
| }; | 
|   | 
| Deceiver.prototype._emitEmpty = function _emitEmpty() { | 
|   // Emit data to force out handling of UPGRADE | 
|   var empty = new Buffer(0); | 
|   if (this.socket.ondata) | 
|     this.socket.ondata(empty, 0, 0); | 
|   else | 
|     this.socket.emit('data', empty); | 
| }; | 
|   | 
| Deceiver.prototype.emitMessageComplete = function emitMessageComplete() { | 
|   var parser = this.socket.parser; | 
|   assert(parser, 'No parser present'); | 
|   | 
|   parser[kOnMessageComplete](); | 
| }; |