Sunday, May 22, 2011

SPDY Responses in Detail

‹prev | My Chain | next›

Yesterday, I examined the details of SPDY requests (to a test node-spdy server). In all, there were 5 SYN_STREAM requests that went through for this page:



(web page, same web page again, CSS stylesheet, image, favicon)

Today, I examine the details of the response from the node-spdy server.

The first response packet is the server hello / certificate:
««« response
57 6.993692 127.0.0.1 127.0.0.1 TLSv1 Server Hello, Certificate, Server Hello Done
0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E.
0010 02 b4 e5 02 40 00 40 06 55 3f 7f 00 00 01 7f 00 ....@.@.U?......
0020 00 01 1f 91 b1 a2 72 b9 33 3f 72 7d 25 c3 80 18 ......r.3?r}%...
0030 01 09 00 a9 00 00 01 01 08 0a 01 52 d6 3e 01 52 ...........R.>.R
0040 d6 3e 16 03 01 00 40 02 00 00 3c 03 01 4d d7 2c .>....@...<..M.,
0050 98 c6 35 6a c5 85 29 8c c1 cf 3d c1 80 e1 8e 81 ..5j..)...=.....
0060 a5 59 4e e4 af d0 76 e0 a2 19 02 86 67 00 00 35 .YN...v.....g..5
0070 01 00 14 ff 01 00 01 00 00 23 00 00 33 74 00 07 .........#..3t..
0080 06 73 70 64 79 2f 32 16 03 01 02 2d 0b 00 02 29 .spdy/2....-...)
0090 00 02 26 00 02 23 30 82 02 1f 30 82 01 88 02 09 ..&..#0...0.....
00a0 00 8f 3d 25 00 6b c4 19 a2 30 0d 06 09 2a 86 48 ..=%.k...0...*.H
00b0 86 f7 0d 01 01 05 05 00 30 54 31 0b 30 09 06 03 ........0T1.0...
00c0 55 04 06 13 02 52 55 31 13 30 11 06 03 55 04 08 U....RU1.0...U..
00d0 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 0d 30 0b ..Some-State1.0.
00e0 06 03 55 04 07 13 04 4f 6d 73 6b 31 21 30 1f 06 ..U....Omsk1!0..
00f0 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 .U....Internet W
0100 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 1e idgits Pty Ltd0.
...
Most of that is just plain-old SSL. The only new / SPDY thing in there is the list of protocols supported. In this example server, only SPDY is supported (when accessing Google's servers, SPDY, HTTP/1.1 and HTTP/1.0 are supported).

The next response is:
««« response
60 7.000103 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 14 00 00 0c 3d 6a eb 5a 0d 58 9e c0 03 5d a9 41 ....=j.Z.X...].A
==
0000 80 02 00 04 00 00 00 0c 00 00 00 01 04 00 00 00 ................
0010 00 00 00 64 ...d
I am not quite sure what that first frame was (just SSL setup), but the second frame is a SETTINGS frame. Arranging the packets next to the packet diagram from SPDY protocol (draft 2):
              +----------------------------------+
80 02 00 04 |1| version | 4 |
+----------------------------------+
00 00 00 0c | Flags (8) | Length (24 bits) |
+----------------------------------+
00 00 00 01 | Number of entries |
+----------------------------------+
04 00 00 00 | ID/Value Pairs |
00 00 00 64 | ... |
The first row matches up exactly with the spec. The second indicates that there are no flags and 12 additional octets after this row (0x0c == 12). The number of entries indicates that there is only a single setting being set. Skipping ahead, the numeric value being set is 100 (0x64), but what is the ID in the ID/Value pair? The ID is supposed to be one octet of flags and 3 octets describing the ID. The ID in there is empty (00 00 00). That seems like a bug, but I will investigate another day.

