]> git.wh0rd.org Git - chrome-ext/music-player-client.git/blob - js/tcp-client.js
images: update small tile to try & pass CWS guidelines
[chrome-ext/music-player-client.git] / js / tcp-client.js
1 /*
2 Copyright 2012 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 Author: Boris Smus (smus@chromium.org)
17 */
18
19 (function(exports) {
20
21   // Define some local variables here.
22   var socket = chrome.socket;
23
24   /**
25    * Creates an instance of the client
26    *
27    * @param {String} host The remote host to connect to
28    * @param {Number} port The port to connect to at the remote host
29    */
30   function TcpClient(host, port) {
31     this.host = host;
32     this.port = port;
33
34     // Callback functions.
35     this.callbacks = {
36       connect: null,    // Called when socket is connected.
37       disconnect: null, // Called when socket is disconnected.
38       recv: null,       // Called when client receives data from server.
39       sent: null        // Called when client sends data to server.
40     };
41
42     // Socket.
43     this.socketId = null;
44     this.isConnected = false;
45     this.pollerId = null;
46
47     log('initialized tcp client');
48   }
49
50   /**
51    * Connects to the TCP socket, and creates an open socket.
52    *
53    * @see http://developer.chrome.com/apps/socket.html#method-create
54    * @param {Function} callback The function to call on connection
55    */
56   TcpClient.prototype.connect = function(callback) {
57     socket.create('tcp', {}, this._onCreate.bind(this));
58
59     // Register connect callback.
60     this.callbacks.connect = callback;
61   };
62
63   /**
64    * Sends a message down the wire to the remote side
65    *
66    * @see http://developer.chrome.com/apps/socket.html#method-write
67    * @param {String} msg The message to send
68    * @param {Function} callback The function to call when the message has sent
69    */
70   TcpClient.prototype.sendMessage = function(msg, callback) {
71     this._stringToArrayBuffer(msg + '\n', function(arrayBuffer) {
72       socket.write(this.socketId, arrayBuffer, this._onWriteComplete.bind(this));
73     }.bind(this));
74
75     // Register sent callback.
76     this.callbacks.sent = callback;
77   };
78
79   /**
80    * Sets the callback for when a message is received
81    *
82    * @param {Function} callback The function to call when a message has arrived
83    */
84   TcpClient.prototype.addResponseListener = function(callback) {
85     // Register received callback.
86     this.callbacks.recv = callback;
87   };
88
89   /**
90    * Disconnects from the remote side
91    *
92    * @see http://developer.chrome.com/apps/socket.html#method-disconnect
93    */
94   TcpClient.prototype.disconnect = function() {
95     socket.disconnect(this.socketId);
96     if (this.isConnected) {
97       clearInterval(this.pollerId);
98       this.pollerId = null;
99       this.isConnected = false;
100     }
101   };
102
103   /**
104    * The callback function used for when we attempt to have Chrome
105    * create a socket. If the socket is successfully created
106    * we go ahead and connect to the remote side.
107    *
108    * @private
109    * @see http://developer.chrome.com/apps/socket.html#method-connect
110    * @param {Object} createInfo The socket details
111    */
112   TcpClient.prototype._onCreate = function(createInfo) {
113     if (this.socketId !== null) {
114       socket.destroy(this.socketId);
115     }
116     this.socketId = createInfo.socketId;
117     if (this.socketId > 0) {
118       socket.connect(this.socketId, this.host, this.port, this._onConnectComplete.bind(this));
119     } else {
120       error('Unable to create socket');
121     }
122   };
123
124   /**
125    * The callback function used for when we attempt to have Chrome
126    * connect to the remote side. If a successful connection is
127    * made then polling starts to check for data to read
128    *
129    * @private
130    * @param {Number} resultCode Indicates whether the connection was successful
131    */
132   TcpClient.prototype._onConnectComplete = function(resultCode) {
133     log('resultCode: ' + resultCode);
134
135     // XXX: Can this ever be positive ?
136     this.isConnected = (resultCode >= 0);
137
138     // Start polling for reads.
139     clearInterval(this.pollerId);
140     if (this.isConnected) {
141       this.pollerId = setInterval(this.poll.bind(this), 500);
142     }
143
144     if (this.callbacks.connect) {
145       log('connect complete');
146       this.callbacks.connect(resultCode);
147     }
148     log('onConnectComplete');
149   };
150
151   /**
152    * Checks for new data to read from the socket
153    *
154    * @see http://developer.chrome.com/apps/socket.html#method-read
155    */
156   TcpClient.prototype.poll = function() {
157     socket.read(this.socketId, null, this._onDataRead.bind(this));
158   };
159
160   /**
161    * Callback function for when data has been read from the socket.
162    * Converts the array buffer that is read in to a string
163    * and sends it on for further processing by passing it to
164    * the previously assigned callback function.
165    *
166    * @private
167    * @see TcpClient.prototype.addResponseListener
168    * @param {Object} readInfo The incoming message
169    */
170   TcpClient.prototype._onDataRead = function(readInfo) {
171     // Call received callback if there's data in the response.
172     if (readInfo.resultCode > 0 && this.callbacks.recv) {
173       log('onDataRead');
174       // Convert ArrayBuffer to string.
175       this._arrayBufferToString(readInfo.data, function(str) {
176         this.callbacks.recv(str);
177       }.bind(this));
178     }
179   };
180
181   /**
182    * Callback for when data has been successfully
183    * written to the socket.
184    *
185    * @private
186    * @param {Object} writeInfo The outgoing message
187    */
188   TcpClient.prototype._onWriteComplete = function(writeInfo) {
189     log('onWriteComplete');
190     // Call sent callback.
191     if (this.callbacks.sent) {
192       this.callbacks.sent(writeInfo);
193     }
194   };
195
196   /**
197    * Converts an array buffer to a string
198    *
199    * @private
200    * @param {ArrayBuffer} buf The buffer to convert
201    * @param {Function} callback The function to call when conversion is complete
202    */
203   TcpClient.prototype._arrayBufferToString = function(buf, callback) {
204     var bb = new Blob([new Uint8Array(buf)]);
205     var f = new FileReader();
206     f.onload = function(e) {
207       callback(e.target.result);
208     };
209     f.readAsText(bb);
210   };
211
212   /**
213    * Converts a string to an array buffer
214    *
215    * @private
216    * @param {String} str The string to convert
217    * @param {Function} callback The function to call when conversion is complete
218    */
219   TcpClient.prototype._stringToArrayBuffer = function(str, callback) {
220     var bb = new Blob([str]);
221     var f = new FileReader();
222     f.onload = function(e) {
223         callback(e.target.result);
224     };
225     f.readAsArrayBuffer(bb);
226   };
227
228   /**
229    * Wrapper function for logging
230    */
231   function log(msg) {
232     //console.log('tcp-client:', msg);
233   }
234
235   /**
236    * Wrapper function for error logging
237    */
238   function error(msg) {
239     console.error('tcp-client:', msg);
240   }
241
242   exports.TcpClient = TcpClient;
243
244 })(window);