Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
benmmurphy committed Oct 16, 2011
0 parents commit a61868f
Show file tree
Hide file tree
Showing 19 changed files with 2,349 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.eunit
*.beam
deps
ebin
log
TEST-*xml

10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
compile:
./rebar compile

eunit:
./rebar skip_deps=true eunit

run:
erl -pa ebin -pa deps/lager/ebin -s espdy_test_server

.PHONY: eunit compile
73 changes: 73 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#Status

This project is still very alpha. Enough of the protocol has been implemented to view pages in google chrome. Check out espdy_test_server.erl

#Running
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --use-spdy=ssl
make compile
./test_server
http://localhost:8443

# {active, false} socket like API
This makes the code much more complicated :( and I'm wondering if it is worth having. If you use a callback module or {active, true} style message sending
then the code becomes much simpler.

However, {active, false} gives us flow control (with spdy/3) and really simple integration with erlang web frameworks that use tcp like sockets and do recv to process POSTs.

We also support multiple concurrent send() or recv() operations on the same stream which makes the code a little bit more complicated. I'm not sure how useful this behaviour is because you have to make sure you are send()'ing and recv()'ing atomic blocks for it to be useful otherwise you might interleave messages corrupting the stream. gen_tcp supports this behaviour. i'm not sure if the ssl module supports this behaviour.

#Issues

## NPN Support in Erlang

There is no NPN support for SSL in Erlang. I'm currently working on a patch to fix this. Whether Erlang
would accept a patch for a draft extensions is another question.

## Write Queueing

We queue up writes in a write process. If the reader at the other end is not reading data fast enough then our write process will start consuming lots of memory. We need to kill off connections that are misbehaving. send() calls block until the write has returned so there is _some_ flow control on the send() side. once the os buffer has filled up send() will start blocking. however, we will send data in response to PING and protocol errors and it is possible a misbehaving client could trick us into allocating lots of memory for the write queue.

## Read Buffering

There is no flow control in spdy draft 2. When we receive data we add it to a buffer. We keep adding data to the buffer. If we receive data faster than we are recv()'ing it then we can start chewing up memory. The plan is to add a max_recv_buffer setting and to stop reading from the socket if this limit is met.

## Goaway Implementation

We don't correctly send {error, closed_not_processed} in a lot of places. This hasn't been implemented in send/recv. Also, we kill the gen_server too early and a client may receive {error, closed} because the gen_server is not around instead of {error, closed_not_processed}.

## No settings

Have not implemented sending or receiving of the settings frame.

## Partial implementation of headers

No support for receiving header frames. I'm not sure how this would look in the api :(

## StreamId limit

No support for stopping connections when the StreamId limit has been reached

## Not checking version

We are currently not checking the version field on control or data frames :(

## No backlimit for accepts

We continue to add connections to the accept buffer without bound.

## Communicating errors back to the client

If a client isn't send'ing or recv'ing on a stream then they won't receive error notifications about previous failed sends. I think this is how unix
tcp works so i don't think it is that terrible :). However, the spdy http protocol is the client writes to the server and then half-closes, then the
server writes to the client and then half-closes. There is no server waiting for an ack from the client. If the servers response to the client is not
received it will not be aware of this. I'm not sure how big of a problem this is. Generally http servers don't care if they fail to deliver a response
to the client.

## No chunking of sends

If you do a large send() then it will block all the other channels using the spdy socket. We should probably chunk sends() to a reasonable value.

# Code duplication

There is some code duplication between espdy_server and espdy_frame for control frame decoding

53 changes: 53 additions & 0 deletions include/espdy_frame.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-define(BYTE(X), (X):8/unsigned-big-integer).
-define(UINT16(X), (X):16/unsigned-big-integer).
-define(UINT24(X), (X):24/unsigned-big-integer).
-define(UINT32(X), (X):32/unsigned-big-integer).
-define(UINT64(X), (X):64/unsigned-big-integer).

-define(NOOP, 5).
-define(PING, 6).
-define(SYN_STREAM, 1).
-define(SYN_REPLY, 2).
-define(RST_STREAM, 3).
-define(HEADERS, 8).
-define(GOAWAY, 7).

-define(SPDY_VERSION, 2).
-define(CONTROL_FRAME, 1:1/unsigned-big-integer).
-define(DATA_FRAME, 0:1/unsigned-big-integer).
-define(TYPE(X), (X):16/unsigned-big-integer).
-define(VERSION(X), (X):15/unsigned-big-integer).
-define(LENGTH(X), ?UINT24(X)).
-define(FLAGS(X), ?BYTE(X)).
-define(RESERVED_BIT, _:1).
-define(MAKE_RESERVED_BIT, 0:1).
-define(STREAM_ID(X), (X):31/unsigned-big-integer).
-define(PRIORITY(X), (X):2/unsigned-big-integer).
-define(UNUSED(X), _:(X)).
-define(MAKE_UNUSED(X), 0:(X)).

-define(UNUSED_SYN_REPLY, 16).
-define(UNUSED_SYN_STREAM, 14).
-define(UNUSED_HEADERS, 16).

-define(FLAG_FIN, 1).
-define(FLAG_UNIDIRECTIONAL, 2).

%% RST_STREAM STATUSES
-define(PROTOCOL_ERROR, 1).
-define(INVALID_STREAM, 2).
-define(REFUSED_STREAM, 3).
-define(UNSUPPORTED_VERSION, 4).
-define(CANCEL, 5).
-define(FLOW_CONTROL_ERROR, 6).
-define(STREAM_IN_USE, 7).
-define(STREAM_ALREADY_CLOSED, 8).

-record(control_frame, {version, type, flags, data}).
-record(rst_stream, {stream_id, status}).
-record(headers, {headers, stream_id}).
-record(data_frame, {stream_id, flags, data}).
-record(syn_reply, {stream_id, flags, headers}).
-record(syn_stream, {stream_id, flags, headers, associated_stream_id}).
-record(goaway, {last_good_stream_id}).
-record(noop, {}).
1 change: 1 addition & 0 deletions include/espdy_server.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-record(espdy_socket, {pid, stream_id}).
Binary file added rebar
Binary file not shown.
6 changes: 6 additions & 0 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{deps, [
{lager, "0.9.*", {git, "git://github.com/basho/lager", {branch, "master"}}}
]}.
{cover_enabled, true}.
{eunit_opts, [verbose,
{report, {eunit_surefire, [{dir, "."}]}}]}.
14 changes: 14 additions & 0 deletions server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICKTCCAZICCQC/DgnBN+wo7jANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJB
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTExMDA2MjM1NjEzWhcN
MTIxMDA1MjM1NjEzWjBZMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0
ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKZOG7/aDqeEVr+R
73/SZs9Xzw+XYTPkPNykPe5/7pL4LDuNc0seFnthMI8/qBAZ14pBnR7pIx1s6eqy
hSH+yxghc9T6yot+cM71EsVydPaN0IbjJONwR4RMStiydSLsVECAaDXt4bSwDuCf
qoGsx5q4bBwv7SR8gy0Wqx3+PH6/AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAYtrw
KlJT23M50BOfC6KEvl9so0OzkyaCoLVPcM1UcNi5AfjMuXcxf2foFn0SmorGnJQ6
FkXXwu/nF6R/ngDDgrLBv7vVLQY/JfU1+eUjblkfdpeykwpK+bd1N5UzdYM6LX5Z
2IMU4eYaBkaISkeA7IAS09lRyDSs9MsxgvfGCjk=
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCmThu/2g6nhFa/ke9/0mbPV88Pl2Ez5DzcpD3uf+6S+Cw7jXNL
HhZ7YTCPP6gQGdeKQZ0e6SMdbOnqsoUh/ssYIXPU+sqLfnDO9RLFcnT2jdCG4yTj
cEeETErYsnUi7FRAgGg17eG0sA7gn6qBrMeauGwcL+0kfIMtFqsd/jx+vwIDAQAB
AoGAa+ceBhrbi0FIb7+mX48KedmFVZ5oyRx7iMVgEZEcIGu5d2JNvh1lhOQId8lb
qCa8PM5ZvaaSzBLQqyDtVKNW7eNt8z1cCUUCXy74dfUAqT0gk13cMs+InCqNWheU
DaFttpgerPUHW4puaNoKJr+UKDgkEQqgyla/ixBHFNfW6dECQQDRa+cDf00g9aB0
Kq6Yurf/KIf3LsJJHYizYKucirQdWhIo87mD9tez/UK9iTCjC2SM+sIklGYiW2ns
ZfxVJtYTAkEAy0s71pJBsbV7b7PQf8p2P1ICX/QN7/wALYmd6iJqWC+599GzF8j6
Fq3pNUED6wy61W715YcFziIdyRNcKUv6JQJABQUkJYZQsACTVxWK1+hp7rjnAXri
d2Q42avwkTEV/johg0/MW6h4JT1l8ystukrUnziHnN7dz+cHE/6h3NywdwJAdGE3
elj0PtXUOlhITkALfahnL6M5r18mgus7eeQF2UJJRjPIQR+O/BjHXvM/WPpKoxEI
uEOZ8S3au1fX9NRH+QJBAJKPv47Nr3Old03Imdwu7JPjwwXtm6gJb6Id4MRDiP6k
bUPOw1GtM79o2xjc33+5e1ekaMAP5+d6+04vAlZ4Ijg=
-----END RSA PRIVATE KEY-----
8 changes: 8 additions & 0 deletions src/espdy.app.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{application, espdy,
[{description, "SPDY Server"},
{vsn, "0.0.1"},
{modules, []},
{registered, []},
{applications, [kernel, stdlib]},
{build_dependencies, []},
{env, []}]}.
Loading

0 comments on commit a61868f

Please sign in to comment.