var where_v = ""; function mcproto(s) { var bufs=[]; var eating=null; var eatpr=0; var cond=null; var rr=null; var lasted = false; async function read_b(count,b) { var arred=count!=null; count=count??1; var out = []; if(b==null) { while (count>0) { if(eating!=null&&eatpr>=eating.length) { eating = null; eatpr = 0; } if(eating==null) { if(bufs.length == 0) { if (lasted) { throw "ran out of data"; } await (new Promise((a,r)=>(cond=a,rr=r,[][[]]))); } eating=bufs.shift(); if(eating==null ) throw "Wtf!" } out.push(eating[eatpr++]);count--; } } else { while (count>0) { b.i=b.i??0; var cc = b.buf[b.i++];count--; if(cc==null) { throw new Error("ran out of data (buf)"); } out.push(cc); } } return arred?out:out[0]; } s.on("upstream",function(b,opt){ if (b.length > 0) { bufs.push(b); if(cond!=null) cond(); } lasted = lasted||opt.last; if (b.length==0 && lasted) { rr("unexpected end"); } }) var unreg =_=> s.off("upstream"); async function readVarInt(b) { var Int = 0; var power = 0; var rr; while(1) { rr=await read_b(null,b); Int+=(rr&(0x80-1))<>7)) { break; } power+=7; if(power>32) throw "varInt too big!"; } return Int|0; } async function readPacket(b) { var len = await readVarInt(b); if (len > 2097151) { throw "packet too big!"; } var pack = await read_b(len,b); pack = {buf:pack}; try { pack.type = await readVarInt(pack); } catch(e) { s.error("bad packet! "+JSON.stringify(pack)); throw e; } return pack; } async function readString(b) { var len = await readVarInt(b); var text = await read_b(len,b); text = (new TextDecoder()) .decode(new Uint8Array(text)); return text; } async function readShort(b) { var p = await read_b(2,b); return (p[0]<<8)+p[1]; } return { read_b, unreg, readVarInt, readPacket, readString, readShort }; } function makeVarInt(Int) { var rr; var out=[]; while (1) { rr = Int&(0x80-1); Int>>=7; if(Int>0) { out.push(rr|0x80); } else { out.push(rr); break; } } return out; } function makePacket(type,pack) { var pack1 = []; var ll=makeVarInt(type); memcpy(makeVarInt(ll.length+pack.length),pack1) memcpy(ll,pack1); memcpy(pack,pack1); return pack1; } function makeString(desc) { var pack = []; var str=[]; memcpy((new TextEncoder()) .encode(desc),str); memcpy(makeVarInt(str.length),pack); memcpy(str,pack); return pack; } function makeNBTString(desc) { var pack = []; var str=[]; memcpy((new TextEncoder()) .encode(desc),str); memcpy([8,(str.length>>8)&0xff,str.length&0xff],pack); return pack; } function wellcome(desc,s) { return {"version":{"name":"nginx/"+s.variables.nginx_version,"protocol": 65535},"description":{"text":desc},"players":{"max":1000000,"online":-1}, "favicon": "data:image/png;base64,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",}; } function memcpy(from,to) { for(var i=0; i{ s.error(e.stack); s.deny(); return Promise.reject(e); }); } } var err404 = makeHandler("404 Not Found") var err503 = makeHandler("503 Bad Gateway") function ponger(s) { var mm=mcproto(s); var read_b = mm.read_b; var unreg = mm.unreg; var readVarInt = mm.readVarInt; var readPacket = mm.readPacket; var readString = mm.readString; var readShort = mm.readShort; (async function() { await readPacket(); // discard hello; var pack = await readPacket(); if(pack.type != 1) { throw "ponger wants a ping request!"; } var data = await read_b(8,pack); pack = makePacket(1,data); hout = Buffer.from(new Uint8Array(pack)).toString('base64'); s.done(); })().catch(e=>{ s.error(e.stack); unreg(); s.deny(); return Promise.reject(e); }); } function disconner(s) { (async function() { var pack = makePacket(0,makeString(JSON.stringify({text:"404 Not Found\n---------------\nnginx/"+s.variables.nginx_version}))); hout = Buffer.from(new Uint8Array(pack)).toString('base64'); s.done(); })().catch(e=>{ s.error(e.stack); unreg(); s.deny(); return Promise.reject(e); }); } function unb64(s) { s.on("downstream",function(b){ s.send(Buffer.from(b.toString(),'base64')); }) } function preread(s) { var mm=mcproto(s); var read_b = mm.read_b; var unreg = mm.unreg; var readVarInt = mm.readVarInt; var readPacket = mm.readPacket; var readString = mm.readString; var readShort = mm.readShort; (async function() { //await readVarInt(); // we do not care about packet length somehow // ^ we do actually var pack = await readPacket(); if(pack.type != 0) { throw "not minecraft..."; } await readVarInt(pack); // we do not care what version this is where_v = (await readString(pack)) .match(/([^\0]*)\0*/)[1]; // Forge Modloader support var port = (await readShort(pack)); var nstate = (await readVarInt(pack)); if(nstate != 1) { stt="disconnect"; } else { pack = await readPacket(); if(pack.type == 1) { stt="pinger"; } else if (pack.type == 0) { stt = "status"; } } unreg(); s.error("YES minecraft! "+where_v+" from "+s.variables.remote_addr); s.done(); })().catch(e=>{ s.error(e.stack); unreg(); s.deny(); return Promise.reject(e); }); } function where() { return where_v; } function status_type() { return stt; } export default { preread, where, err404, err503, disconner, ponger, handler_out, status_type, unb64 };