The next response packet(s) packet looks like:
««« response
62 7.038667 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP trafficContinuation or non-HTTP traffic
0000 80 02 00 02 00 00 00 a3 00 00 00 01 00 00 78 bb ........ ......x.
0010 df a2 51 b2 62 e0 64 e0 42 c4 10 03 57 76 6a 6a ..Q.b.d. B...Wvjj
0020 81 6e 62 4e 66 59 2a 03 1f 6a 90 33 30 9b 59 5a .nbNfY*. .j.30.YZ
0030 30 f0 a2 c4 2d 83 20 c4 1d 3a 0a 50 97 d8 1a 30 0...-. . .:.P...0
0040 f0 a2 04 2e 83 2c 30 c0 74 14 0c 4d 14 80 c1 a3 .....,0. t..M....
0050 00 cc 0b 86 0a 06 46 56 c6 66 56 40 11 77 df 10 ......FV .fV@.w..
0060 06 16 50 ac 30 08 2b 01 cd d6 35 04 e5 04 60 aa ..P.0.+. ..5...`.
0070 07 65 04 03 25 06 1e e4 c8 63 90 80 87 9f b5 02 .e..%... .c......
0080 cc bf a1 21 6e ba 40 27 a1 a4 77 06 d6 a4 ca 12 ...!n.@' ..w.....
0090 20 c5 06 f1 2a 03 1b 30 0b 2a f8 7b 33 b0 43 3d ...*..0 .*.{3.C=
00a0 cd c0 01 0b 0b 00 00 00 00 ff ff ........ ...
==
0000 00 00 00 01 00 00 02 ba 3c 21 44 4f 43 54 59 50 ........ <!DOCTYP
0010 45 20 68 74 6d 6c 3e 0a 3c 68 74 6d 6c 3e 0a 20 E html>. <html>.
0020 20 3c 68 65 61 64 3e 0a 20 20 20 20 3c 6c 69 6e <head>. <lin
0030 6b 20 72 65 6c 3d 69 63 6f 6e 20 74 79 70 65 3d k rel=ic on type=
0040 69 6d 61 67 65 2f 70 6e 67 20 68 72 65 66 3d 22 image/pn g href="
0050 66 61 76 69 63 6f 6e 2e 70 6e 67 22 20 2f 3e 0a favicon. png" />.
...
That second packet is a SPDY DATA frame, but with uncompressed data. It would certainly be nice if the web page were compressed—something else to investigate.

Unraveling the first packet next to its spec, I see that it is a SYN_REPLY:
               +----------------------------------+       
80 02 00 02 |1| 1 | 2 |
+----------------------------------+
00 00 00 a3 | Flags (8) | Length (24 bits) |
+----------------------------------+
00 00 00 01 |X| Stream-ID (31bits) |
+----------------------------------+
00 00 78 bb | Unused | |
+---------------- |
df a2 51 b2 | Name/value header block |
62 e0 64 e0 | ... |
42 c4 10 03
57 76 6a 6a
...
To see what the Name/value header block in that packet is, I drop down to the node.js REPL:
var context = new ZLibContext(flatDict);

var octets_1 = [
0x78, 0xbb,
0xdf, 0xa2, 0x51, 0xb2, 0x62, 0xe0, 0x64, 0xe0, 0x42, 0xc4, 0x10, 0x03, 0x57, 0x76, 0x6a, 0x6a,
0x81, 0x6e, 0x62, 0x4e, 0x66, 0x59, 0x2a, 0x03, 0x1f, 0x6a, 0x90, 0x33, 0x30, 0x9b, 0x59, 0x5a,
0x30, 0xf0, 0xa2, 0xc4, 0x2d, 0x83, 0x20, 0xc4, 0x1d, 0x3a, 0x0a, 0x50, 0x97, 0xd8, 0x1a, 0x30,
0xf0, 0xa2, 0x04, 0x2e, 0x83, 0x2c, 0x30, 0xc0, 0x74, 0x14, 0x0c, 0x4d, 0x14, 0x80, 0xc1, 0xa3,
0x00, 0xcc, 0x0b, 0x86, 0x0a, 0x06, 0x46, 0x56, 0xc6, 0x66, 0x56, 0x40, 0x11, 0x77, 0xdf, 0x10,
0x06, 0x16, 0x50, 0xac, 0x30, 0x08, 0x2b, 0x01, 0xcd, 0xd6, 0x35, 0x04, 0xe5, 0x04, 0x60, 0xaa,
0x07, 0x65, 0x04, 0x03, 0x25, 0x06, 0x1e, 0xe4, 0xc8, 0x63, 0x90, 0x80, 0x87, 0x9f, 0xb5, 0x02,
0xcc, 0xbf, 0xa1, 0x21, 0x6e, 0xba, 0x40, 0x27, 0xa1, 0xa4, 0x77, 0x06, 0xd6, 0xa4, 0xca, 0x12,
0x20, 0xc5, 0x06, 0xf1, 0x2a, 0x03, 0x1b, 0x30, 0x0b, 0x2a, 0xf8, 0x7b, 0x33, 0xb0, 0x43, 0x3d,
0xcd, 0xc0, 0x01, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff
];

var d1 = new Buffer(octets_1);
var u1 = context.inflate(d1);
u1.toString();
'\u0000\t\u0000\nconnection\u0000\nkeep-alive\u0000\u000econtent-length\u0000\u0003698\u0000\rcache-control\u0000\u0011public, max-age=0\u0000\rlast-modified\u0000\u001dSat, 14 May 2011 02:36:14 GMT\u0000\u0004etag\u0000\u0013"698-1305340574000"\u0000\fcontent-type\u0000\u0018text/html; charset=UTF-8\u0000\raccept-ranges\u0000\u0005bytes\u0000\u0006status\u0000\u0006200 OK\u0000\u0007version\u0000\bHTTP/1.1'
Those are normal HTTP headers for the following DATA response.

The next response packet is another SYN_REPLY:
««« response
65 7.078185 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 02 00 00 00 22 00 00 00 03 00 00 22 c5 ......."......".
0010 eb c6 26 e6 34 f3 3a d0 6c fc 5e 17 07 7b 3d b9 ..&.4.:.l.^..{=.
0020 b8 98 5a 3e 07 00 00 00 ff ff ..Z>......
Running that through node (and re-using the zlib context for this stream), I find that this SYN_REPLY is for the stylesheet:
var octets_2 = [
0x22, 0xc5,
0xeb, 0xc6, 0x26, 0xe6, 0x34, 0xf3, 0x3a, 0xd0, 0x6c, 0xfc, 0x5e, 0x17, 0x07, 0x7b, 0x3d, 0xb9,
0xb8, 0x98, 0x5a, 0x3e, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff
];

var d2 = new Buffer(octets_2);
var u2 = context.inflate(d2);
u2.toString();
'\u0000\t\u0000\nconnection\u0000\nkeep-alive\u0000\u000econtent-length\u0000\u0003347\u0000\rcache-control\u0000\u0011public, max-age=0\u0000\rlast-modified\u0000\u001dSat, 14 May 2011 02:36:14 GMT\u0000\u0004etag\u0000\u0013"347-1305340574000"\u0000\fcontent-type\u0000\u0017text/css; charset=UTF-8\u0000\raccept-ranges\u0000\u0005bytes\u0000\u0006status\u0000\u0006200 OK\u0000\u0007version\u0000\bHTTP/1.1'
The response packet that immediately follows the CSS header is:
««« response
67 7.108609 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic
0000 00 00 00 03 00 00 01 5b 62 6f 64 79 20 7b 0a 20 .......[body {.
0010 20 70 61 64 64 69 6e 67 3a 20 30 3b 0a 20 20 6d padding: 0;. m
0020 61 72 67 69 6e 3a 20 30 3b 0a 7d 0a 0a 73 65 63 argin: 0;.}..sec
0030 74 69 6f 6e 23 6d 61 69 6e 20 7b 0a 20 20 6d 61 tion#main {. ma
0040 72 67 69 6e 3a 20 30 20 61 75 74 6f 3b 0a 20 20 rgin: 0 auto;.
0050 6d 61 78 2d 77 69 64 74 68 3a 20 36 30 30 70 78 max-width: 600px
0060 3b 0a 20 20 74 65 78 74 2d 61 6c 69 67 6e 3a 20 ;. text-align:
0070 63 65 6e 74 65 72 3b 0a 20 20 62 61 63 6b 67 72 center;. backgr
0080 6f 75 6e 64 3a 20 75 72 6c 28 73 70 64 79 2e 6a ound: url(spdy.j
0090 70 67 29 20 6e 6f 2d 72 65 70 65 61 74 20 35 30 pg) no-repeat 50
00a0 25 20 35 30 25 3b 0a 20 20 68 65 69 67 68 74 3a % 50%;. height:
00b0 20 33 30 30 70 78 3b 0a 7d 0a 0a 73 65 63 74 69 300px;.}..secti
00c0 6f 6e 23 6d 61 69 6e 20 68 31 2e 74 69 74 6c 65 on#main h1.title
00d0 20 7b 0a 20 20 63 6f 6c 6f 72 3a 20 23 33 33 33 {. color: #333
00e0 3b 0a 7d 0a 0a 73 65 63 74 69 6f 6e 23 6d 61 69 ;.}..section#mai
00f0 6e 20 64 69 76 23 63 6f 6e 74 65 6e 74 20 7b 0a n div#content {.
0100 20 20 74 65 78 74 2d 73 68 61 64 6f 77 3a 20 30 text-shadow: 0
0110 20 30 20 35 70 78 20 72 67 62 61 28 30 2c 30 2c 0 5px rgba(0,0,
0120 30 2c 30 2e 33 29 3b 0a 20 20 66 6f 6e 74 2d 73 0,0.3);. font-s
0130 69 7a 65 3a 20 32 35 70 78 3b 0a 20 20 62 61 63 ize: 25px;. bac
0140 6b 67 72 6f 75 6e 64 3a 20 72 67 62 61 28 32 35 kground: rgba(25
0150 35 2c 32 35 35 2c 32 35 35 2c 30 2e 36 29 3b 0a 5,255,255,0.6);.
0160 7d 0a 0a }..
==
0000 00 00 00 03 01 00 00 00 ........
... which is another uncompressed DATA response frame.

The next response packet is a SYN_REPLY:
««« response
72 7.123613 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 02 00 00 00 13 00 00 00 05 00 00 62 60 ..............b`
0010 c6 e9 73 c2 9a 01 00 00 00 ff ff ..s........
The NV frame decompresses to:
'\u0000\u0003\u0000\nconnection\u0000\nkeep-alive\u0000\u0006status\u0000\u0006200 OK\u0000\u0007version\u0000\bHTTP/1.1'
That seems intended for little more than simple keep-alive. Another something to investigate.

