mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			498 lines
		
	
	
		
			No EOL
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
		
			No EOL
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
| * @description APF/CIRA Client for duktape
 | |
| * @author Joko Sastriawan
 | |
| * @copyright Intel Corporation 2019
 | |
| * @license Apache-2.0
 | |
| * @version v0.0.1
 | |
| */
 | |
| 
 | |
| function CreateAPFClient(parent, args) {    
 | |
|     var obj = {};
 | |
|     obj.parent = parent;
 | |
|     obj.args = args;
 | |
|     obj.http = require('http');
 | |
|     //obj.common = require('common');    
 | |
|     obj.net = require('net');    
 | |
|     obj.forwardClient = null;
 | |
|     obj.downlinks = {};
 | |
|     obj.pfwd_idx = 0;
 | |
|     // keep alive timer
 | |
|     obj.timer = null;
 | |
|     
 | |
|     // some function copied from common.js
 | |
|     function ReadInt(v, p) { 
 | |
|         return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); 
 | |
|     }; // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
 | |
|     
 | |
|     function IntToStr(v) { 
 | |
|         return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); 
 | |
|     };
 | |
| 
 | |
|     function hex2rstr(d) {
 | |
|         var r = '', m = ('' + d).match(/../g), t;
 | |
|         while (t = m.shift()) { r += String.fromCharCode('0x' + t); }
 | |
|         return r;
 | |
|     };
 | |
| 
 | |
|     // Convert decimal to hex
 | |
|     function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); };
 | |
| 
 | |
|     // Convert a raw string to a hex string
 | |
|     function rstr2hex(input) {
 | |
|         var r = '', i;
 | |
|         for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); }
 | |
|         return r;
 | |
|     };
 | |
| 
 | |
|     function d2h(d) {
 | |
|         return (d / 256 + 1 / 512).toString(16).substring(2, 4);
 | |
|     }
 | |
| 
 | |
|     function buf2hex(input) {
 | |
|         var r = '', i;        
 | |
|         for (i = 0; i < input.length; i++) { r += d2h(input[i]); }
 | |
|         return r;
 | |
|     };
 | |
| 
 | |
|     
 | |
|     function Debug(str) {
 | |
|         if (obj.parent.debug) {
 | |
|             console.log(str);
 | |
|         }
 | |
|     }
 | |
|     // CIRA state
 | |
|     var CIRASTATE = {
 | |
|         INITIAL: 0,
 | |
|         PROTOCOL_VERSION_SENT: 1,
 | |
|         AUTH_SERVICE_REQUEST_SENT: 2,
 | |
|         AUTH_REQUEST_SENT: 3,
 | |
|         PFWD_SERVICE_REQUEST_SENT: 4,
 | |
|         GLOBAL_REQUEST_SENT: 5,
 | |
|         FAILED: -1
 | |
|     }
 | |
|     obj.cirastate = CIRASTATE.INITIAL;
 | |
| 
 | |
|     // REDIR state
 | |
|     var REDIR_TYPE = {
 | |
|         REDIR_UNKNOWN: 0,
 | |
|         REDIR_SOL: 1,
 | |
|         REDIR_KVM: 2,
 | |
|         REDIR_IDER: 3
 | |
|     }
 | |
| 
 | |
|     // redirection start command
 | |
|     obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
 | |
|     obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
 | |
|     obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
 | |
| 
 | |
| 
 | |
|     // AMT forwarded port list for non-TLS mode
 | |
|     var pfwd_ports = [16992, 623, 16994, 5900];
 | |
|     // protocol definitions
 | |
|     var APFProtocol = {
 | |
|         UNKNOWN: 0,
 | |
|         DISCONNECT: 1,
 | |
|         SERVICE_REQUEST: 5,
 | |
|         SERVICE_ACCEPT: 6,
 | |
|         USERAUTH_REQUEST: 50,
 | |
|         USERAUTH_FAILURE: 51,
 | |
|         USERAUTH_SUCCESS: 52,
 | |
|         GLOBAL_REQUEST: 80,
 | |
|         REQUEST_SUCCESS: 81,
 | |
|         REQUEST_FAILURE: 82,
 | |
|         CHANNEL_OPEN: 90,
 | |
|         CHANNEL_OPEN_CONFIRMATION: 91,
 | |
|         CHANNEL_OPEN_FAILURE: 92,
 | |
|         CHANNEL_WINDOW_ADJUST: 93,
 | |
|         CHANNEL_DATA: 94,
 | |
|         CHANNEL_CLOSE: 97,
 | |
|         PROTOCOLVERSION: 192,
 | |
|         KEEPALIVE_REQUEST: 208,
 | |
|         KEEPALIVE_REPLY: 209,
 | |
|         KEEPALIVE_OPTIONS_REQUEST: 210,
 | |
|         KEEPALIVE_OPTIONS_REPLY: 211
 | |
|     }
 | |
