diff --git a/src/browser.js b/src/browser.js index f76c7c7..9c9d400 100644 --- a/src/browser.js +++ b/src/browser.js @@ -1,8 +1,10 @@ +var createClientStream = require('./createClientStream'); var Client = require('./client'); var Server = require('./server'); var serializer = require("./transforms/serializer"); module.exports = { + createClientStream: createClientStream, Client: Client, Server: Server, states: require("./states"), diff --git a/src/createClientStream.js b/src/createClientStream.js index 8867249..c5d047c 100644 --- a/src/createClientStream.js +++ b/src/createClientStream.js @@ -1,41 +1,15 @@ -var ursa=require("./ursa"); -var net = require('net'); -var dns = require('dns'); var Client = require('./client'); var assert = require('assert'); -var crypto = require('crypto'); -var yggdrasil = require('yggdrasil')({}); -var yggserver = require('yggdrasil').server({}); var states = require("./states"); -var debug = require("./debug"); -var uuid = require('uuid'); -module.exports=createClient; +module.exports=createClientStream; -Client.prototype.connect = function(port, host) { - var self = this; - if(port == 25565 && net.isIP(host) === 0) { - dns.resolveSrv("_minecraft._tcp." + host, function(err, addresses) { - if(addresses && addresses.length > 0) { - self.setSocket(net.connect(addresses[0].port, addresses[0].name)); - } else { - self.setSocket(net.connect(port, host)); - } - }); - } else { - self.setSocket(net.connect(port, host)); - } -}; - -function createClient(options) { +function createClientStream(options) { assert.ok(options, "options is required"); - var port = options.port || 25565; - var host = options.host || 'localhost'; - var clientToken = options.clientToken || uuid.v4(); - var accessToken; + var stream = options.stream; + assert.ok(stream, "stream is required"); assert.ok(options.username, "username is required"); - var haveCredentials = options.password != null || (clientToken != null && options.session != null); var keepAlive = options.keepAlive == null ? true : options.keepAlive; var checkTimeoutInterval = options.checkTimeoutInterval || 10 * 1000; @@ -43,65 +17,19 @@ function createClient(options) { var mcData=require("minecraft-data")(optVersion); var version = mcData.version; - var client = new Client(false,version.majorVersion); - client.on('connect', onConnect); + if(keepAlive) client.on('keep_alive', onKeepAlive); - client.once('encryption_begin', onEncryptionKeyRequest); client.once('success', onLogin); client.once("compress", onCompressionRequest); client.on("set_compression", onCompressionRequest); - if(haveCredentials) { - // make a request to get the case-correct username before connecting. - var cb = function(err, session) { - if(err) { - client.emit('error', err); - } else { - client.session = session; - client.username = session.selectedProfile.name; - accessToken = session.accessToken; - client.emit('session'); - client.connect(port, host); - } - }; - if (options.session) { - yggdrasil.validate(options.session.accessToken, function(ok) { - if (ok) - cb(null, options.session); - else - yggdrasil.refresh(options.session.accessToken, options.session.clientToken, function(err, _, data) { - cb(err, data); - }); - }); - } - else yggdrasil.auth({ - user: options.username, - pass: options.password, - token: clientToken - }, cb); - } else { - // assume the server is in offline mode and just go for it. - client.username = options.username; - client.connect(port, host); - } + client.username = options.username; + client.setSocket(stream); var timeout = null; return client; - function onConnect() { - client.write('set_protocol', { - protocolVersion: version.version, - serverHost: host, - serverPort: port, - nextState: 2 - }); - client.state = states.LOGIN; - client.write('login_start', { - username: client.username - }); - } - function onCompressionRequest(packet) { client.compressionThreshold = packet.threshold; } @@ -114,69 +42,9 @@ function createClient(options) { }); } - function onEncryptionKeyRequest(packet) { - crypto.randomBytes(16, gotSharedSecret); - - function gotSharedSecret(err, sharedSecret) { - if(err) { - debug(err); - client.emit('error', err); - client.end(); - return; - } - if(haveCredentials) { - joinServerRequest(onJoinServerResponse); - } else { - if(packet.serverId != '-') { - debug('This server appears to be an online server and you are providing no password, the authentication will probably fail'); - } - sendEncryptionKeyResponse(); - } - - function onJoinServerResponse(err) { - if(err) { - client.emit('error', err); - client.end(); - } else { - sendEncryptionKeyResponse(); - } - } - - function joinServerRequest(cb) { - yggserver.join(accessToken, client.session.selectedProfile.id, - packet.serverId, sharedSecret, packet.publicKey, cb); - } - - function sendEncryptionKeyResponse() { - var pubKey = mcPubKeyToURsa(packet.publicKey); - var encryptedSharedSecretBuffer = pubKey.encrypt(sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); - var encryptedVerifyTokenBuffer = pubKey.encrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); - client.write('encryption_begin', { - sharedSecret: encryptedSharedSecretBuffer, - verifyToken: encryptedVerifyTokenBuffer - }); - client.setEncryption(sharedSecret); - } - } - } - function onLogin(packet) { client.state = states.PLAY; client.uuid = packet.uuid; client.username = packet.username; } } - - - -function mcPubKeyToURsa(mcPubKeyBuffer) { - var pem = "-----BEGIN PUBLIC KEY-----\n"; - var base64PubKey = mcPubKeyBuffer.toString('base64'); - var maxLineLength = 65; - while(base64PubKey.length > 0) { - pem += base64PubKey.substring(0, maxLineLength) + "\n"; - base64PubKey = base64PubKey.substring(maxLineLength); - } - pem += "-----END PUBLIC KEY-----\n"; - return ursa.createPublicKey(pem, 'utf8'); -} diff --git a/src/index.js b/src/index.js index 8d90027..f75ed06 100644 --- a/src/index.js +++ b/src/index.js @@ -2,10 +2,12 @@ var Client = require('./client'); var Server = require('./server'); var serializer = require("./transforms/serializer"); var createClient = require("./createClient"); +var createClientStream = require("./createClientStream"); var createServer = require("./createServer"); module.exports = { createClient: createClient, + createClientStream: createClientStream, createServer: createServer, Client: Client, Server: Server,