diff --git a/TODO.goals b/TODO.goals
index d63b1d2..e3f90f9 100644
--- a/TODO.goals
+++ b/TODO.goals
@@ -1,2 +1,22 @@
-# US/Pacific 11/19/2013
-Include graingert's pull request on travis.yml
+Check that setting stream=True makes sure that we receive all server events #45
+Use HTTP headers for Websocket connection #44
+Do not connect to blank namespace if overriding default namespace exists #40
+Pass wait timeout to underlying transports #34
+Make heartbeat time independent from elapsed time #38
+ Check that heartbeats are sent even with short wait time #64
+ Revive heartbeat as separate process thanks to sarietta
+Restore namespace as separate process #50
+Check that we have the correct version of websocket #62
+Fall back to next transport #48
+Check that SSL websocket connections work properly #54
+Write a unit test to make sure that the client can disconnect properly #42 #46
+Make sure that on_reconnect works #61
+Check that the library reconnects despite server restart #63 #53
+Upgrade to socket.io 1.2 #41 #52
+ Merge sarietta's pull request
+Implement rooms #65
+Run under Python 3 #51
+ Use urllib.parse.urlparse
+Use continuous integration with TravisCI
+Credit everyone who took the time to submit an issue or pull request
+Add __version__
diff --git a/experiments/app.js b/experiments/app.js
new file mode 100644
index 0000000..4df4754
--- /dev/null
+++ b/experiments/app.js
@@ -0,0 +1,17 @@
+// DEBUG=* node app.js
+var app = require('express')();
+var server = require('http').Server(app);
+var io = require('socket.io')(server);
+
+server.listen(9000);
+
+app.get('/', function (req, res) {
+ res.sendFile(__dirname + '/index.html');
+});
+
+io.on('connection', function (socket) {
+ socket.emit('news', { hello: 'world' });
+ socket.on('my other event', function (data) {
+ console.log(data);
+ });
+});
diff --git a/experiments/client1.py b/experiments/client1.py
new file mode 100644
index 0000000..4880a14
--- /dev/null
+++ b/experiments/client1.py
@@ -0,0 +1,217 @@
+import json
+import requests
+import time
+
+
+# def decode_payload(payload)
+def get_packets(content):
+ packets = []
+ index = 0
+ content_length = len(content)
+ while index < content_length:
+ index, packet_length = read_packet_length(content, index)
+ index, packet = read_packet(content, index, packet_length)
+ packet_type = int(packet[0])
+ packet_payload = packet[1:]
+ packets.append((packet_type, packet_payload))
+ return packets
+
+
+def read_packet_length(content, index):
+ while ord(content[index]) != 0:
+ index += 1
+ index += 1
+ packet_length_string = ''
+ while ord(content[index]) != 255:
+ packet_length_string += str(ord(content[index]))
+ index += 1
+ return index, int(packet_length_string)
+
+
+def read_packet(content, index, packet_length):
+ while ord(content[index]) == 255:
+ index += 1
+ packet = content[index:index + packet_length]
+ return index + packet_length, packet
+
+
+request_counter = 0
+
+
+def get_timestamp():
+ global request_counter
+ timestamp = '%s-%s' % (int(time.time() * 1000), request_counter)
+ request_counter += 1
+ return timestamp
+
+
+base_url = 'http://localhost:9000'
+url = base_url + '/socket.io/'
+
+
+print '*** Connect'
+session = requests.Session()
+print session.cookies.items()
+response = session.get(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+})
+print response.url
+print session.cookies.items()
+packets = get_packets(response.content)
+for packet_type, packet in packets:
+ print packet_type, packet
+packet_type, packet = packets[0]
+packet_json = json.loads(packet)
+print packet_json
+print packet_json['pingInterval']
+print packet_json['pingTimeout']
+print packet_json['sid']
+assert packet_type == 0
+
+
+response = session.get(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+})
+print response.url
+print session.cookies.items()
+packets = get_packets(response.content)
+for packet_type, packet in packets:
+ print 'engineIO_packet_type = %s' % packet_type
+ print 'socketIO_packet_type = %s' % packet[0]
+ print 'packet = %s' % packet[1:]
+# from IPython import embed; embed()
+
+
+# def wrap_payload
+# def pack_packets
+# def pack_packs
+# def wrap_payload
+def encode_payload(packs):
+ parts = []
+ for packet_type, packet in packs:
+ content = str(packet_type) + str(packet)
+ parts.append(make_header(content) + content)
+ return ''.join(parts)
+
+
+def make_header(content):
+ length_string = str(len(content))
+ print length_string
+ header_digits = [0]
+ for index in xrange(len(length_string)):
+ header_digits.append(ord(length_string[index]) - 48)
+ header_digits.append(255)
+ print '---'
+ for x in header_digits:
+ print str(x)
+ print '---'
+ return ''.join(chr(x) for x in header_digits)
+
+
+# print '***'
+# response = session.get(url, params={
+ # 'EIO': 3,
+ # 'transport': 'polling',
+ # 't': get_timestamp(),
+ # 'sid': packet_json['sid'],
+# })
+# print response.url
+# print response.content
+# packets = get_packets(response.content)
+# for packet_type, packet in packets:
+ # print packet_type, packet
+
+
+print '*** Send event'
+packets = [
+ (4, '2["my other event",{"my":"data"}]'),
+]
+payload = encode_payload(packets)
+print payload
+print session.cookies.items()
+response = session.post(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+}, data=payload, headers={
+ 'content-type': 'application/octet-stream',
+})
+print response.url
+print response.content
+
+from time import sleep
+sleep(10)
+
+
+print '*** Send event'
+packets = [
+ (4, '2["my other event",{"my":"data"}]'),
+]
+payload = encode_payload(packets)
+print payload
+print session.cookies.items()
+response = session.post(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+}, data=payload, headers={
+ 'content-type': 'application/octet-stream',
+})
+print response.url
+print response.content
+
+
+print '*** Send ping'
+packets = [
+ (2, ''),
+]
+payload = encode_payload(packets)
+print payload
+response = session.post(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+}, data=payload, headers={
+ 'content-type': 'application/octet-stream',
+})
+print response.url
+print response.content
+
+
+print '*** Send ping'
+packets = [
+ (2, ''),
+]
+payload = encode_payload(packets)
+print payload
+response = session.post(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+}, data=payload, headers={
+ 'content-type': 'application/octet-stream',
+})
+print response.url
+print response.content
+
+
+response = session.get(url, params={
+ 'EIO': 3,
+ 'transport': 'polling',
+ 't': get_timestamp(),
+ 'sid': packet_json['sid'],
+})
+print response.url
+print session.cookies.items()
+packets = get_packets(response.content)
+for packet_type, packet in packets:
+ print packet_type, packet
diff --git a/experiments/client2.py b/experiments/client2.py
new file mode 100644
index 0000000..14c0d7a
--- /dev/null
+++ b/experiments/client2.py
@@ -0,0 +1,11 @@
+from socketIO_client import SocketIO
+
+
+# def on_news(self, data):
+ # print(data)
+ # self.emit('my other event', {'my': 'data'})
+
+
+s = SocketIO('localhost', 9000)
+s.emit('whee')
+# s.on('news', on_news)
diff --git a/experiments/index.html b/experiments/index.html
new file mode 100644
index 0000000..90f066c
--- /dev/null
+++ b/experiments/index.html
@@ -0,0 +1,8 @@
+
+
diff --git a/experiments/interpretation.log b/experiments/interpretation.log
new file mode 100644
index 0000000..ea51ac8
Binary files /dev/null and b/experiments/interpretation.log differ
diff --git a/experiments/proxy.js b/experiments/proxy.js
new file mode 100644
index 0000000..756da12
--- /dev/null
+++ b/experiments/proxy.js
@@ -0,0 +1,30 @@
+var proxy = require('http-proxy').createProxyServer({
+ target: {host: 'localhost', port: 9000}
+});
+var server = require('http').createServer(function(req, res) {
+ console.log('[REQUEST.%s] %s', req.method, req.url);
+ console.log(req['headers']);
+ if (req.method == 'POST') {
+ var body = '';
+ req.on('data', function (data) {
+ body += data;
+ });
+ req.on('end', function () {
+ print_body('[REQUEST.BODY] ', body);
+ });
+ }
+ var _write = res.write;
+ res.write = function(data) {
+ print_body('[RESPONSE.BODY] ', data);
+ _write.call(res, data);
+ }
+ proxy.web(req, res);
+});
+function print_body(header, body) {
+ var text = String(body);
+ console.log(header + text);
+ for (var i = 0; i < text.length; i++) {
+ console.log('body[%s] = %s = %s', i, text[i], text.charCodeAt(i));
+ }
+}
+server.listen(8000);
diff --git a/experiments/proxy.log b/experiments/proxy.log
new file mode 100644
index 0000000..45d0872
Binary files /dev/null and b/experiments/proxy.log differ
diff --git a/experiments/socketIO_client/__init__.py b/experiments/socketIO_client/__init__.py
new file mode 100644
index 0000000..52413f9
--- /dev/null
+++ b/experiments/socketIO_client/__init__.py
@@ -0,0 +1,104 @@
+import json
+import requests
+import time
+
+
+class EngineIO(object):
+
+ _path = 'engine.io'
+ _engine_io_protocol = 3
+ _request_index = 0
+
+ def __init__(self, host, port):
+ url = 'http://%s:%s/%s/' % (host, port, self._path)
+ self.session = requests.Session()
+ response = self.session.get(url, params={
+ 'EIO': self._engine_io_protocol,
+ 'transport': 'polling',
+ 't': self._get_timestamp(),
+ })
+ packs = _decode_content(response.content)
+ packet_type, packet = packs[0]
+ assert packet_type == 0
+ packet_json = json.loads(packet)
+ self._session_id = packet_json['sid']
+ print(packet_json)
+ response = self.session.get(url, params={
+ 'EIO': self._engine_io_protocol,
+ 'transport': 'polling',
+ 't': self._get_timestamp(),
+ 'sid': self._session_id,
+ })
+ packs = _decode_content(response.content)
+ for packet_type, packet in packs:
+ print 'engineIO_packet_type = %s' % packet_type
+ print 'socketIO_packet_type = %s' % packet[0]
+ print 'packet = %s' % packet[1:]
+
+ def _get_timestamp(self):
+ timestamp = '%s-%s' % (int(time.time() * 1000), self._request_index)
+ self._request_index += 1
+ return timestamp
+
+ def _message(self, packet):
+ packet_type = 4
+ response = self.session.post(self.url, params={
+ 'EIO': self._engine_io_protocol,
+ 'transport': 'polling',
+ 't': self._get_timestamp(),
+ 'sid': self._session_id,
+ }, data=_encode_content([(packet_type, packet)]), headers={
+ 'content-type': 'application/octet-stream',
+ })
+
+
+class SocketIO(EngineIO):
+
+ _path = 'socket.io'
+ _socket_io_protocol = 4
+
+ def __init__(self, host, port):
+ super(SocketIO, self).__init__(host, port)
+
+ def on(self, event, callback):
+ pass
+
+ def emit(self, event):
+ packet_type = 2
+ packet = json.dumps([event])
+ self._message(str(packet_type) + packet)
+
+
+def _decode_content(content):
+ packs = []
+ index = 0
+ content_length = len(content)
+ while index < content_length:
+ index, packet_length = _read_packet_length(content, index)
+ index, packet = _read_packet(content, index, packet_length)
+ packet_type = int(packet[0])
+ packet_payload = packet[1:]
+ packs.append((packet_type, packet_payload))
+ return packs
+
+
+def _read_packet_length(content, index):
+ while ord(content[index]) != 0:
+ index += 1
+ index += 1
+ packet_length_string = ''
+ while ord(content[index]) != 255:
+ packet_length_string += str(ord(content[index]))
+ index += 1
+ return index, int(packet_length_string)
+
+
+def _read_packet(content, index, packet_length):
+ while ord(content[index]) == 255:
+ index += 1
+ packet = content[index:index + packet_length]
+ return index + packet_length, packet
+
+
+def _encode_content(packs):
+ pass
diff --git a/setup.cfg b/setup.cfg
index 8a2014f..468f360 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,7 @@
[nosetests]
-detailed-errors=TRUE
-with-coverage=TRUE
-cover-package=socketIO_client
-cover-erase=TRUE
+detailed-errors = TRUE
+with-coverage = TRUE
+cover-package = socketIO_client
+cover-erase = TRUE
+
+[easy_install]