| 
 | |
|     var APFDisconnectCode = {
 | |
|         HOST_NOT_ALLOWED_TO_CONNECT: 1,
 | |
|         PROTOCOL_ERROR: 2,
 | |
|         KEY_EXCHANGE_FAILED: 3,
 | |
|         RESERVED: 4,
 | |
|         MAC_ERROR: 5,
 | |
|         COMPRESSION_ERROR: 6,
 | |
|         SERVICE_NOT_AVAILABLE: 7,
 | |
|         PROTOCOL_VERSION_NOT_SUPPORTED: 8,
 | |
|         HOST_KEY_NOT_VERIFIABLE: 9,
 | |
|         CONNECTION_LOST: 10,
 | |
|         BY_APPLICATION: 11,
 | |
|         TOO_MANY_CONNECTIONS: 12,
 | |
|         AUTH_CANCELLED_BY_USER: 13,
 | |
|         NO_MORE_AUTH_METHODS_AVAILABLE: 14,
 | |
|         INVALID_CREDENTIALS: 15,
 | |
|         CONNECTION_TIMED_OUT: 16,
 | |
|         BY_POLICY: 17,
 | |
|         TEMPORARILY_UNAVAILABLE: 18
 | |
|     }
 | |
| 
 | |
|     var APFChannelOpenFailCodes = {
 | |
|         ADMINISTRATIVELY_PROHIBITED: 1,
 | |
|         CONNECT_FAILED: 2,
 | |
|         UNKNOWN_CHANNEL_TYPE: 3,
 | |
|         RESOURCE_SHORTAGE: 4,
 | |
|     }
 | |
| 
 | |
|     var APFChannelOpenFailureReasonCode = {
 | |
|         AdministrativelyProhibited: 1,
 | |
|         ConnectFailed: 2,
 | |
|         UnknownChannelType: 3,
 | |
|         ResourceShortage: 4,
 | |
|     }
 | |
| 
 | |
|     obj.onSecureConnect = function onSecureConnect(resp, ws, head) {
 | |
|         Debug("APF Secure WebSocket connected.");
 | |
|         //console.log(JSON.stringify(resp));                
 | |
|         obj.forwardClient.tag = { accumulator: [] };
 | |
|         obj.forwardClient.ws = ws;                
 | |
|         obj.forwardClient.ws.on('end', function () {
 | |
|             Debug("APF: Connection is closing.");
 | |
|             if (obj.timer != null) {
 | |
|                 clearInterval(obj.timer);
 | |
|                 obj.timer = null;
 | |
|             }
 | |
|         });
 | |
| 
 | |
|         obj.forwardClient.ws.on('data', function (data) {
 | |
|             obj.forwardClient.tag.accumulator += hex2rstr(buf2hex(data));                        
 | |
|             try {
 | |
|                 var len = 0;
 | |
|                 do {
 | |
|                     len = ProcessData(obj.forwardClient);
 | |
|                     if (len > 0) {                        
 | |
|                         obj.forwardClient.tag.accumulator = obj.forwardClient.tag.accumulator.slice(len);
 | |
|                     }
 | |
|                     if (obj.cirastate == CIRASTATE.FAILED) {
 | |
|                         Debug("APF: in a failed state, destroying socket.")
 | |
|                         obj.forwardClient.ws.end();
 | |
|                     }
 | |
|                 } while (len > 0);
 | |
|             } catch (e) {
 | |
|                 Debug(e);
 | |
|             }
 | |
|         });        
 | |
|         
 | |
|         obj.forwardClient.ws.on('error', function (e) {
 | |
|             Debug("APF: Connection error, ending connecting.");
 | |
|             if (obj.timer != null) {
 | |
|                 clearInterval(obj.timer);
 | |
|                 obj.timer = null;
 | |
|             }
 | |
|         });        
 | |
| 
 | |
|         obj.state = CIRASTATE.INITIAL;
 | |
|         SendProtocolVersion(obj.forwardClient.ws, obj.args.clientuuid);
 | |
|         SendServiceRequest(obj.forwardClient.ws, 'auth@amt.intel.com');
 | |
|     }
 | |
