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