forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			130 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			130 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								package kha.netsync;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import haxe.io.Bytes;
							 | 
						||
| 
								 | 
							
								#if sys_server
							 | 
						||
| 
								 | 
							
								import js.Node;
							 | 
						||
| 
								 | 
							
								import js.node.Buffer;
							 | 
						||
| 
								 | 
							
								import js.node.Dgram;
							 | 
						||
| 
								 | 
							
								#end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Server {
							 | 
						||
| 
								 | 
							
									#if sys_server
							 | 
						||
| 
								 | 
							
									private var app: Dynamic;
							 | 
						||
| 
								 | 
							
									private var udpSocket: Dynamic;
							 | 
						||
| 
								 | 
							
									private var udpClients: Map<String, UdpClient> = new Map();
							 | 
						||
| 
								 | 
							
									private var lastId: Int = -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#if !direct_connection
							 | 
						||
| 
								 | 
							
									private var clients: Map<Int, NodeProcessClient> = new Map();
							 | 
						||
| 
								 | 
							
									private var connectionCallback: Client->Void;
							 | 
						||
| 
								 | 
							
									#end
							 | 
						||
| 
								 | 
							
									#end
							 | 
						||
| 
								 | 
							
									public function new(port: Int) {
							 | 
						||
| 
								 | 
							
										#if sys_server
							 | 
						||
| 
								 | 
							
										#if direct_connection
							 | 
						||
| 
								 | 
							
										var express = Node.require("express");
							 | 
						||
| 
								 | 
							
										app = express();
							 | 
						||
| 
								 | 
							
										Node.require("express-ws")(app);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.use('/', untyped __js__("express.static('../html5')"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.use(function(err, req, res, next) {
							 | 
						||
| 
								 | 
							
											Node.console.error(err.stack);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										app.listen(port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										udpSocket = Dgram.createSocket("udp4");
							 | 
						||
| 
								 | 
							
										udpSocket.bind(port +
							 | 
						||
| 
								 | 
							
											1); // TODO: This is somewhat ugly, but necessary to maintain both websocket and UPD connections at the same time (see also kore/network/Network.hx)
							 | 
						||
| 
								 | 
							
										#else
							 | 
						||
| 
								 | 
							
										Node.process.on("message", function(message) {
							 | 
						||
| 
								 | 
							
											var msg: String = message.message;
							 | 
						||
| 
								 | 
							
											switch (msg) {
							 | 
						||
| 
								 | 
							
												case "connect":
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														var id: Int = message.id;
							 | 
						||
| 
								 | 
							
														var client = new NodeProcessClient(id);
							 | 
						||
| 
								 | 
							
														clients[id] = client;
							 | 
						||
| 
								 | 
							
														connectionCallback(client);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												case "disconnect":
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														var id: Int = message.id;
							 | 
						||
| 
								 | 
							
														var client = clients[id];
							 | 
						||
| 
								 | 
							
														client._close();
							 | 
						||
| 
								 | 
							
														clients.remove(id);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												case "message":
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														var id: Int = message.id;
							 | 
						||
| 
								 | 
							
														var client = clients[id];
							 | 
						||
| 
								 | 
							
														client._message(message.data);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function onConnection(connection: Client->Void): Void {
							 | 
						||
| 
								 | 
							
										#if sys_server
							 | 
						||
| 
								 | 
							
										#if direct_connection
							 | 
						||
| 
								 | 
							
										app.ws('/', function(socket, req) {
							 | 
						||
| 
								 | 
							
											++lastId;
							 | 
						||
| 
								 | 
							
											connection(new WebSocketClient(lastId, socket));
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										udpSocket.on('message', function(message: Buffer, info) {
							 | 
						||
| 
								 | 
							
											if (compare(message, "JOIN")) {
							 | 
						||
| 
								 | 
							
												++lastId;
							 | 
						||
| 
								 | 
							
												var client = new UdpClient(lastId, udpSocket, info.address, info.port);
							 | 
						||
| 
								 | 
							
												udpClients.set(info.address + info.port, client);
							 | 
						||
| 
								 | 
							
												connection(client);
							 | 
						||
| 
								 | 
							
												// var content = Bytes.alloc(4);
							 | 
						||
| 
								 | 
							
												// content.setInt32(0, lastId);
							 | 
						||
| 
								 | 
							
												// client.send(content, true);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else {
							 | 
						||
| 
								 | 
							
												var client = udpClients.get(info.address + info.port);
							 | 
						||
| 
								 | 
							
												if (client != null) {
							 | 
						||
| 
								 | 
							
													if (client.onReceive != null) {
							 | 
						||
| 
								 | 
							
														var data: haxe.io.BytesData = cast message;
							 | 
						||
| 
								 | 
							
														client.onReceive(Bytes.ofData(data));
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												// TODO
							 | 
						||
| 
								 | 
							
												/*var id: Int = message[0];
							 | 
						||
| 
								 | 
							
													var client = clients[id];
							 | 
						||
| 
								 | 
							
													var content = Bytes.alloc(message.length - 1);
							 | 
						||
| 
								 | 
							
													content.blit(0, message, 1, message.length);
							 | 
						||
| 
								 | 
							
													client._message(message.length); */
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											// TODO: Timeout for disconnect
							 | 
						||
| 
								 | 
							
											// console.log('Received %d bytes from %s:%d\n', message.length, info.address, info.port);
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
										#else
							 | 
						||
| 
								 | 
							
										connectionCallback = connection;
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function reset(): Void {
							 | 
						||
| 
								 | 
							
										#if sys_server
							 | 
						||
| 
								 | 
							
										lastId = -1;
							 | 
						||
| 
								 | 
							
										#end
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#if sys_server
							 | 
						||
| 
								 | 
							
									private static function compare(buffer: Buffer, message: String): Bool {
							 | 
						||
| 
								 | 
							
										if (buffer.length != message.length)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										for (i in 0...buffer.length) {
							 | 
						||
| 
								 | 
							
											if (buffer.readUInt8(i) != message.charCodeAt(i))
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									#end
							 | 
						||
| 
								 | 
							
								}
							 |