@@ -28,18 +28,17 @@ module.exports = params => {
2828 } ) ;
2929 connection . send ( buf ) ;
3030 return Promise . race ( [
31- util . promiseTimeout ( 3000 ) . then ( ( ) => 'timeout' ) ,
31+ util . promiseTimeout ( 3000 ) . then ( ( ) => {
32+ let err = new Error ( 'Auth timeout' ) ;
33+ return Promise . reject ( err ) ;
34+ } ) ,
3235 connection . getData ( dataHandler )
3336 ] ) . then ( data => {
3437 // TODO: data as a single type, not string/object
35- if ( 'timeout' === data ) {
36- let err = new Error ( 'Auth timeout' ) ;
37- throw err ;
38- }
3938 let res = packet . response ( data ) ;
4039 if ( res . id === - 1 ) {
4140 let err = new Error ( 'Wrong rcon password' ) ;
42- throw err ;
41+ return Promise . reject ( err ) ;
4342 }
4443 // Auth successful, but continue after receiving packet index
4544 return connection . getData ( dataHandler ) . then ( ( ) => {
@@ -62,41 +61,87 @@ module.exports = params => {
6261 return nextPacketId += 1 ;
6362 }
6463
65- function command ( text ) {
66- return new Promise ( resolve => {
67- let responseData = new Buffer ( 0 ) ;
68- let reqId = _getNextPacketId ( ) ;
69- let req = packet . request ( {
70- id : reqId ,
71- type : packet . SERVERDATA_EXECCOMMAND ,
72- body : text
73- } ) ;
74- let ackId = _getNextPacketId ( ) ;
75- let ack = packet . request ( {
76- id : ackId ,
77- type : packet . SERVERDATA_EXECCOMMAND ,
78- body : ''
79- } ) ;
80- _connection . send ( req ) ;
81- _connection . send ( ack ) ;
82- _connection . getData ( dataHandler ) . then ( done ) ;
64+ function command ( text , timeout ) {
65+ return Promise . race ( [
66+ new Promise ( ( resolve , reject ) => {
67+ let unexpectedPackets ;
68+
69+ let responseData = new Buffer ( 0 ) ;
70+ let reqId = _getNextPacketId ( ) ;
71+ let req = packet . request ( {
72+ id : reqId ,
73+ type : packet . SERVERDATA_EXECCOMMAND ,
74+ body : text
75+ } ) ;
76+ let ackId = _getNextPacketId ( ) ;
77+ let ack = packet . request ( {
78+ id : ackId ,
79+ type : packet . SERVERDATA_EXECCOMMAND ,
80+ body : ''
81+ } ) ;
82+ _connection . send ( req ) ;
83+ _connection . send ( ack ) ;
84+ _connection . getData ( dataHandler ) . then ( done ) ;
8385
84- function dataHandler ( data ) {
85- let res = packet . response ( data ) ;
86- if ( res . id === ackId ) {
87- return false ;
88- } else if ( res . id === reqId ) {
89- // More data to come
90- responseData = Buffer . concat ( [ responseData , res . payload ] , responseData . length + res . payload . length ) ;
86+ function dataHandler ( data ) {
87+ let res = packet . response ( data ) ;
88+ if ( res . id === ackId ) {
89+ return false ;
90+ } else if ( res . id === reqId ) {
91+ // More data to come
92+ responseData = Buffer . concat ( [ responseData , res . payload ] , responseData . length + res . payload . length ) ;
93+ return true ;
94+ } else {
95+ return handleUnexpectedData ( res . id ) ;
96+ }
9197 }
92- return true ;
93- }
9498
95- function done ( ) {
96- let text = packet . convertPayload ( responseData ) ;
97- resolve ( text ) ;
98- }
99- } ) ;
99+ function done ( ) {
100+ let text = packet . convertPayload ( responseData ) ;
101+ resolve ( text ) ;
102+ }
103+
104+ function handleUnexpectedData ( id ) {
105+ // Unexpected res.id, possibly from other commands
106+ if ( reqId > id ) {
107+ // Do nothing and keep listening, packets from older
108+ // commands are still coming in
109+ return true ;
110+ }
111+ if ( 'undefined' === typeof unexpectedPackets ) {
112+ unexpectedPackets = new Map ( ) ;
113+ }
114+ if ( ! unexpectedPackets . has ( id ) ) {
115+ if ( unexpectedPackets . size >= 2 ) {
116+ let err = new Error ( 'Command lost' ) ;
117+ err . details = {
118+ reqId : reqId
119+ } ;
120+ if ( responseData . length > 0 ) {
121+ err . details . partialResponse = packet . convertPayload ( responseData ) ;
122+ }
123+ reject ( err ) ;
124+ return false ;
125+ }
126+ unexpectedPackets . set ( id , 1 ) ;
127+ return true ;
128+ }
129+ unexpectedPackets . set ( id , unexpectedPackets . get ( id ) + 1 ) ;
130+ return true ;
131+ }
132+ } ) ,
133+ new Promise ( ( resolve , reject ) => {
134+ if ( 'number' === typeof timeout ) {
135+ return util . promiseTimeout ( timeout ) . then ( ( ) => {
136+ let err = new Error ( 'Command timeout' ) ;
137+ err . details = {
138+ timeout : timeout
139+ } ;
140+ reject ( err ) ;
141+ } ) ;
142+ }
143+ } )
144+ ] ) ;
100145 }
101146} ;
102147
0 commit comments