Next up, comes a small DATA response:
««« response
74 7.131888 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic
0000 00 00 00 05 00 00 00 12 68 65 6c 6c 6f 20 66 72 ........hello fr
0010 6f 6d 20 73 65 72 76 65 72 21 om server!
==
0000 00 00 00 05 01 00 00 00 ........
This data ends up on the banner of the sample page.

I know that it is a DATA packet because it matches up with the spec:
              +----------------------------------+
00 00 00 05 |C| Stream-ID (31bits) |
+----------------------------------+
00 00 00 12 | Flags (8) | Length (24 bits) |
+----------------------------------+
68 65 6c 6c | Data |
6f 20 66 72 +----------------------------------+
6f 6d 20 73
65 72 76 65
72 21
Similarly, the DATA_FIN:
              +----------------------------------+
00 00 00 05 |C| Stream-ID (31bits) |
+----------------------------------+
01 00 00 00 | Flags (8) | Length (24 bits) |
+----------------------------------+
| Data |
+----------------------------------+
The DATA_FIN is indicated by the flag (0x01).

Next is another SYN_REPLY frame followed by the uncompressed JPEG background image:
««« response
75 7.139855 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic
0000 80 02 00 02 00 00 00 26 00 00 00 07 00 00 22 21 .......&......"!
0010 d8 58 cd cd cc 0c 69 15 70 a2 4a 60 d3 f1 07 1d .X....i.p.J`....
0020 17 2c 8f a5 a6 93 1d 5a 00 00 00 00 ff ff .,.....Z......
==
0000 00 00 00 07 00 00 a0 00 ff d8 ff e0 00 10 4a 46 ..............JF
0010 49 46 00 01 01 00 00 01 00 01 00 00 ff fe 00 3c IF.............<
0020 43 52 45 41 54 4f 52 3a 20 67 64 2d 6a 70 65 67 CREATOR: gd-jpeg
0030 20 76 31 2e 30 20 28 75 73 69 6e 67 20 49 4a 47 v1.0 (using IJG
0040 20 4a 50 45 47 20 76 36 32 29 2c 20 71 75 61 6c JPEG v62), qual
0050 69 74 79 20 3d 20 31 30 30 0a ff db 00 43 00 01 ity = 100....C..
0060 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................
...
The NV section of the SYN_REPLY frame decompresses to the image header:
'\u0000\t\u0000\nconnection\u0000\nkeep-alive\u0000\u000econtent-length\u0000\u000576617\u0000\rcache-control\u0000\u0011public, max-age=0\u0000\rlast-modified\u0000\u001dSat, 14 May 2011 02:36:14 GMT\u0000\u0004etag\u0000\u0015"76617-1305340574000"\u0000\fcontent-type\u0000\nimage/jpeg\u0000\raccept-ranges\u0000\u0005bytes\u0000\u0006status\u0000\u0006200 OK\u0000\u0007version\u0000\bHTTP/1.1'
The next few packets are more of the JPEG image:
««« response
77 7.142581 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 f9 9d f5 7e f5 e5 08 ef aa b2 ed 7e e8 fb ec f5 ...~.......~....
0010 f5 f5 ce 3a 71 c9 f9 78 ea 33 d8 01 eb 40 ef c1 ...:q..x.3...@..
0020 e9 8e 40 c9 c8 e3 3c 1f 7c 93 c1 23 8e 32 28 1f ..@...<.|..#.2(.
0030 9e 79 1c 91 9e 79 1c e7 3d 00 e4 0e 0f 6a 5f 51 .y...y..=....j_Q
0040 cf 6c e7 39 e9 d3 8e fd f2 38 39 c7 7c d4 1b 09 .l.9.....89.|...
0050 9f 63 c7 5e 3a 72 0f a7 3c e3 18 e7 b9 ec 69 79 .c.^:r..<.....iy
...

««« response
78 7.142701 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 a9 5e 70 a3 4a 8c 5c e4 9a 4a 33 bd e0 af 81 d7 .^p.J.\..J3.....
0010 fa ae 81 69 e3 9f 1e 78 83 4b f8 4d f0 ce e1 9a ...i...x.K.M....
0020 3d 2b c4 de 22 b6 9a e3 57 f1 57 d9 fe 5b 8b 3f =+.."...W.W..[.?
0030 87 1e 08 b2 0b ad f8 ca 58 06 d4 92 fe ca 1b 4f ........X......O
0040 0c 69 f8 51 a8 6b 76 63 6a 57 b2 f8 64 78 2b 4f .i.Q.kvcjW..dx+O
0050 06 3f 82 9f 05 ed 7c 4b 35 bb 98 5b e2 87 c7 3f .?....|K5..[...?
...

««« response
79 7.147850 127.0.0.1 127.0.0.1 TLSv1 Application Data
???

««« response
81 7.150942 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP trafficContinuation or non-HTTP traffic
0000 00 00 00 07 00 00 8b 49 8f 7d 3a 73 86 9e 5d 3f .......I.}:s..]?
0010 44 32 49 8c e7 26 e2 ea ed c9 3c 96 91 fd 71 5f D2I..&....<...q_
0020 e9 3f 83 19 54 72 cf 0f b8 17 0b 18 a5 53 34 cd .?..Tr.......S4.
0030 69 e6 55 93 8a 8d e1 42 15 31 15 17 2b b3 49 62 i.U....B.1..+.Ib
0040 68 ae 64 d5 e5 2a 92 9a 56 97 31 fc 37 e2 6e 62 h.d..*..V.1.7.nb
0050 f1 dc 67 c5 b5 dc a4 fe a1 97 bc 0d 3b b7 3a 6a ..g.........;.:j
...

««« response
83 7.154903 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 c8 60 11 a3 d5 f4 bd 46 67 8f 04 82 16 e1 25 61 .`.....Fg.....%a
0010 c1 9b 19 af be 79 c1 f7 c9 38 e7 af 00 f4 e9 e8 .....y...8......
0020 07 38 f5 20 d0 54 f6 c6 38 c0 e3 f1 27 8f 4f af .8. .T..8...'.O.
0030 f4 af 57 0d 9e e7 58 3b 2c 36 6b 8e a4 96 d0 8e ..W...X;,6k.....
0040 22 a3 a6 b6 fb 0e 4d 5b 4f f3 b9 e6 57 c9 72 ac ".....M[O...W.r.
0050 4b 6e b6 5f 84 9b 77 6e 4e 8c 14 af bd ef 14 9b Kn._..wnN.......
...

