Files
sdk/runtime/bin/base64.dart
T
sgjesse@google.com f4a87d0e2e Initial web socket server implementation
This implements the web socket protocol as a request handler for
the HTTP server. The HTTP server have been updated with the
ability of getting the socket when a HTTP upgrade request is
processed. This way the web socket implementation is not builtin
to the HTTP server.

The API on the server is:

interface WebSocketConnection {
  void set onMessage(void callback(Object message));
  void set onClosed(void callback(int status, String reason));
  void set onError(void callback(e));

  send(Object message);
  close([int status, String reason]);
}

This API currently does not have any streaming but collects the
entire message before invoking the onMessage callback. The
current browser web socket API
(http://dev.w3.org/html5/websockets/) works the same way. The
underlying web socket protocol can have unbounded messages so
long term this probably have to change. But for now the only
likely client for a web socket server is a browser.

Currently this is missing tests. The implementation has been
tested by running the WebSocketTest.dart script and connecting
using a browser. This testing have been done using Chrome 19 and
Firefox 11.

I will be adding tests in separate change lists.

The SHA-1 and base 64 code (initially written by
ajohnsen@google.com) can be removed when these algorithms is
available in the dart:crypto.

R=ager@google.com, ajohnsen@google.com, vsm@google.com, jacobr@google.com

BUG=dart:2001
TEST=none

Review URL: https://chromiumcodereview.appspot.com//10205012

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@6998 260f80e4-7a28-3924-810f-c04153c831b5
2012-04-26 10:15:30 +00:00

105 lines
3.2 KiB
Dart

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class _Base64 {
static final List<int> _encodingTable = const [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/'];
/**
* Base64 transfer encoding for MIME (RFC 2045)
*/
static String _encode(List<int> data) {
List<String> characters = new List<String>();
int i;
for (i = 0; i + 3 <= data.length; i += 3) {
int value = 0;
value |= data[i + 2];
value |= data[i + 1] << 8;
value |= data[i] << 16;
for (int j = 0; j < 4; j++) {
int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
characters.add(_encodingTable[index]);
}
}
// Remainders.
if (i + 2 == data.length) {
int value = 0;
value |= data[i + 1] << 8;
value |= data[i] << 16;
for (int j = 0; j < 3; j++) {
int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
characters.add(_encodingTable[index]);
}
characters.add("=");
} else if (i + 1 == data.length) {
int value = 0;
value |= data[i] << 16;
for (int j = 0; j < 2; j++) {
int index = (value >> ((3 - j) * 6)) & ((1 << 6) - 1);
characters.add(_encodingTable[index]);
}
characters.add("=");
characters.add("=");
}
StringBuffer output = new StringBuffer();
for (i = 0; i < characters.length; i++) {
if (i > 0 && i % 76 == 0) {
output.add("\r\n");
}
output.add(characters[i]);
}
return output.toString();
}
/**
* Base64 transfer decoding for MIME (RFC 2045).
*/
static List<int> _decode(String data) {
List<int> result = new List<int>();
int padCount = 0;
int charCount = 0;
int value = 0;
for (int i = 0; i < data.length; i++) {
int char = data.charCodeAt(i);
if (65 <= char && char <= 90) { // "A" - "Z".
value = (value << 6) | char - 65;
charCount++;
} else if (97 <= char && char <= 122) { // "a" - "z".
value = (value << 6) | char - 97 + 26;
charCount++;
} else if (48 <= char && char <= 57) { // "0" - "9".
value = (value << 6) | char - 48 + 52;
charCount++;
} else if (char == 43) { // "+".
value = (value << 6) | 62;
charCount++;
} else if (char == 47) { // "/".
value = (value << 6) | 63;
charCount++;
} else if (char == 61) { // "=".
value = (value << 6);
charCount++;
padCount++;
}
if (charCount == 4) {
result.add((value & 0xFF0000) >> 16);
if (padCount < 2) {
result.add((value & 0xFF00) >> 8);
}
if (padCount == 0) {
result.add(value & 0xFF);
}
charCount = 0;
value = 0;
}
}
return result;
}
}