/* CBDL_netwine - netwine (bi-directional proxy) network library This library is designed to interface with the netwine server - a proxy server that seemlessly connects the networking methods of browser-based JavaScript to a standard TCP bidirectional stream. To understand more of this technology, see http://kettek.exoss.net/netwine/ Provided is a single Socket "class" that does its best to emulate a normal bi-direction TCP stream. This is accomplished through one dedicated inbound stream from the server (non-closing socket) and multiple dynamically created outbound push requests to the server. In future versions, netwine may also provide a WebSockets interface for more efficient bandwidth usage and less latency. */ CBDL.netwine = CBDL.netwine || { version: 0.1, FLAG: { SYNC: 0x01 // syncronous socket behavior }, UNOPENED: 0x00, PROXY_CONNECTING: 0x01, PROXY_CONNECTED: 0x02, PROXY_FAILED: 0x03, SERVER_CONNECTING: 0x04, SERVER_CONNECTED: 0x05, SERVER_FAILED: 0x06 }; // TODO: Socket should produce Event(s) in the standard browser method - I hope custom events are possible. CBDL.netwine.Socket = function(proxy_address, proxy_port, target_address, target_port, flags) { this.proxy_address = proxy_address; this.proxy_port = proxy_port; this.target_address = target_address; this.target_port = target_port; this.key = null; this.flags = flags; this.in_socket = null; // our in socket - outbound is dynamically created this.inbound = []; // inbound sockets, uses an array due to socket refresh this.outbound = []; // outbound sockets this.is_connected = false; this.status = 0; this.poll_interval = 50; // poll input every 50 ms this.buffer = ""; // our buffer of bytes received this.bytes = 0; // the amount of bytes read thus far // }; CBDL.netwine.Socket.prototype.Connect = function() { // first we open up our INIT request socket and wait for the ack and our new key // if successful, we establish INIT socket as our input and poll it for new data according to poll_interval. Due to the input being cached, it may be wise to open a new input connection (live), switch to it, then close the original seemlessly, so as to free memory // this.status = CBDL.netwine.PROXY_CONNECTING; var init_socket = new XMLHttpRequest(); init_socket.open("INIT", "/"+this.target_address+":"+this.target_port, (this.flags & CBDL.netwine.FLAG.SYNC ? false : true)); init_socket.onreadystatechange = (function(socket) {return function() { switch(this.readyState) { case 1: // open break; case 2: // headers received if (this.status == 200) { // we're good! console.log(this.status+': '+this.statusText); // report connection ok socket.key = this.statusText; socket.in_socket = this; socket.status = CBDL.netwine.PROXY_CONNECTED; socket.bytes = this.responseText.length; } CBDL.fireEvent(socket, "open", {status: this.status}); break; case 3: // loading // FIXME: loading triggers even when responseText is not populated with new bytes! :S // "read in" the new bytes var read = this.responseText.substr(socket.bytes); // increment our bytes read socket.bytes += read.length; // append to the socket's buffer (remove?) socket.buffer += read; // send off the event to all our listeners out there! CBDL.fireEvent(socket, "recv", {data: read, length: read.length}); break; case 4: // done CBDL.fireEvent(socket, "close", {}); break; } }})(this); init_socket.send(""); return 0; }; //this function sends the provided data to the netwine server we are connected to. CBDL.netwine.Socket.prototype.Send = function(bytes, size) { if (this.status != CBDL.netwine.PROXY_CONNECTED) { return 1; } if (!this.key) { return 2; } var socket = new XMLHttpRequest(); socket.open("PUSH", this.key, (this.flags & CBDL.netwine.FLAG.SYNC ? false : true)); socket.onreadystatechange = (function(socket) {return function() { switch(this.readyState) { case 1: // open break; case 2: // headers received if (this.response == 200) { // we're good! } break; case 3: // loading break; case 4: // done break; } }})(this); socket.send(bytes); return 0; // success }; // this function is called by the parent program to see if any new data has come on. CBDL.netwine.Socket.Poll = function() { };