««« response
85 7.188625 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 00 00 00 07 01 00 00 00 ........
The last packet is a DATA_FIN. Also included in there is a non-decrypted packet. I am unsure about that one. It originates from the example node-spdy server (the SRC port is 8081), but I am hard pressed to explain why Wireshark is unable to decrypt it. Another mystery.

The last packets are the header for the favicon:
««« response
88 7.295411 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 80 02 00 02 00 00 00 23 00 00 00 09 00 00 22 c1 .......#......".
0010 c3 2c 46 a6 16 46 34 f2 af 88 12 c8 70 fc de e5 .,F..F4.....p...
0020 84 97 2d 64 fb 16 00 00 00 ff ff ..-d.......
This decompresses to:
'\u0000\t\u0000\nconnection\u0000\nkeep-alive\u0000\u000econtent-length\u0000\u00042582\u0000\rcache-control\u0000\u0011public, max-age=0\u0000\rlast-modified\u0000\u001dSat, 14 May 2011 02:36:14 GMT\u0000\u0004etag\u0000\u0014"2582-1305340574000"\u0000\fcontent-type\u0000\timage/png\u0000\raccept-ranges\u0000\u0005bytes\u0000\u0006status\u0000\u0006200 OK\u0000\u0007version\u0000\bHTTP/1.1'
Lastly, the favicon PNG itself is sent back:
««« response
90 7.296229 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 00 00 00 09 00 00 0a 16 89 50 4e 47 0d 0a 1a 0a .........PNG....
0010 00 00 00 0d 49 48 44 52 00 00 00 20 00 00 00 20 ....IHDR... ...
0020 08 06 00 00 00 73 7a 7a f4 00 00 09 dd 49 44 41 .....szz.....IDA
0030 54 58 85 c5 97 69 6c 5c d7 79 86 9f bb cc 90 33 TX...il\.y.....3
0040 1c 0e 17 91 22 29 c9 9c 11 29 4a a2 2c ca 92 2c ....")...)J.,..,
0050 59 b6 6c c9 72 e4 38 71 ea b8 46 63 48 ad 52 a3 Y.l.r.8q..FcH.R.
...

««« response
92 7.296729 127.0.0.1 127.0.0.1 HTTP Continuation or non-HTTP traffic
0000 00 00 00 09 01 00 00 00 ........
...ending with a DATA_FIN again.

And that completes the request/response. I believe that the SETTING frame is in error. I am unsure if the stream needs to be closed after each response as it is. Also, I would like to investigate compressed the DATA some. Aside from a few loose end, this is a fine stopping place for the day.


Day #28

No comments:

Post a Comment