mirror of
				https://github.com/nodemailer/wildduck.git
				synced 2025-10-26 22:16:26 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			107 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| const zlib = require('zlib');
 | |
| 
 | |
| // tag COMPRESS DEFLATE
 | |
| module.exports = {
 | |
|     state: ['Authenticated', 'Selected'],
 | |
| 
 | |
|     schema: [
 | |
|         {
 | |
|             name: 'mechanism',
 | |
|             type: 'string'
 | |
|         }
 | |
|     ],
 | |
| 
 | |
|     handler(command, callback) {
 | |
|         let mechanism = ((command.attributes[0] && command.attributes[0].value) || '')
 | |
|             .toString()
 | |
|             .toUpperCase()
 | |
|             .trim();
 | |
| 
 | |
|         if (!mechanism) {
 | |
|             return callback(null, {
 | |
|                 response: 'BAD'
 | |
|             });
 | |
|         }
 | |
| 
 | |
|         if (mechanism !== 'DEFLATE') {
 | |
|             return callback(null, {
 | |
|                 response: 'BAD',
 | |
|                 code: 'CANNOT',
 | |
|                 message: 'Unsupported compression mechanism'
 | |
|             });
 | |
|         }
 | |
| 
 | |
|         setImmediate(() => {
 | |
|             this.compression = true;
 | |
| 
 | |
|             this._deflate = zlib.createDeflateRaw({
 | |
|                 windowBits: 15
 | |
|             });
 | |
|             this._inflate = zlib.createInflateRaw();
 | |
| 
 | |
|             this._deflate.once('error', err => {
 | |
|                 this._server.logger.debug(
 | |
|                     {
 | |
|                         err,
 | |
|                         tnx: 'deflate',
 | |
|                         cid: this.id
 | |
|                     },
 | |
|                     '[%s] Deflate error %s',
 | |
|                     this.id,
 | |
|                     err.message
 | |
|                 );
 | |
|                 this.close();
 | |
|             });
 | |
| 
 | |
|             this._inflate.once('error', err => {
 | |
|                 this._server.logger.debug(
 | |
|                     {
 | |
|                         err,
 | |
|                         tnx: 'inflate',
 | |
|                         cid: this.id
 | |
|                     },
 | |
|                     '[%s] Inflate error %s',
 | |
|                     this.id,
 | |
|                     err.message
 | |
|                 );
 | |
|                 this.close();
 | |
|             });
 | |
| 
 | |
|             this.writeStream.unpipe(this._socket);
 | |
|             this._deflate.pipe(this._socket);
 | |
|             let reading = false;
 | |
|             let readNext = () => {
 | |
|                 reading = true;
 | |
| 
 | |
|                 let chunk;
 | |
|                 while ((chunk = this.writeStream.read()) !== null) {
 | |
|                     if (this._deflate && this._deflate.write(chunk) === false) {
 | |
|                         return this._deflate.once('drain', readNext);
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 // flush data to socket
 | |
|                 if (this._deflate) {
 | |
|                     this._deflate.flush();
 | |
|                 }
 | |
| 
 | |
|                 reading = false;
 | |
|             };
 | |
|             this.writeStream.on('readable', () => {
 | |
|                 if (!reading) {
 | |
|                     readNext();
 | |
|                 }
 | |
|             });
 | |
| 
 | |
|             this._socket.unpipe(this._parser);
 | |
|             this._socket.pipe(this._inflate).pipe(this._parser);
 | |
|         });
 | |
| 
 | |
|         callback(null, {
 | |
|             response: 'OK',
 | |
|             message: 'DEFLATE active'
 | |
|         });
 | |
|     }
 | |
| };
 |