| 
 | |
|     function guidToStr(g) { return g.substring(6, 8) + g.substring(4, 6) + g.substring(2, 4) + g.substring(0, 2) + "-" + g.substring(10, 12) + g.substring(8, 10) + "-" + g.substring(14, 16) + g.substring(12, 14) + "-" + g.substring(16, 20) + "-" + g.substring(20); }
 | |
|     function strToGuid(s) {
 | |
|         s = s.replace(/-/g, '');
 | |
|         var ret = s.substring(6, 8) + s.substring(4, 6) + s.substring(2, 4) + s.substring(0, 2);
 | |
|         ret += s.substring(10, 12) + s.substring(8, 10) + s.substring(14, 16) + s.substring(12, 14) + s.substring(16, 20) + s.substring(20);
 | |
|         return ret;
 | |
|     }
 | |
| 
 | |
|     function binzerostring(len) {
 | |
|         var res='';
 | |
|         for (var l=0; l< len ; l++) {
 | |
|             res+=String.fromCharCode(0 & 0xFF);
 | |
|         }
 | |
|         return res;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     
 | |
|     function SendProtocolVersion(socket, uuid) {        
 | |
|         var buuid = strToGuid(uuid);
 | |
|         var data = String.fromCharCode(APFProtocol.PROTOCOLVERSION) + '' + IntToStr(1) + IntToStr(0) + IntToStr(0) + hex2rstr(buuid) + binzerostring(64);
 | |
|         socket.write(data);        
 | |
|         Debug("APF: Send protocol version 1 0 " + uuid);        
 | |
|         obj.cirastate = CIRASTATE.PROTOCOL_VERSION_SENT;
 | |
|     }
 | |
| 
 | |
|     function SendServiceRequest(socket, service) {
 | |
|         var data = String.fromCharCode(APFProtocol.SERVICE_REQUEST) + IntToStr(service.length) + service;
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send service request " + service);
 | |
|         if (service == 'auth@amt.intel.com') {
 | |
|             obj.cirastate = CIRASTATE.AUTH_SERVICE_REQUEST_SENT;
 | |
|         } else if (service == 'pfwd@amt.intel.com') {
 | |
|             obj.cirastate = CIRASTATE.PFWD_SERVICE_REQUEST_SENT;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function SendUserAuthRequest(socket, user, pass) {
 | |
|         var service = "pfwd@amt.intel.com";
 | |
|         var data = String.fromCharCode(APFProtocol.USERAUTH_REQUEST) + IntToStr(user.length) + user + IntToStr(service.length) + service;
 | |
|         //password auth
 | |
|         data += IntToStr(8) + 'password';
 | |
|         data += binzerostring(1) + IntToStr(pass.length) + pass;
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send username password authentication to MPS");
 | |
|         obj.cirastate = CIRASTATE.AUTH_REQUEST_SENT;
 | |
|     }
 | |
| 
 | |
|     function SendGlobalRequestPfwd(socket, amthostname, amtport) {
 | |
|         var tcpipfwd = 'tcpip-forward';
 | |
|         var data = String.fromCharCode(APFProtocol.GLOBAL_REQUEST) + IntToStr(tcpipfwd.length) + tcpipfwd + binzerostring(1, 1);
 | |
|         data += IntToStr(amthostname.length) + amthostname + IntToStr(amtport);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send tcpip-forward " + amthostname + ":" + amtport);
 | |
|         obj.cirastate = CIRASTATE.GLOBAL_REQUEST_SENT;
 | |
|     }
 | |
| 
 | |
|     function SendKeepAliveRequest(socket) {
 | |
|         var data = String.fromCharCode(APFProtocol.KEEPALIVE_REQUEST) + IntToStr(255);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send keepalive request");
 | |
|     }
 | |
| 
 | |
|     function SendKeepAliveReply(socket, cookie) {
 | |
|         var data = String.fromCharCode(APFProtocol.KEEPALIVE_REPLY) + IntToStr(cookie);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send keepalive reply");
 | |
|     }
 | |
| 
 | |
|     function ProcessData(socket) {
 | |
|         var cmd = socket.tag.accumulator.charCodeAt(0);
 | |
|         var len = socket.tag.accumulator.length;
 | |
|         var data = socket.tag.accumulator;
 | |
|         if (len == 0) { return 0; }
 | |
|         // respond to MPS according to obj.cirastate
 | |
|         switch (cmd) {
 | |
|             case APFProtocol.SERVICE_ACCEPT: {
 | |
|                 var slen = ReadInt(data, 1);
 | |
|                 var service = data.substring(5, 6 + slen);
 | |
|                 Debug("APF: Service request to " + service + " accepted.");
 | |
|                 if (service == 'auth@amt.intel.com') {
 | |
|                     if (obj.cirastate >= CIRASTATE.AUTH_SERVICE_REQUEST_SENT) {
 | |
|                         SendUserAuthRequest(socket.ws, obj.args.mpsuser, obj.args.mpspass);
 | |
|                     }
 | |
|                 } else if (service == 'pfwd@amt.intel.com') {
 | |
|                     if (obj.cirastate >= CIRASTATE.PFWD_SERVICE_REQUEST_SENT) {
 | |
|                         SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
 | |
|                     }
 | |
|                 }
 | |
|                 return 5 + slen;
 | |
|             }
 | |
|             case APFProtocol.REQUEST_SUCCESS: {
 | |
|                 if (len >= 5) {
 | |
|                     var port = ReadInt(data, 1);
 | |
|                     Debug("APF: Request to port forward " + port + " successful.");
 | |
|                     // iterate to pending port forward request
 | |
|                     if (obj.pfwd_idx < pfwd_ports.length) {
 | |
|                         SendGlobalRequestPfwd(socket.ws, obj.args.clientname, pfwd_ports[obj.pfwd_idx++]);
 | |
|                     } else {
 | |
|                         // no more port forward, now setup timer to send keep alive
 | |
|                         Debug("APF: Start keep alive for every " + obj.args.mpskeepalive + " ms.");
 | |
|                         obj.timer = setInterval(function () {
 | |
|                             SendKeepAliveRequest(obj.forwardClient.ws);
 | |
|                         }, obj.args.mpskeepalive);//
 | |
|                     }
 | |
|                     return 5;
 | |
|                 }
 | |
|                 Debug("APF: Request successful.");
 | |
|                 return 1;
 | |
|             }
 | |
|             case APFProtocol.USERAUTH_SUCCESS: {
 | |
|                 Debug("APF: User Authentication successful");
 | |
|                 // Send Pfwd service request
 | |
|                 SendServiceRequest(socket.ws, 'pfwd@amt.intel.com');
 | |
|                 return 1;
 | |
|             }
 | |
|             case APFProtocol.USERAUTH_FAILURE: {
 | |
|                 Debug("APF: User Authentication failed");
 | |
|                 obj.cirastate = CIRASTATE.FAILED;
 | |
|                 return 14;
 | |
|             }
 | |
|             case APFProtocol.KEEPALIVE_REQUEST: {
 | |
|                 Debug("APF: Keep Alive Request with cookie: " + ReadInt(data, 1));
 | |
|                 SendKeepAliveReply(socket.ws, ReadInt(data, 1));
 | |
|                 return 5;
 | |
|             }
 | |
|             case APFProtocol.KEEPALIVE_REPLY: {
 | |
|                 Debug("APF: Keep Alive Reply with cookie: " + ReadInt(data, 1));
 | |
|                 return 5;
 | |
|             }
 | |
|             // Channel management
 | |
|             case APFProtocol.CHANNEL_OPEN: {
 | |
|                 //parse CHANNEL OPEN request
 | |
|                 var p_res = parseChannelOpen(data);
 | |
|                 Debug("APF: CHANNEL_OPEN request: " + JSON.stringify(p_res));
 | |
|                 // Check if target port is in pfwd_ports
 | |
|                 if (pfwd_ports.indexOf(p_res.target_port) >= 0) {
 | |
|                     // connect socket to that port
 | |
|                     obj.downlinks[p_res.sender_chan] = obj.net.createConnection({ host: obj.args.clientaddress, port: p_res.target_port }, function () {
 | |
|                         //obj.downlinks[p_res.sender_chan].setEncoding('binary');//assume everything is binary, not interpreting
 | |
|                         SendChannelOpenConfirm(socket.ws, p_res);
 | |
|                     });
 | |
| 
 | |
|                     obj.downlinks[p_res.sender_chan].on('data', function (ddata) {
 | |
|                         //Relay data to fordwardclient
 | |
|                         SendChannelData(socket.ws, p_res.sender_chan, ddata.length, ddata);
 | |
|                     });
 | |
| 
 | |
|                     obj.downlinks[p_res.sender_chan].on('error', function (e) {
 | |
|                         Debug("Downlink connection error: " + e);
 | |
|                     });
 | |
| 
 | |
|                     obj.downlinks[p_res.sender_chan].on('end', function () {
 | |
|                         if (obj.downlinks[p_res.sender_chan]) {
 | |
|                             try {
 | |
|                                 Debug("Socket ends.");
 | |
|                                 SendChannelClose(socket.ws, p_res.sender_chan);
 | |
|                                 // add some delay before removing... otherwise race condition
 | |
|                                 setTimeout(function () { delete obj.downlinks[p_res.sender_chan];},100);
 | |
|                             } catch (e) {
 | |
|                                 Debug("Downlink connection exception: " + e);
 | |
|                             }
 | |
|                         }
 | |
|                     });
 | |
|                 } else {
 | |
|                     SendChannelOpenFailure(socket.ws, p_res);
 | |
|                 }
 | |
|                 return p_res.len;
 | |
|             }
 | |
|             case APFProtocol.CHANNEL_OPEN_CONFIRMATION: {
 | |
|                 Debug("APF: CHANNEL_OPEN_CONFIRMATION");
 | |
|                 return 17;
 | |
|             }
 | |
|             case APFProtocol.CHANNEL_CLOSE: {
 | |
|                 var rcpt_chan = ReadInt(data, 1);
 | |
|                 Debug("APF: CHANNEL_CLOSE: " + rcpt_chan);
 | |
|                 SendChannelClose(socket.ws, rcpt_chan);
 | |
|                 try {
 | |
|                     obj.downlinks[rcpt_chan].end();
 | |
|                     delete obj.downlinks[rcpt_chan];
 | |
|                 } catch (e) { }
 | |
|                 return 5;
 | |
|             }
 | |
|             case APFProtocol.CHANNEL_DATA: {
 | |
|                 Debug("APF: CHANNEL_DATA: " + JSON.stringify(rstr2hex(data)));
 | |
|                 var rcpt_chan = ReadInt(data, 1);
 | |
|                 var chan_data_len = ReadInt(data, 5);
 | |
|                 var chan_data = data.substring(9, 9 + chan_data_len);
 | |
|                 if (obj.downlinks[rcpt_chan]) {
 | |
|                     try {
 | |
|                         obj.downlinks[rcpt_chan].write(chan_data, 'binary', function () {
 | |
|                             Debug("Write completed.");
 | |
|                             SendChannelWindowAdjust(socket.ws, rcpt_chan, chan_data_len);//I have full window capacity now
 | |
|                         });
 | |
|                     } catch (e) {
 | |
|                         Debug("Cannot forward data to downlink socket.");
 | |
|                     }
 | |
|                 }
 | |
|                 return 9 + chan_data_len;
 | |
|             }
 | |
|             case APFProtocol.CHANNEL_WINDOW_ADJUST: {
 | |
|                 Debug("APF: CHANNEL_WINDOW_ADJUST ");
 | |
|                 return 9;
 | |
|             }
 | |
|             default: {
 | |
|                 Debug("CMD: " + cmd + " is not implemented.");
 | |
|                 obj.cirastate = CIRASTATE.FAILED;
 | |
|                 return 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     function parseChannelOpen(data) {
 | |
|         var result = {
 | |
|             len: 0, //to be filled later
 | |
|             cmd: APFProtocol.CHANNEL_OPEN,
 | |
|             chan_type: "", //to be filled later
 | |
|             sender_chan: 0, //to be filled later
 | |
|             window_size: 0, //to be filled later
 | |
|             target_address: "", //to be filled later
 | |
|             target_port: 0, //to be filled later
 | |
|             origin_address: "", //to be filled later
 | |
|             origin_port: 0, //to be filled later
 | |
|         };
 | |
|         var chan_type_slen = ReadInt(data, 1);
 | |
|         result.chan_type = data.substring(5, 5 + chan_type_slen);
 | |
|         result.sender_chan = ReadInt(data, 5 + chan_type_slen);
 | |
|         result.window_size = ReadInt(data, 9 + chan_type_slen);
 | |
|         var c_len = ReadInt(data, 17 + chan_type_slen);
 | |
|         result.target_address = data.substring(21 + chan_type_slen, 21 + chan_type_slen + c_len);
 | |
|         result.target_port = ReadInt(data, 21 + chan_type_slen + c_len);
 | |
|         var o_len = ReadInt(data, 25 + chan_type_slen + c_len);
 | |
|         result.origin_address = data.substring(29 + chan_type_slen + c_len, 29 + chan_type_slen + c_len + o_len);
 | |
|         result.origin_port = ReadInt(data, 29 + chan_type_slen + c_len + o_len);
 | |
|         result.len = 33 + chan_type_slen + c_len + o_len;
 | |
|         return result;
 | |
|     }
 | |
|     function SendChannelOpenFailure(socket, chan_data) {
 | |
|         var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_FAILURE) + IntToStr(chan_data.sender_chan)
 | |
|             + IntToStr(2) + IntToStr(0) + IntToStr(0);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send ChannelOpenFailure");
 | |
|     }
 | |
|     function SendChannelOpenConfirm(socket, chan_data) {
 | |
|         var data = String.fromCharCode(APFProtocol.CHANNEL_OPEN_CONFIRMATION) + IntToStr(chan_data.sender_chan)
 | |
|             + IntToStr(chan_data.sender_chan) + IntToStr(chan_data.window_size) + IntToStr(0xFFFFFFFF);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send ChannelOpenConfirmation");
 | |
|     }
 | |
| 
 | |
|     function SendChannelWindowAdjust(socket, chan, size) {
 | |
|         var data = String.fromCharCode(APFProtocol.CHANNEL_WINDOW_ADJUST) + IntToStr(chan) + IntToStr(size);
 | |
|         socket.write(data);
 | |
|         Debug("APF: Send ChannelWindowAdjust: " + rstr2hex(data));
 | |
|     }
 | |
| 
 | |
|     function SendChannelData(socket, chan, len, data) {
 | |
|         var buf = String.fromCharCode(APFProtocol.CHANNEL_DATA) + IntToStr(chan) + IntToStr(len) + data;
 | |
|         socket.write(buf);
 | |
|         Debug("APF: Send ChannelData: " + rstr2hex(buf));
 | |
|     }
 | |
| 
 | |
|     function SendChannelClose(socket, chan) {
 | |
|         var buf = String.fromCharCode(APFProtocol.CHANNEL_CLOSE) + IntToStr(chan);
 | |
|         socket.write(buf);
 | |
|         Debug("APF: Send ChannelClose ");
 | |
|     }
 | |
| 
 | |
|     obj.connect = function () {
 | |
|         if (obj.forwardClient != null) {
 | |
|             try {
 | |
|                 obj.forwardClient.ws.end();
 | |
|             } catch (e) {
 | |
|                 Debug(e);
 | |
|             }
 | |
|             //obj.forwardClient = null;
 | |
|         }
 | |
|         obj.cirastate = CIRASTATE.INITIAL;
 | |
|         obj.pfwd_idx = 0;
 | |
|         
 | |
|         //obj.forwardClient = new obj.ws(obj.args.mpsurl, obj.tlsoptions);
 | |
|         //obj.forwardClient.on("open", obj.onSecureConnect);
 | |
| 
 | |
| 
 | |
|         var wsoptions = obj.http.parseUri(obj.args.mpsurl);        
 | |
|         wsoptions.rejectUnauthorized = 0;
 | |
|         obj.forwardClient = obj.http.request(wsoptions);        
 | |
|         obj.forwardClient.upgrade = obj.onSecureConnect;        
 | |
|         obj.forwardClient.end(); // end request, trigger completion of HTTP request
 | |
|     }
 | |
| 
 | |
|     obj.disconnect = function () {
 | |
|         try {
 | |
|             obj.forwardClient.ws.end();
 | |
|         } catch (e) {
 | |
|             Debug(e);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return obj;
 | |
| }
 | |
| 
 | |
| module.exports = CreateAPFClient; 
 |